ImageView的setImageMatrix在某些设备上可能无法正常运行(可能早于Android 4.4)

问题描述 投票:2回答:2

我尝试通过此代码在触摸事件上移动ImageView:

public class ScrollableImageView extends ImageView {
    private GestureDetectorCompat gestureDetectorCompat;

    public ScrollableImageView(Context context) {
        this(context, null);
    }

    public ScrollableImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ScrollableImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setScaleType(ScaleType.MATRIX);

        gestureDetectorCompat = new GestureDetectorCompat(context,
                new MySimpleOnGestureListener(this));
    }

    @Override
    public boolean onTouchEvent(@NonNull MotionEvent event) {
        gestureDetectorCompat.onTouchEvent(event);
        return true;
    }

    public void scroll(float distance) {
        Matrix imageMatrix = getImageMatrix();
        imageMatrix.postTranslate(distance, 0);
        setImageMatrix(imageMatrix);
        invalidate();
    }

    private static class MySimpleOnGestureListener extends GestureDetector.SimpleOnGestureListener {
        private ScrollableImageView scrollableImageView;

        public MySimpleOnGestureListener(ScrollableImageView scrollableImageView) {
            this.scrollableImageView = scrollableImageView;
        }

        @Override
        public boolean onDown(MotionEvent e) {
            Utils.log("onDown");
            return true;
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            scrollableImageView.scroll(-distanceX);
            return true;
        }
    }
}

起初,一切都在Nexus 5(Android 4.4.4和Lollipop)上运行良好。但是后来我尝试使用4.0.4(Galaxy S2)或Nexus S(4.1.1)等旧版本的Android,但都没有用。

然后经过一阵苦苦挣扎,我想出了这个解决方案,它在所有设备上都运行良好:

((现在注意,我通过本地对象来跟踪ImageView的矩阵对象,而不是通过ImageView的getImageMatrix()来获取它)

public class ScrollableImageView extends ImageView {
    private GestureDetectorCompat gestureDetectorCompat;
    private Matrix imageMatrix;

    public ScrollableImageView(Context context) {
        this(context, null);
    }

    public ScrollableImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ScrollableImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setScaleType(ScaleType.MATRIX);

        imageMatrix = new Matrix();

        gestureDetectorCompat = new GestureDetectorCompat(context,
                new MySimpleOnGestureListener(this));
    }

    @Override
    public boolean onTouchEvent(@NonNull MotionEvent event) {
        gestureDetectorCompat.onTouchEvent(event);
        return true;
    }

    public void scroll(float distance) {
        imageMatrix.postTranslate(distance, 0);
        setImageMatrix(imageMatrix);
        invalidate();
    }

    private static class MySimpleOnGestureListener extends GestureDetector.SimpleOnGestureListener {
        private ScrollableImageView scrollableImageView;

        public MySimpleOnGestureListener(ScrollableImageView scrollableImageView) {
            this.scrollableImageView = scrollableImageView;
        }

        @Override
        public boolean onDown(MotionEvent e) {
            Utils.log("onDown");
            return true;
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            scrollableImageView.scroll(-distanceX);
            return true;
        }
    }
}

我有解决方案,但我仍然不明白为什么以前的代码不起作用?!

我试图进行研究,但唯一有意义的是ImageView的getImageMatrix()的文档:

返回视图的可选矩阵。这适用于视图的绘制时可绘制。如果没有矩阵,此方法将返回一个单位矩阵。不要就地更改此矩阵,而是复印件。如果要将其他矩阵应用于可绘制对象,请确保调用setImageMatrix()。

然后,我说Do not change this matrix in place but make a copy使我更加困惑,这样做的目的是什么?为什么我不能像以前的代码那样做? (获取ImageView的当前矩阵,然后应用翻译,然后按照文档所述通过setImageMatrix()进行设置)

有人请给我一些启发,这对我来说太混乱了。

android matrix imageview
2个回答
3
投票

好,伙计,我明白了!

实际上,文档很有道理。

返回视图的可选矩阵。这适用于视图的绘制时可绘制。如果没有矩阵,此方法将返回一个单位矩阵。 请不要在适当位置更改此矩阵,副本。如果要将其他矩阵应用于可绘制对象,请确保调用setImageMatrix()。

由于ics_mr1的ImageView源代码中的以下代码:

public void setImageMatrix(Matrix matrix) {
    // collaps null and identity to just null
    if (matrix != null && matrix.isIdentity()) {
        matrix = null;
    }

    // don't invalidate unless we're actually changing our matrix
    if (matrix == null && !mMatrix.isIdentity() ||
            matrix != null && !mMatrix.equals(matrix)) {
        mMatrix.set(matrix);
        configureBounds();
        invalidate();
    }
}

所以,如果我喜欢:

   Matrix imageMatrix = getImageMatrix();
   imageMatrix.postTranslate(distance, 0);
   setImageMatrix(imageMatrix);

[matrix != null && !mMatrix.equals(matrix)将为false,因为我重用了相同的Matrix对象(这就是文档说为Do not change this matrix in place but make a copy的原因,所以什么都不会发生,因为没有满足任何条件。]]

然后,我想出了一个非常优雅的解决方案:

   Matrix imageMatrix = new Matrix(getImageMatrix());
   imageMatrix.postTranslate(distance, 0);
   setImageMatrix(imageMatrix);

就是这样YIKES


0
投票

我尝试了几次,但都没用-

© www.soinside.com 2019 - 2024. All rights reserved.