Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle touch event for child view in parent view

I'm making a custom calendar view which extends LinearLayout and has child views for each date. What I want to do is handling swipe and click, as you can imagine, swipe is for changing month and click is for selecting a date and showing new activity. To do this, I use GestureDetector on CalendarView and could make it work for swipe. But to handle click event, I have no idea how to find a child view which click happened.

  1. Does anyone have any idea to resolve this?
  2. What's the difference between return true and false on OnScroll(MotionEvent)?

Below is part of my codes.

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;
    }

    ....
}
like image 745
genki98 Avatar asked Nov 09 '22 05:11

genki98


1 Answers

The boolean return value of on[GestureEvent] callbacks indicates whether or not the callback function consumed the event. That is, in your onScroll implementation you would return true, because you are handling these events.

However, onSingleTapUp should return false to indicate that you want the event to be passed on to the child views.

You should then register an OnClickListener that is able to handle the actual date for each child view in:

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);
    }
}

With an OnclickListener implementation like

class DateOnClickListner(Date date) extends View.OnClickListener {
    public void onClick(View v) {
        ...
    }
}
like image 115
Sascha Kolberg Avatar answered Nov 14 '22 21:11

Sascha Kolberg