当覆盖ViewGroup的“getChildStaticTransformation”方法或使用变换函数如
setRotationY()
、
setScaleX()
、
setTranslationY()
、
getMatrix()
(从API 11可用)时,只会影响渲染矩阵,因此您自定义的子视图将返回远离子视图绘制位置的边界“Rects”。大多数情况下,这不是问题,但当您开始点击时,问题就出现了。以下是我解决该问题的方法。我相信可能有更好的方法,但由于在这个主题上我没找到太多东西,所以这里是我的方法。
在ViewGroup中进行重载:
public interface Itransformable {
public void setTransformationMatrix(Matrix trsMatrix);
}
@Override
protected boolean getChildStaticTransformation(View child, Transformation t) {
if (child instanceof Itransformable){
t.clear();
t.setTransformationType(Transformation.TYPE_MATRIX);
...
...
((Itransformable)child).setTransformationMatrix(t.getMatrix());
return true;
} else {
return false;
}
}
这是自定义视图的子视图:
请注意,我没有直接在自定义视图中存储变换矩阵,而是存储了变换后的矩形。如果您想要存储矩阵(例如以后进行点之类的转换),则可能需要克隆它,因为矩阵会以某种奇怪的方式被更改,例如回收等。
public class MyCustomView extends View implements MyViewGroup.Itransformable{
private Rect mViewRect = null;
public void setTransformationMatrix(Matrix trsMatrix){
if (trsMatrix!=null){
RectF rect = new RectF();
rect.top = 0;
rect.bottom = (float) this.getHeight();
rect.left = 0;
rect.right = (float) this.getWidth();
trsMatrix.mapRect(rect);
rect.offset((float) this.getLeft(), (float) this.getTop());
if (mViewRect == null) mViewRect = new Rect();
rect.round(mViewRect);
}
}
public Rect getTransformatedRect() {
if (mViewRect!=null){
if(getRight() < 0 || getLeft() > mParentWidth){
return new Rect(getLeft(),getTop(),getRight(),getBottom());
} else {
return mViewRect;
}
} else {
return new Rect(getLeft(),getTop(),getRight(),getBottom());
}
}
@Override
public void getHitRect(Rect outRect){
if (mViewRect == null){
super.getHitRect(outRect);
} else {
outRect.set(getTransformatedRect());
}
}
getHitRect()
不会自动调用。为了增加对使用 SDK < 4.0 的项目的兼容性,即使不完美,也可以在父级上使用isTransformedTouchPointInView()
。 - olivier_sdg