2015-09-05 3 views
4

Я создаю пользовательский вид календаря, который расширяет LinearLayout и имеет дочерние представления для каждой даты. То, что я хочу сделать, - это обработать салфетки и щелкнуть, как вы можете себе представить, проведите пальцем по изменению месяца и нажмите для выбора даты и отображения новой активности. Для этого я использую GestureDetector для CalendarView и могу заставить его работать для прокрутки. Но для обработки события click я не знаю, как найти дочерний вид, который нажал.Как обработать событие касания для дочернего представления в родительском представлении

  1. У кого-нибудь есть идея решить эту проблему?
  2. В чем разница между return true и false на OnScroll (MotionEvent)?

Ниже приведена часть моих кодов.

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

    .... 
} 

ответ

0

Я решил это, перекрывая «onInterceptTouchEvent() 'на MonthView, и опубликовать решение, чтобы помочь кому-то, кто будет бороться с той же проблемой. Я применил 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; 
} 
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) { 
     ... 
    } 
} 
+0

Спасибо за совет, но на самом деле это, кажется, очень похожи с моими оригинальными кодами, которые я пытался использовать onTouchEvent() на экране календаря и OnClick() по мнению ребенка. Однако это не сработало, как я ожидал, когда движение началось с детского просмотра. Поскольку дочернее представление потребляет OnDown Event методом onClick() обратного вызова. Вот почему я решил использовать GestureDetector для просмотра календаря, чтобы обрабатывать салфетки и клики. – user3110409

Смежные вопросы