如何在父视图中处理子视图的触摸事件

时间:2015-09-05 08:13:18

标签: android click swipe ontouchevent gesturedetector

我制作了一个自定义日历视图,该视图扩展了LinearLayout并为每个日期提供了子视图。我想要做的是处理滑动和点击,你可以想象,滑动用于更改月份,点击用于选择日期和显示新活动。为此,我在CalendarView上使用GestureDetector,可以使其适用于滑动。但是为了处理点击事件,我不知道如何找到发生点击的子视图。

  1. 有没有人有任何想法解决这个问题?
  2. OnScroll(MotionEvent)上返回true和false的区别是什么?
  3. 以下是我的代码的一部分。

    public class MonthView extends LinearLayout implements GestureDetector.OnGestureListener {
    
        public MonthView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            gestureDetector = new GestureDetector(this);
            initDateViews();
        }
    
        //other codes here
        ....
    
        private void initDateViews() {
            for(int i = 0; i < 42; i++) {
                DateView view = new DateView();
                //init date views and add to calendar view.
                ....
                calendar.Add(view);
            }
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            Logger.debug(TAG, ">>> MonthView.onTouchEvent()");
    
            return gestureDetector.onTouchEvent(event);
        }
    
        @Override
        public boolean OnSingleTapUp(MotionEvent event) {
            // how can I find a child view to handle click event?
        }
    
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            // right to left
            if (e1.getX() - e2.getX() > minSwipeDistance) {
                this.prevMonth();
            }
            // left to right
            else if(e2.getX() - e1.getX() > minSwipeDistance) {
                this.nextMonth();
            }
            // bottom to top
            else if(e1.getY() - e2.getY() > minSwipeDistance) {
                this.prevMonth();
            }
            //top to bottom
            else if(e2.getY() - e1.getY() > minSwipeDistance) {
                this.nextMonth();
            }
    
            return false;
        }
    
        ....
    }
    

2 个答案:

答案 0 :(得分:1)

on[GestureEvent]回调的布尔返回值表示回调函数是否消耗了该事件。也就是说,在onScroll实现中,您将返回true,因为您正在处理这些事件。

但是,onSingleTapUp应该返回false以指示您希望将事件传递给子视图。

然后,您应该注册一个能够处理每个子视图的实际日期的OnClickListener

private void initDateViews() {
    for(int i = 0; i < 42; i++) {
        DateView view = new DateView();
        //init date views and add to calendar view.
        ....

        // register onClickListener for e.g. date
        view.setOnCLickListener(new DateOnClickListner(date))
        calendar.Add(view);
    }
}

使用OnclickListener实施,例如

class DateOnClickListner(Date date) extends View.OnClickListener {
    public void onClick(View v) {
        ...
    }
}

答案 1 :(得分:0)

我通过覆盖MonthView上的'onInterceptTouchEvent()'来解决这个问题,并发布解决方案以帮助那些会遇到同样问题的人。 我实现了GestureDetector来改变'onFling()'上的月份,就像下面的代码一样。

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    boolean result = gestureDetector.onTouchEvent(event);

    return result;
}

@Override
public boolean onDown(MotionEvent e) {
    return false;
}

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
    // right to left
    if (e1.getX() - e2.getX() > minSwipeDistance) {
        nextMonth();
    }
    // left to right
    else if(e2.getX() - e1.getX() > minSwipeDistance) {
        prevMonth();
    }
    // bottom to top
    else if(e1.getY() - e2.getY() > minSwipeDistance) {
        nextMonth();
    }
    //top to bottom
    else if(e2.getY() - e1.getY() > minSwipeDistance) {
        prevMonth();
    }

    return true;
}

@Override
public void onLongPress(MotionEvent e) {
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
    return false;
}

@Override
public void onShowPress(MotionEvent e) {
}

@Override
public boolean onSingleTapUp(MotionEvent e) {
    return false;
}