我怎样才能限制我的帆布的翻译matrix?

所以我扩展了一个自定义的SurfaceView并试图使它具有捏缩放和滚动function。

我如何滚动:

  @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)比例值正确。

全球使用的字段:

  • drawWdrawH = float ,scale = 1时canvas数据的大小(以像素为单位)。
  • parentWparentH = float ,可见视图的大小(以像素为单位)。
  • matrix = android.graphics.Matrix

问题是“ rebound() ”(也许需要一个更好的名字,嘿)我试图实现的方法会自动强制内容保持在视图中。

我尝试了各种方法来尝试计算边界应该在哪里(在矩形(0,0,parentW,parentH)内),并将matrix“返回”时转换太远。

这是我目前所拥有的,这肯定是行不通的,反而把它向右推进了很多。 我觉得问题是我的math,而不是我的想法。 有人可以拿出更简单或更干净的代码,如果它的太远和/或解决我的尝试在这个实施的问题解决matrix到边缘? 如果检查用于使其出现在左上angular

 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); } 

在matrix之前写的以前的版本是一个字段(我只是使用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()

更新 :我改变了现在的方法。 它只起到一些作用,仍然限制y方向偏离中心,改变缩放级别后错误。 我也做了“preScale”和“postTranslate”,所以(据我所知)应该总是应用这个尺度,然后是翻译而不是混合它们。

最后更新 :现在起作用。 这里有一个工作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); } 

它否定了任何我不想将其翻译回界限的滚动。 如果内容太小,则完全否定滚动,从而迫使内容位于左上angular。

Solutions Collecting From Web of "我怎样才能限制我的帆布的翻译matrix?"

我实现了像这样的东西来滚动我自己捏缩放。 我怀疑你的y轴偏离中心的问题可能是视图不是全屏大小,或者你可能不会改变坐标来匹配比例。

我的实现计算比例因子,并将其应用于:canvas.scale(pinchZoomScale,pinchZoomScale); 然后以像素为单位计算屏幕的物理尺寸,将其转换为米,最后应用缩放因子,以便所有绘制的对象都能正确偏移。

这个实现依赖于总是知道什么应该在屏幕的中心,并locking它,无论缩放级别。