首页 > 解决方案 > 在自定义布局中平移、翻转、缩放和更正边框

问题描述

你好!感谢您的阅读。

我一直在寻找正确创建一定大小(用户屏幕的 5 倍)的多方向可滚动Android 布局的方法,该布局可以被投掷(&平移)并且也可以被放大

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

显然,我在网上找到了很多答案,可以通过不同的方式来整合它。最初,我正准备发布迄今为止我尝试过的所有不同的集成,直到我遇到了Oded 的解决方案。在这一个中,所有不能正常工作的东西都起作用了。

这表示:

这是一个巨大的解脱,因为修改不同的已经制作但缺乏集成(主要修复边界+缩放问题)已经花费了几天时间。

我建议将来遇到类似问题的任何人使用此集成。

在任何情况下,都有一些问题,包括:在屏幕方向更改时返回 (0,0)、没有双击缩放和没有投掷。我认为解决这两个第一个问题并不难,但是第三个问题很成问题。我希望用户能够自由地查看这个大区域。没有投掷能力会使在应用程序中的移动速度比首选速度慢。

我已经尝试过不同的方法来做到这一点,例如使用带有 GestureDetector 的 Scroller 类、使用“Flinger”可运行类(包含 Scroller)、使用某种形式的 Choreographer 等等。

我一直无法让它工作,并且解决方案通常会完全破坏这种布局进行滚动的方式(例如,我注意到 scrollX 永远不会改变,并且不存在 scrollTo 功能(它被 mPosX 取代))。通常在这里添加 Flinging 的正确解决方案似乎无法使用,并且在某些情况下,实现会导致滚动条从应有的位置移动数千个单位。

是我的 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;
}

非常感谢您的帮助。

标签: javaandroidscrollscrollview

解决方案


推荐阅读