在自定义布局中平移,平移,缩放和校正边框

时间:2018-07-31 22:06:41

标签: java android scroll scrollview

你好!谢谢您的阅读。

我一直在寻找正确创建特定尺寸(用户屏幕尺寸的5倍)的多向可滚动 Android布局的方法。 猛冲(和平移),也可以放大

要注意,让孩子(ConstraintLayout)成为所需大小(用户屏幕的5倍)不是不是问题。

很明显,我在网上找到了很多答案,以了解如何通过不同的方式来实现此目的。最初,我将发布迄今为止尚未尝试的所有不同集成,直到遇到 Oded's solution 。在这一过程中,所有无法正常工作的事物都可以正常工作。

这意味着:

  • 布局允许滚动子级的整个宽度和高度,但不能再滚动
  • 可滚动区域的边界/边界可以通过Zooming正确缩放(这是最重要的事情,几乎没有自定义布局可以做到)
  • 可以平移布局
  • 枢轴点正确(在中间)。

这是一个极大的解脱,因为修改不同的已完成但缺乏集成(主要用于解决边界和缩放问题)的工作已经花费了几天。

我建议以后遇到类似问题的任何人都可以使用此集成。

在任何情况下,都存在一些问题,包括:屏幕方向更改后返回(0,0),无两次轻按缩放和无晃动。我认为要解决前两个问题并不困难,但是,这第三个问题很成问题。我希望用户能够自由查看这个大区域。没有能力,将使应用程序的移动速度慢于可取的速度。

我已经尝试了不同的方法,例如,将Scroller类与GestureDetector一起使用,使用“ Flinger”可运行类(包含Scroller),使用某种形式的Choreographer,等等。

我一直无法使其正常工作,解决方案通常会完全破坏此布局进行滚动的方式(例如,我注意到scrollX从未改变,并且没有scrollTo函数存在(由mPosX替换)。通常,在这里似乎无法使用添加Flinging的正确解决方案,并且在某些情况下,实现使滚动条从应有的位置移动了数千个单位。

Here是我对Odid解决方案的备份,唯一的更改是为避免Android Studio警告而进行的细微调整。

摘要(必填):

@Override
public boolean onTouchEvent(MotionEvent ev) {
    mOnTouchEventWorkingArray[0] = ev.getX();
    mOnTouchEventWorkingArray[1] = ev.getY();

    mOnTouchEventWorkingArray = scaledPointsToScreenPoints(mOnTouchEventWorkingArray);

    ev.setLocation(mOnTouchEventWorkingArray[0], mOnTouchEventWorkingArray[1]);
    mScaleDetector.onTouchEvent(ev);

    final int action = ev.getAction();
    switch (action & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN: {
            final float x = ev.getX();
            final float y = ev.getY();

            mLastTouchX = x;
            mLastTouchY = y;

            // Save the ID of this pointer
            mActivePointerId = ev.getPointerId(0);
            break;
        }

        case MotionEvent.ACTION_MOVE: {
            // Find the index of the active pointer and fetch its position
            final int pointerIndex = ev.findPointerIndex(mActivePointerId);
            final float x = ev.getX(pointerIndex);
            final float y = ev.getY(pointerIndex);

            if (mIsScaling && ev.getPointerCount() == 1) {
                // Don't move during a QuickScale.
                mLastTouchX = x;
                mLastTouchY = y;

                break;
            }

            float dx = x - mLastTouchX;
            float dy = y - mLastTouchY;

            float[] topLeft = {0f, 0f};
            float[] bottomRight = {getWidth(), getHeight()};
            /*
             * Corners of the view in screen coordinates, so dx/dy should not be allowed to
             * push these beyond the canvas bounds.
             */
            float[] scaledTopLeft = screenPointsToScaledPoints(topLeft);
            float[] scaledBottomRight = screenPointsToScaledPoints(bottomRight);

            dx = Math.min(Math.max(dx, scaledBottomRight[0] - mCanvasWidth), scaledTopLeft[0]);
            dy = Math.min(Math.max(dy, scaledBottomRight[1] - mCanvasHeight), scaledTopLeft[1]);

            mPosX += dx;
            mPosY += dy;

            mTranslateMatrix.preTranslate(dx, dy);
            mTranslateMatrix.invert(mTranslateMatrixInverse);

            mLastTouchX = x;
            mLastTouchY = y;

            invalidate();
            break;
        }

        case MotionEvent.ACTION_UP: {
            mActivePointerId = INVALID_POINTER_ID;
            break;
        }

        case MotionEvent.ACTION_CANCEL: {
            mActivePointerId = INVALID_POINTER_ID;
            break;
        }

        case MotionEvent.ACTION_POINTER_UP: {
            // Extract the index of the pointer that left the touch sensor
            final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
            final int pointerId = ev.getPointerId(pointerIndex);
            if (pointerId == mActivePointerId) {
                // This was our active pointer going up. Choose a new
                // active pointer and adjust accordingly.
                final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                mLastTouchX = ev.getX(newPointerIndex);
                mLastTouchY = ev.getY(newPointerIndex);
                mActivePointerId = ev.getPointerId(newPointerIndex);
            }
            break;
        }
    }
    return true;
}

非常感谢您的帮助。

0 个答案:

没有答案