2017-05-12 1 views
1

J'ai donc la structure de vue suivant:Android: geste tactile Intercept manipulation du parent à la vue des enfants

  • LinearLayout
    • HorizontalScrollView
    • Autres images enfant

Le parent linearLayout est cliquable a un sélecteur personnalisé (c change de couleur lorsqu'il est pressé). Je veux être en mesure de toucher le HorizontalScrollView dans LinearLayout et toujours gérer le toucher dans le LinearLayout tant qu'il ne s'agit pas d'un mouvement de défilement. Si je fais un mouvement de défilement, HorizontalScrollView doit intercepter le mouvement et annuler le contact pour LinearLayout. Fondamentalement, je veux être capable d'intercepter le geste d'une vue enfant par opposition au parent qui est la norme.

J'ai essayé de gérer la MotionEvent manuellement en créant des classes d'extension effectuer les opérations suivantes:

LinearLayout

public override bool OnInterceptTouchEvent(MotionEvent ev) 
{ 
    // Handle the motion event even if a child returned true for OnTouchEvent 
    base.OnTouchEvent(ev); 
    return base.OnInterceptTouchEvent(ev); 
} 

HorizontalScrollView

public override bool OnTouchEvent(MotionEvent e) 
{ 
    if (e.Action == MotionEventActions.Down) 
    { 
     _intialXPos = e.GetX(); 
    } 

    if (e.Action == MotionEventActions.Move) 
    { 
     float xDifference = Math.Abs(e.GetX() - _intialXPos); 
     if (xDifference > _touchSlop) 
     { 
      // Prevent the parent OnInterceptTouchEvent from being called, thus it will no longer be able to handle motion events for this gesture 
      Parent.RequestDisallowInterceptTouchEvent(true); 
     } 
    } 

    return base.OnTouchEvent(e); 
} 

Ce presque fonctionné. Lorsque je touche le HorizontalScrollView, le LinearLayout montre l'état de l'interface enfoncé et s'active lorsque le clic est terminé. Si je touche et défile le HorizontalScrollView alors le défilement fonctionne. Lorsque je lâche le parchemin, le gestionnaire de clic pour le LinearLayout ne se déclenche pas parce qu'il a été intercepté. Mais le problème est que avant de commencer à faire défiler les changements LinearLayout à l'état pressé et il ne se réinitialise pas même après que le geste est terminé. Dans ma tentative supplémentaire d'essayer d'annuler manuellement le geste pour le LinearLayout j'ai continué à rencontrer d'autres problèmes. De plus, le LinearyLayout a d'autres boutons à l'intérieur qui, lorsqu'il est cliqué, ne doit pas permettre à LinearLayout parent d'afficher l'état enfoncé. Aucune suggestion? Existe-t-il un modèle défini pour intercepter les événements tactiles d'un enfant? Je suis sûr que c'est possible si les deux classes se connaissent, mais j'essaie d'éviter de les coupler.

Répondre

0

Les travaux suivants pour moi dans tous les cas:

InterceptableLinearLayout

public override bool DispatchTouchEvent(MotionEvent e) 
{ 
    bool dispatched = base.DispatchTouchEvent(e); 
    // Handle the motion event even if a child returns true in OnTouchEvent 
    // The MotionEvent may have been canceled by the child view 
    base.OnTouchEvent(e); 

    return dispatched; 
} 

public override bool OnTouchEvent(MotionEvent e) 
{ 
    // We are calling OnTouchEvent manually, if OnTouchEvent propagates back to this layout do nothing as it was already handled. 
    return true; 
} 

InterceptCapableChildView

public override bool OnTouchEvent(MotionEvent e) 
{ 
    bool handledTouch = base.OnTouchEvent(e); 

    if ([Meets Condition to Intercept Gesture]) 
    { 
     // If we are inside an interceptable viewgroup, intercept the motionevent by sending the cancel action to the parent 
     e.Action = MotionEventActions.Cancel; 
    } 

    return handledTouch; 
}