所以我擴展自定義SurfaceView
,並試圖讓它具有捏縮放和滾動功能。如何限制我的畫布的平移矩陣?
我怎麼滾動:
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
// subtract scrolled amount
matrix.postTranslate(-distanceX, -distanceY);
rebound();
invalidate();
// handled
return true;
}
我怎麼放大:
@Override
public boolean onScale(ScaleGestureDetector detector) {
if (detector.isInProgress()) {
// get scale
float factor = detector.getScaleFactor();
// Don't let the object get too small or too large.
if (factor * scale > 1f) {
factor = 1f/scale;
} else if (factor * scale < minScale) {
factor = minScale/scale;
}
// store local scale
scale *= factor;
// do the scale
matrix.preScale(factor, factor, detector.getFocusX(), detector.getFocusY());
rebound();
invalidate();
}
return true;
}
(僅供參考我使用此代碼爲onDraw
:)
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.setMatrix(matrix);
// [...] stuff drawn with matrix settings
canvas.restore();
// [...] stuff drawn without matrix settings, as an overlay
}
目前這兩種方法是運作良好。縮放停止在最小值(0f和1f之間)和最大值(當前總是1f)的比例值。使用
全局字段:
drawW
,drawH
=float
,其大小在中規模畫布數據的像素= 1parentW
,parentH
=float
,在可見視圖的像素的尺寸。matrix
=android.graphics.Matrix
。
的問題是「rebound()
」(也許需要一個更好的名字,嘿嘿)方法我試圖實施將自動強制的內容留在視圖中。
我嘗試過各種方法來嘗試計算邊界應該在哪裏(在矩形(0,0,parentW,parentH)內),並且在矩陣變得太遠時將其轉換回來。
這是我現在擁有的東西,絕對不行,反而把它推向更遠的地方。我覺得問題是我的數學問題,而不是我的想法。 有人可以提出更簡單或更乾淨的代碼,如果它的太遠和/或解決我的嘗試在這個實現的問題解決矩陣到邊緣?的,如果用來做它出現在頂部檢查左
public void rebound() {
// bounds
RectF currentBounds = new RectF(0, 0, drawW, drawH);
matrix.mapRect(currentBounds);
RectF parentBounds = new RectF(0, 0, parentW, parentH/2);
PointF diff = new PointF(0, 0);
if (currentBounds.left > parentBounds.left) {
diff.x += (parentBounds.left - currentBounds.left);
}
if (currentBounds.top > parentBounds.top) {
diff.y += (parentBounds.top - currentBounds.top);
}
if (currentBounds.width() > parentBounds.width()) {
if (currentBounds.right < parentBounds.right) {
diff.x += (parentBounds.right - currentBounds.right);
}
if (currentBounds.bottom < parentBounds.bottom) {
diff.y += (parentBounds.bottom - currentBounds.bottom);
}
}
matrix.postTranslate(diff.x, diff.y);
}
先前的版本,我寫的矩陣是一個前場(我只是用canvas.scale()
然後onDraw
canvas.translate()
),其工作:
public void rebound() {
// bounds
int boundTop = 0;
int boundLeft = 0;
int boundRight = (int)(-scale * drawW + parentW);
int boundBottom = (int)(-scale * drawH + parentH);
if (boundLeft >= boundRight) {
mScrollX = Math.min(boundLeft, Math.max(boundRight, mScrollX));
} else {
mScrollX = 0;
}
if (boundTop >= boundBottom) {
mScrollY = Math.min(boundTop, Math.max(boundBottom, mScrollY));
} else {
mScrollY = 0;
}
}
我正在使用新方法,以便我可以正確縮放以detector.getFocusX()
,detector.getFocusY()
爲中心。
UPDATE:我改變了現在的方法。它只起作用,仍然限制y方向偏離中心,並且在改變縮放級別後錯誤。我也做了「preScale」和「postTranslate」,這樣(據我瞭解),它應該始終應用縮放比例,而不是混合它們。
FINAL UPDATE:現在可以使用。這裏有一個工作rebound
方法與評論:
public void rebound() {
// make a rectangle representing what our current canvas looks like
RectF currentBounds = new RectF(0, 0, drawW, drawH);
matrix.mapRect(currentBounds);
// make a rectangle representing the scroll bounds
RectF areaBounds = new RectF((float) getLeft(),
(float) getTop(),
(float) parentW + (float) getLeft(),
(float) parentH + (float) getTop());
// the difference between the current rectangle and the rectangle we want
PointF diff = new PointF(0f, 0f);
// x-direction
if (currentBounds.width() > areaBounds.width()) {
// allow scrolling only if the amount of content is too wide at this scale
if (currentBounds.left > areaBounds.left) {
// stop from scrolling too far left
diff.x = (areaBounds.left - currentBounds.left);
}
if (currentBounds.right < areaBounds.right) {
// stop from scrolling too far right
diff.x = (areaBounds.right - currentBounds.right);
}
} else {
// negate any scrolling
diff.x = (areaBounds.left - currentBounds.left);
}
// y-direction
if (currentBounds.height() > areaBounds.height()) {
// allow scrolling only if the amount of content is too tall at this scale
if (currentBounds.top > areaBounds.top) {
// stop from scrolling too far above
diff.y = (areaBounds.top - currentBounds.top);
}
if (currentBounds.bottom < areaBounds.bottom) {
// stop from scrolling too far below
diff.y = (areaBounds.bottom - currentBounds.bottom);
}
} else {
// negate any scrolling
diff.y = (areaBounds.top - currentBounds.top);
}
// translate
matrix.postTranslate(diff.x, diff.y);
}
它否定了,我不通過翻譯回邊界想要的任何滾動。如果內容太小,則會完全否定滾動,從而迫使內容位於左上角。
你說得對!該視圖不是整個屏幕大小。矩陣轉換是相對於屏幕而不是畫布視圖嗎?我認爲它是最有意義的是相對於畫布而不是屏幕... – Ribose
矩陣是相對於畫布,但它錨定在位置0,0,所以倍增的比例和畫東西到5,5將使它看起來是在2.5,2.5 我發現在某些情況下,視圖大小可能會感到困惑,並嘗試使用屏幕大小作爲指導,而不是您操縱的實際視圖。花了很多試驗和錯誤才能讓我的縮放比例適合畫布上對象位置的縮放比例。 – ScouseChris
謝謝!隨着大量的試驗和錯誤,我確實得到它終於工作。 – Ribose