我试图通过以下代码在触摸事件上移动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)上运行良好。但后来我尝试使用旧版本的Android,如4.0.4(Galaxy S2)或Nexus S(4.1.1)......但这些版本都没有用。
然后经过一段时间的努力,我想出了这个解决方案,它在所有设备上运行良好:
(请注意,现在,我通过本地对象跟踪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()文档:
返回视图的可选矩阵。这适用于视图 绘制时绘制。如果没有矩阵,这个方法会 返回一个单位矩阵。不要改变这个矩阵,但要做 复印件。如果你想要一个不同的矩阵应用于drawable,be 一定要调用setImageMatrix()。
然后通过说Do not change this matrix in place but make a copy
让我更加困惑,这样做的重点是什么?为什么我不能像以前的代码那样做? (获取ImageView的当前矩阵然后应用转换,然后通过setImageMatrix()将其设置回来,如文档所述)
有人请给我一些启示,这对我来说太混乱了。
答案 0 :(得分:3)
好的,伙计们,我明白了!
实际上文档是有道理的。
返回视图的可选矩阵。这适用于视图 绘制时绘制。如果没有矩阵,这个方法会 返回一个单位矩阵。 不要更改此矩阵,但要制作 副本。如果你想要一个不同的矩阵应用于drawable,be 一定要调用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