android - personalizado - FastScroller solo vuelve al primer elemento, no a la vista de encabezado
listview android example (1)
Este es un comportamiento deliberado de FastScroller
. Cuando llama a setAdapter
en su ListView
, el adaptador se envuelve en un HeaderViewListAdapter
si hay algún conjunto de encabezados; Es por eso que debe llamar a addHeaderView
antes de setAdapter
. Luego, en el código FastScroller
, vemos:
if (adapter instanceof HeaderViewListAdapter) {
mListOffset = ((HeaderViewListAdapter)adapter).getHeadersCount();
adapter = ((HeaderViewListAdapter)adapter).getWrappedAdapter();
}
Es decir, obtener un desplazamiento y utilizar el adaptador subyacente. mListOffset
se usa luego para establecer la posición superior para desplazarse con el control rápido. Entonces, ¿dónde sucede realmente esta envoltura? Hasta, como se esperaba, ListView.addHeaderView
, donde vemos:
if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
} else {
mAdapter = adapter;
}
Así que definitivamente estamos buscando el lugar correcto. Ahora, parece que su objetivo es NO tener el comportamiento de desplazamiento para los encabezados de lista para su pulgar rápido, pero de lo contrario tener una lista normal con encabezado. Para hacer esto, es suficiente (basado en lo que hemos visto del código) para tener FastScroller.mListOffset = 0
. Esto se establece solo en getSectionsFromIndexer
, que se llama incondicionalmente en init
, y condicionalmente en varias otras funciones solo cuando mListAdapter == null
. mListAdapter
solo es nulo si se llama a onSectionsChanged
, así que ignoremos esa ruta por ahora.
Después de cavar mucho y jugar con varios ganchos de reflexión, puedo decir que no hay forma de hacerlo que sea incluso un poco compatible con el futuro. Puede utilizar la reflexión para intercambiar el HeaderViewListAdapter por uno que se encuentra en el recuento de encabezados, etc .; pero eso es bastante frágil. De manera similar, puede crear una subclase del FastScroller (paquete visible) con uno con su propio comportamiento; pero se hace referencia a mListOffset
ampliamente y no a través de un captador, por lo que es incluso más feo de lo habitual. Básicamente, se está enfrentando al hecho de que el sistema no funciona como usted desea.
Dudo en llamar a esto un error, ya que está tan claro en el código que es un comportamiento deliberado. ¿Ha considerado hacer del primer elemento de la lista solo un primer elemento especial (posiblemente usando un WrapperListAdapter
personalizado como HeaderViewListAdapter
si se desea para la contabilidad), en lugar de usar el mecanismo de encabezado?
He habilitado el desplazamiento rápido en un ListView, que tiene una vista de cabecera no seleccionable. Si se desplaza hacia abajo en la lista y arrastra el pulgar de desplazamiento rápido hacia la parte superior, la lista solo se desplaza de nuevo al primer elemento, pero no a la vista de encabezado. Arrastrando la lista, funciona como se espera.
Captura de pantalla 1: el área roja en la captura de pantalla es la vista de encabezado.
Captura de pantalla 2: si arrastra el pulgar hacia la parte superior, solo obtiene el primer elemento y la vista del encabezado aún está arriba.
ListView lv = (ListView) findViewById(R.id.listView);
lv.addHeaderView(getLayoutInflater().inflate(R.layout.view,null), null, false);
<ListView
android:layout_height="fill_parent"
android:id="@+id/listView"
android:layout_width="fill_parent"
android:fastScrollEnabled="true"
></ListView>
He creado un proyecto de demostración: https://github.com/mikegr/fastscroll-bug
¿Por qué arrastrar el pulgar no se desplaza hacia la parte superior?