viewpager example change android onclick android-listview android-fragments android-viewpager

android - example - fragmentstatepageradapter notifydatasetchanged



Android-clics retrasados en ListView (6)

En caso de que alguien se preguntara cómo resolví esto. Básicamente tuve que simplificar mis diseños. Parece que cuando se tienen estructuras complejas anidadas, los eventos pueden tardar demasiado en burbujear y si comienza a desplazar la lista al mismo tiempo, los eventos pueden desencadenar una acción incorrecta. Recorté los diseños cambiando a RelativeLayout lo más posible y eso pareció ayudar mucho.

Tengo la siguiente estructura en mi aplicación:

FragmentActivity con ViewPager contiene múltiples fragmentos administrados por FragmentStatePagerAdapter usando un paquete de compatibilidad con Android 2.1

Cada fragmento contiene ListView . Cada elemento en el ListView tiene un LinearLayout con dos TextViews y un Button . El LinearLayout y el botón tienen onClickListeners (separados). Al hacer clic en el LinearLayout inicia otra Activity . Noté que el comportamiento de los clics es muy inconsistente: a veces la acción se ejecuta inmediatamente, pero a menudo se retrasa y otras veces se ignora sin importar cuántas veces toque. Se vuelve aún más extraño porque puedo tocar y la acción solo se ejecutará cuando comience a desplazarme por la lista. setSelectable(true) varias combinaciones de setFocusable(false) y setSelectable(true) pero no parece hacer ninguna diferencia. ¿Algunas ideas? Estaré encantado de proporcionar más detalles.


Lo que funcionó para mí fue asignar un OnItemClickListener a ListView través de setOnItemClickListener , en lugar de un OnClickListener a los elementos de lista individuales. Obviamente, el botón todavía necesita su propio OnClickListener , pero no he probado ese escenario.


Me encontré con el mismo problema, pero en mi caso la solución no fue mantener las referencias a las vistas, lo que causó problemas con el almacenamiento en caché de vistas de ListView. Después de implementar correctamente el método getView() con el uso de converView, todo el comportamiento extraño con llamadas de clic perdidas / inesperadas desapareció.


No estoy seguro de si esto ayuda a alguien, pero tuve un problema similar con un TableLayout. Las soluciones anteriores no solucionaron mi problema.

Para mí el problema era: android:animateLayoutChanges="true"

La eliminación de esto permitió que los clics en mis botones dentro de mis filas de TableLayout funcionen correctamente. Luego tuve que animar mis vistas manualmente en lugar de confiar en la propiedad anterior.


Parece que está ejecutando algún proceso de bloqueo (como invocar servicios web o abrir archivos) en el hilo de eventos, por lo que su hilo de eventos está bloqueado. Si este es el caso, procese su código de bloqueo en otro hilo que no sea el Evento THread.


Tuve un problema similar y me tomó 2 días para depurarlo y resolverlo. Tengo un ListAdapter que crea varias vistas de texto en un LinearLayout para cada elemento de la lista. Cada TextView tiene su propio OnClickListener, porque necesito manejar los clics en cada elemento.

Cuando cambié la implementación para reutilizar las Vistas, OnClickListener dejó de funcionar correctamente. En 4.4.2, la mayoría de los clics funcionaron, pero a veces no hubo reacción hasta que me desplacé en la lista. En 2.3, los primeros clics no funcionarán y luego todos los clics se manejaron en una ráfaga.

En mi caso especial, creé toda la Vista en código Java y no inflando recursos. Y el punto crítico fue que establecí los LayoutParams de LinearLayout incluso cuando la vista se reutilizó (esto parece ser más seguro, luego suponiendo que la vista reutilizada tiene los parámetros de diseño correctos). ¡Cuando no configuro los LayoutParams cuando reutilizo todo funciona bien! Aquí está el código crítico:

public View getView(int position, View convertView, ViewGroup parent) { LinearLayout tapeLine = null; if (convertView != null && convertView instanceof LinearLayout && ((LinearLayout)convertView).getChildCount() == 4) tapeLine = (LinearLayout) convertView; // Reuse view else tapeLine = new LinearLayout(activity); if (convertView == null) { // Don''t set LayoutParams when reusing view ViewGroup.LayoutParams tapeLineLayoutParams = new AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); tapeLine.setLayoutParams(tapeLineLayoutParams); } ScrollingTape scrollingTape = calculatorHolder.getCalculator().getScrollingTape(); int tapeWidthPx = parent.getWidth(); TapeLineTextSizeInfo tapeLineTextSizeInfo = calculatorHolder.getTapeLineTextSizeHelper().createTapeLineTextSizeInfo(tapeWidthPx); ScrollingTapeLine line = scrollingTape.getLine(position); tapeLine.setOrientation(LinearLayout.HORIZONTAL); int tapeBackgroundColor = getBackgroundColor(line); tapeLine.setBackgroundColor(tapeBackgroundColor); addColumnViews(tapeLine, line, tapeLineTextSizeInfo); tapeLine.setTag(R.id.scrollingtapeadapter_viewtag_position, position); tapeLine.setOnLongClickListener(longClickListener); tapeLine.setOnClickListener(remainClickListener); return tapeLine; }

¿Cuál es el fondo de este extraño comportamiento de la vista de lista? Hice un poco de depuración e investigación en las fuentes de Android. Cuando Android actualiza una vista, hay dos pasos importantes en Medida y OnLayout. El método getView del ListAdapter no solo se llama para dibujar la vista sino también antes durante onMeasure. En este último caso, la vista se crea pero aún no está registrada en la cadena de eventos para manejar los eventos de clic.

Cuando una vista que se ha creado para onMeasure se reutiliza más tarde para dibujarla en la pantalla, debe registrarse desde el sistema Android para manejar los eventos de clic. Para este caso especial, los desarrolladores de Android habían hecho algo, lo que podría considerarse como un truco sucio. Se utiliza una bandera especial en los LayoutParams para decidir que la vista debe registrarse en el evento de cambio.

Ahora mi problema: al restablecer los LayoutParams también cuando se reutiliza una vista, este indicador siempre se restableció. Por lo tanto, el sistema Android no registraría la vista y los eventos no llegarían.

para resumir: cuando se vuelve a utilizar una vista en getView de un ListAdapter, no sobrescriba los LayoutParams porque mantienen información interna del sistema Android.