Android View动画运行时,在运动的View上绑定的事件将不能被触发,因为诸如点击事件等,触发点是绑定在View控件初始化时所在位置的点击,当动画移动后点击坐标就发生了改变,通过查询一些资料,了解到,Android 3.0以下,动画存在问题,它只移动了View绘制显示的地方,却没有移动View的物理位置,具体底层实现大家可以看源代码了解,我不大清楚底层,这里就不多说了,下面说说简单的解决方法。
只需继承父级布局,覆盖onTouchEvent(或者其他需要捕获的事件)。这里我以FrameLayout为例,因为要捕获点击事件,实现onTouchEvent,然后通过获取当前点击坐标计算出当前点击范围内包含的View控件,找到第一个就直接触发该View的事件,然后break,示例代码如下:
- public class ExtendFrameLayout extends FrameLayout {
-
- public ExtendFrameLayout(Context context) {
- super(context);
- }
-
- public ExtendFrameLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public ExtendFrameLayout(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- float x = event.getX();
- float y = event.getY();
- for(int i=0;i < getchildcount();i++){
- View child = getChildAt(i);
- if(child!=null){
- if (containPoint(child, x, y)) {
- Toast.makeText(getContext(), "Touch->"+x+":"+y, Toast.LENGTH_SHORT).show();
- child.performClick();
- break;
- }
- }
- }
- }
- return super.onTouchEvent(event);
- }
-
- private boolean containPoint(View view, float x, float y) {
- Transformation trans = new Transformation();
- Animation anim = view.getAnimation();
- if(anim!=null){
- anim.getTransformation(view.getDrawingTime(), trans);
- }
- Matrix matrix = trans.getMatrix();
-
- int dx = view.getLeft();
- int dy = view.getTop();
-
- x -= dx;
- y -= dy;
-
- Matrix mat = new Matrix();
- if (matrix.invert(mat)) {
- float[] pointsSrc = new float[] { x, y };
- float[] pointsEnd = new float[] { 0, 0 };
-
- mat.mapPoints(pointsEnd, pointsSrc);
-
- x = pointsEnd[0] + dx;
- y = pointsEnd[1] + dy;
- }
-
- Rect rect = new Rect();
- view.getHitRect(rect);
- return rect.contains((int) x, (int) y);
- }
- }