Android: ViewPager y HorizontalScrollVIew

Tengo un HorizontalScrollView dentro de mi ViewPager . requestDisallowInterceptTouchEvent(true); Para el HorizontalScrollView pero el ViewPager sigue interceptando eventos táctiles. ¿Hay otro comando que pueda utilizar para evitar que los padres y antepasados ​​de View intercepten eventos de toque?

Nota: el HorizontalScrollView sólo ocupa la mitad de la pantalla.

Yo tuve el mismo problema. Mi solución fue:

  1. Haga una subclase de ViewPager y agregue una propiedad llamada childId .
  2. Cree un setter para la propiedad childId y establezca el id de la HorizontalScrollView .
  3. onInterceptTouchEvent() en la subclase de ViewPager y si la propiedad childId es más de 0, obtenga ese niño y si el evento está en el campo HorizontalScrollView devuelve false.

Código

 public class CustomViewPager extends ViewPager { private int childId; public CustomViewPager(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { if (childId > 0) { View scroll = findViewById(childId); if (scroll != null) { Rect rect = new Rect(); scroll.getHitRect(rect); if (rect.contains((int) event.getX(), (int) event.getY())) { return false; } } } return super.onInterceptTouchEvent(event); } public void setChildId(int id) { this.childId = id; } } 

En el método onCreate()

 viewPager.setChildId(R.id.horizontalScrollViewId); adapter = new ViewPagerAdapter(this); viewPager.setAdapter(adapter); 

Espero que esto ayude

Gracias por la respuesta. He modificado un poco su solución y he logrado que funcione el ViewPager anidado:

 public class CustomViewPager extends ViewPager { private int childId; public CustomViewPager(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { if (childId > 0) { ViewPager pager = (ViewPager)findViewById(childId); if (pager != null) { pager.requestDisallowInterceptTouchEvent(true); } } return super.onInterceptTouchEvent(event); } public void setChildId(int id) { this.childId = id; } } 

Así pues, sé que esta pregunta es bastante vieja, pero he venido con una solución que pienso tiene algunas ventajas adicionales sobre el fijado aquí. Una situación que podría suceder es que podría tener más de un HorizontalScrollView dentro de mi ViewPager (lo que hago), y entonces tendría que proporcionar toneladas de Ids a ViewPager para que siempre se puede comprobar conflictos táctiles.

Analizé el origen del ViewPager y encontré que utilizan este método llamado "canScroll" para determinar si se puede desplazar una vista secundaria. Afortunadamente, no se hizo estático ni final, por lo que podría anularlo. Dentro de ese método que se llamó el "boolean ViewCompat.canScrollHorizontally (View, int)" (el que siempre devuelve false para SDK <14). Mi solución entonces era:

 public class CustomViewPager extends ViewPager { public CustomViewPager(Context context, AttributeSet attrs) { super(context, attrs); } public CustomViewPager(Context context) { super(context); } protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) { return super.canScroll(v, checkV, dx, x, y) || (checkV && customCanScroll(v)); } protected boolean customCanScroll(View v) { if (v instanceof HorizontalScrollView) { View hsvChild = ((HorizontalScrollView) v).getChildAt(0); if (hsvChild.getWidth() > v.getWidth()) return true; } return false; } } 

Por lo tanto, si tiene una clase diferente de Vista dentro de su ViewPager que también debe recibir trazos horizontales, simplemente cambie el CustomCanScroll (Ver) para que pueda devolver si el toque no debe ser interceptado o no.

La verificación booleana es verdadera si la vista actual también debe ser verificada para 'desplazamiento', por eso también debemos comprobarlo.

Espero que esto ayude a futuros problemas como este (o si hay una solución mejor, o una oficial de la plataforma Android, házmelo saber).

No sé si ya has resuelto el problema o no. Pero ninguna de las respuestas anteriores funciona correctamente. Así que creo que es necesario para aquellas personas que podrían buscar las soluciones con sufrimiento.

De hecho, la solución es bastante simple si se lee el documento oficial sobre el manejo de eventos táctiles en ViewGroup.

Primero usted necesita entender el uso de

ViewParent.requestDisallowInterceptTouchEvent (boolean) , Llame esto a una Vista padre para indicar que no debe interceptar eventos táctiles con onInterceptTouchEvent (MotionEvent) .

A continuación, debe interceptar los eventos y asegurarse de que el grupo de vista principal de su HorizontalScrollView no enviará los sucesos más.

Por lo tanto, establecer un OnToushListener para usted HorizontalScrollView. Detectar el toque hacia abajo y mover eventos, a continuación, establezca el requestDisallowInterceptTouchEvent (true) a su padre (ViewPager o algo más) para asegurarse de que los eventos serían manejados por el HorizontalScrollView.

Por supuesto usted podría poner estos código abajo en sus componentes de CustomHorizontalScrollView de modo que pueda ser reutilizado.

Esperando que ayude. D

 horizontalScrollView.setOnTouchListener(new View.OnTouchListener() { float rawX; int mTouchSlop = ViewConfiguration.get(getActivity()).getScaledTouchSlop(); @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: v.getParent().requestDisallowInterceptTouchEvent(true); rawX = event.getRawX(); break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: v.getParent().requestDisallowInterceptTouchEvent(false); rawX = 0f; break; case MotionEvent.ACTION_MOVE: if (Math.abs(rawX - event.getRawX()) > mTouchSlop) v.getParent().requestDisallowInterceptTouchEvent(true); break; } return false; } 

Aquí está otra solución que trabajó para mí,

Crear un ViewPager personalizado

 public class NoScrollViewPager extends ViewPager { private boolean scrollDisable = false; public NoScrollViewPager(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if(scrollDisable) { return false; } else { return super.onInterceptTouchEvent(ev); } } public void disableScroll() { scrollDisable = true; } public void enableScroll() { scrollDisable = false; } } 

A continuación, agregue OnTouchListener a su elemento, ya sea una HorizontalScrollView o Gallery o cualquier otra cosa que no desee que el viewpager se desplace cuando se toca.

 gf.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View arg0, MotionEvent ev) { switch(ev.getAction()) { case MotionEvent.ACTION_DOWN: viewPager.disableScroll(); break; case MotionEvent.ACTION_UP: viewPager.enableScroll(); break; } return false; } }); 

La solución de Fede no funcionó muy bien para mí. Mi HorizontalScrollVIew tenía áreas en las que no captó ninguna entrada (haga clic, deslice ..). Supongo que getHitRect () tiene que hacer algo con eso. Después de reemplazarlo con el siguiente código todo funcionó bien.

Es posible agregar varias vistas de HorizontalScrollVIew o cualquier otra vista que requiera también el enfoque.

 public class CustomViewPager extends ViewPager { private ArrayList<Integer> children; public CustomViewPager(Context context, AttributeSet attrs) { super(context, attrs); children = new ArrayList<Integer>(); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { if (children.size() > 0) { for(int i=0; i<children.size(); i++){ View scroll = findViewById(children.get(i)); if (scroll != null & scroll.isPressed()) { return false; } } } return super.onInterceptTouchEvent(event); } public void addChildId(int id) { children.add(id); } } 

En XML usted tendrá algo como esto:

 <form.paginator.lib.CustomViewPager android:id="@+id/pager" android:layout_width="fill_parent" android:layout_height="150dp" /> 

En el método onCreate ():

 mPager = (CustomViewPager) findViewById(R.id.pager); mPager.setAdapter(mAdapter); mPager.addChildId(R.id.avatarImageView); 

En el método OnTouchListener () para ver que ha agregado a los niños de CustomViewPager:

 case MotionEvent.ACTION_DOWN: v.setPressed(true); . . . case MotionEvent.ACTION_UP: v.setPressed(false); 

Estaba teniendo problemas con una pequeña galería de vista al pie de mi primera página en un grupo de viewpager. Al pasar el foco de la vista de galería saltaría entre mover los elementos de la galería o el viewpager.

Anular ViewPager como se indicó anteriormente y establecer requestDisallowInterceptTouchEvent resuelto mi problema. Las páginas ya no cambian al pasar la galería. Creo que es una solución importante para aquellos que utilizan galleryviews con viewpager.

Esto también funcionará para viewpager dentro de una vista de desplazamiento: https://stackoverflow.com/a/2655740/969325

Descubrí que si tienes un ViewPager en ScrollView y quieres que quede siempre en foco, cuando lo tocas y ScrollView nunca consigue un foco, esto lo hace.

  mViewPager= (ViewPager) findViewById(R.id.pager); mViewPager.setAdapter(adapter); mViewPager.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { mViewPager.getParent().requestDisallowInterceptTouchEvent(true); return false; } }); 

Después de la prueba una gran cantidad de solución, me parece esto. En MyPagerView:

 @Override public boolean onTouchEvent(MotionEvent event) { if (childId > 0) { View scroll = findViewById(childId); if (scroll != null && mGestureDetector.onTouchEvent(event)) { return false; } } return super.onTouchEvent(event); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { if (childId > 0) { HorizontalScrollView scroll = (HorizontalScrollView)findViewById(childId); if (scroll != null && mGestureDetector.onTouchEvent(event)) { return false; } } return super.onInterceptTouchEvent(event); } 

Por lo tanto, modifiqué la respuesta de Fede porque estaba desactivando el toque en la misma área en las páginas alrededor de la que quería. Además, lo hice capaz de agregar múltiples vistas porque estoy tratando con una gran cantidad de gráficos y vistas interactivas que utilizan la interactividad horizontal arrastrar / soltar. De esta manera puede agregar

 public class CustomViewPager extends ViewPager { private List<ViewFocus> lateralTouchViews = new ArrayList<>(); public CustomViewPager(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { for(int i = 0; i< lateralTouchViews.size(); i++){ View scroll = findViewById(lateralTouchViews.get(i).id); if (scroll != null && getCurrentItem() == lateralTouchViews.get(i).itemPosition) { Rect rect = new Rect(); scroll.getHitRect(rect); if (rect.contains((int) event.getX(), (int) event.getY())) { return false; } } } return super.onInterceptTouchEvent(event); } public void addConflict(int id, int pageIndex) { lateralTouchViews.add(new ViewFocus(id, pageIndex)); } public class ViewFocus{ int id; int itemPosition; public ViewFocus(int id, int itemPosition){ this.id = id; this.itemPosition = itemPosition; } } 

}

  • Restaurar vista a estado xml original
  • Android ToggleButton
  • Vista personalizada no dibujada correctamente
  • Zoom centrado en la vista personalizada - calculando las coordenadas de lienzo
  • Dibuja un círculo en una vista (android)
  • Destruir vista (disposición)
  • Método para anular cuando el diseño se destruye en Android
  • Cómo crear una vista parcialmente invisible
  • Cómo detectar si la actividad principal de la vista se está destruyendo
  • Android slide down animación
  • ¿Qué el mensaje de logcat: "E / MoreInfoHPW_ViewGroup (2905): Vista de padre no es un TextView" significa?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.