我尝试通过此代码在触摸事件上移动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()进行设置)
有人请给我一些启发,这对我来说太混乱了。
好,伙计,我明白了!
实际上,文档很有道理。
返回视图的可选矩阵。这适用于视图的绘制时可绘制。如果没有矩阵,此方法将返回一个单位矩阵。 请不要在适当位置更改此矩阵,副本。如果要将其他矩阵应用于可绘制对象,请确保调用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
我尝试了几次,但都没用-