首页 文章

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

提问于
浏览
5

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

  • 有没有人有任何想法解决这个问题?

  • OnScroll(MotionEvent)上返回true和false之间的区别是什么?

以下是我的代码的一部分 .

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

    on[GestureEvent] callbacks的布尔返回值指示回调函数是否消耗了该事件 . 也就是说,在 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

    我通过覆盖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;
    }
    

相关问题