Android: listview en listview
Estoy intentando colocar un listview dentro de un listviewitem. El listview interno no debe ser desplazable pero tomar todo el tamaño que necesita para mostrar todas sus filas. Hay una mejor manera de hacerlo? Mesa, rejilla, …? El problema que estoy enfrentando ahora es que el listview interior no toma el espacio que necesita, por lo que se corta en el final de la primera listitem. Si trato de desplazarse, sólo el listview exterior es el desplazamiento que es exactamente lo que quiero.
Gracias, mi solución final es
- Android ListView Color del texto
- ¿Hay una manera de desactivar la animación de Android ListView?
- ¿Cuál es la diferencia entre los dos tipos de implementación de la getView ()?
- Agregar un elemento CheckBox a ListView impide que pueda recibir ItemClick
- Botón de Android en el elemento ListView para cambiar el texto en la misma fila
LinearLayout layout = (LinearLayout) row.findViewById(R.id.LLBroadcasts); layout.removeAllViews(); for (Item b : bs.getItems()) { View child = _inflater.inflate(R.layout.item_row, null); TextView tvTitle = (TextView) child.findViewById(R.id.TVItemTitle); tvTitle.setText(b.getTitle()); TextView tvDesc = (TextView) child.findViewById(R.id.TVItemDescription); tvDesc.setText(b.getDescription()); layout.addView(child); }
- añadir elementos en la parte superior de la vista de lista android
- Vista personalizada vacía en ListView android
- Lista de Android lista completa seleccionada seleccionada
- Android ListView Despliegue hacia abajo para actualizar
- Viewpager no se desplaza en el diseño del coordinador
- elemento dinámico de listaVista añadir
- ¿Cómo cambiar la altura de ListView de forma dinámica en Android?
- Posición de retención en ListView después de llamar a notifyDataSetChanged
De la documentación de Android – ListView : ListView es un grupo de vistas que muestra una lista de elementos desplazables
En realidad, no desea desplazarse por esa vista de lista interna, desea desplazarse por la lista externa. Sin embargo, supongo que la lista interna puede variar en la cantidad de elementos que contiene.
En lugar de la vista interna de la lista, podría
- Lineal , vea este tutorial o consulte Agregando contenido a un diseño lineal dinámicamente?
- Tabla , vea este tutorial
Para el diseño lineal (código de ejemplo):
// access your linear layout LinearLayout layout = (LinearLayout)findViewById(R.id.layout); // load the xml structure of your row View child = getLayoutInflater().inflate(R.layout.row); // now fill the row as you would do with listview //eg (TextView) child.findViewById(... ... // and than add it layout.addView(child);
Debe guardar el diseño lineal en un soporte de visualización (consulte el patrón del titular de la vista ). Creo que el removeAllViews()
sólo es necesario cuando la fila actual tiene menos filas internas que el reutilizado, por lo que también guardaría el número de filas en el titular de la vista.
Si el número máximo de filas internas no es alto, también podría pensar en ponerlas en caché en el titular de la vista para evitar el inflado y findByViewId (digamos en un ArrayList).
Tengo el mismo problema en mi App pero necesitaba usar una causa de ListView era un artículo compartido y no quise reproducir los componentes iguales. Así que .. Me acaba de arreglar el tamaño de ListView interna para mostrar programaticamente todas las filas y .. voila! Problema resuelto:
ViewGroup.LayoutParams layoutParams = innerListView.getLayoutParams(); layoutParams.height = (int) context.getResources().getDimension(R.dimen.rowheight) * innerListView.getCount(); innerListView.setLayoutParams(layoutParams); CustomAdapter adapter = new CustomAdapter(context, blabla..); innerListView.setAdapter(adapter); rowListView.invalidate();
Tal vez alguien encontrará mi solución útil. Se basa en la respuesta @ChrLipp y utiliza LinearLayout.
public class NotScrollableListView extends LinearLayout { private ListAdapter adapter; private DataChangeObserver dataChangeObserver; private Drawable divider; private int dividerHeight; private List<View> reusableViews = new ArrayList<>(); public NotScrollableListView(Context context) { super(context); } public NotScrollableListView(Context context, AttributeSet attrs) { super(context, attrs); setAttributes(attrs); } public NotScrollableListView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setAttributes(attrs); } public ListAdapter getAdapter() { return adapter; } public void setAdapter(ListAdapter adapter) { if (this.adapter != null && dataChangeObserver != null) { this.adapter.unregisterDataSetObserver(dataChangeObserver); } this.adapter = adapter; } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (adapter != null) { dataChangeObserver = new DataChangeObserver(); adapter.registerDataSetObserver(dataChangeObserver); fillContents(); } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (adapter != null) { adapter.unregisterDataSetObserver(dataChangeObserver); dataChangeObserver = null; } } private void fillContents() { // clearing contents this.removeAllViews(); final int count = adapter.getCount(); // item count final int reusableCount = reusableViews.size(); // count of cached reusable views // calculating of divider properties ViewGroup.LayoutParams dividerLayoutParams = null; if (divider != null && dividerHeight > 0) { dividerLayoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dividerHeight); } // adding items for (int i = 0; i < count; i++) { // adding item View converView = null; if (i < reusableCount) { // we have cached view converView = reusableViews.get(i); } View view = adapter.getView(i, converView, this); if (i >= reusableCount) { // caching view reusableViews.add(view); } addView(view); // adding divider if (divider != null && dividerHeight > 0) { if (i < count - 1) { ImageView dividerView = new ImageView(getContext()); dividerView.setImageDrawable(divider); dividerView.setLayoutParams(dividerLayoutParams); addView(dividerView); } } } } private void setAttributes(AttributeSet attributes) { int[] dividerAttrs = new int[]{android.R.attr.divider, android.R.attr.dividerHeight}; TypedArray a = getContext().obtainStyledAttributes(attributes, dividerAttrs); try { divider = a.getDrawable(0); dividerHeight = a.getDimensionPixelSize(1, 0); } finally { a.recycle(); } setOrientation(VERTICAL); } private class DataChangeObserver extends DataSetObserver { @Override public void onChanged() { super.onChanged(); fillContents(); } @Override public void onInvalidated() { super.onInvalidated(); fillContents(); } } } <com.sample.ui.view.NotScrollableListView android:id="@+id/internalList" android:layout_width="match_parent" android:layout_height="wrap_content" android:divider="@color/list_divider_color" android:dividerHeight="@dimen/list_divider_width" />
@ Pruebe esta clase anidada
Esto funciona para listView
inside listView
O 2 listview
s en la misma activity
<com.example.taskgrptaskslistview.NestedListView android:id="@+id/listviewTasks" android:layout_width="0dip" android:layout_height="wrap_content" android:layout_marginBottom="2dp" android:layout_weight="1" android:cacheColorHint="#00000000" > </com.example.taskgrptaskslistview.NestedListView> </LinearLayout>
NestedListView:
import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; import android.widget.ListAdapter; import android.widget.ListView; public class NestedListView extends ListView implements OnTouchListener, OnScrollListener { private int listViewTouchAction; private static final int MAXIMUM_LIST_ITEMS_VIEWABLE = 99; public NestedListView(Context context, AttributeSet attrs) { super(context, attrs); listViewTouchAction = -1; setOnScrollListener(this); setOnTouchListener(this); } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) { if (listViewTouchAction == MotionEvent.ACTION_MOVE) { scrollBy(0, -1); } } } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int newHeight = 0; final int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (heightMode != MeasureSpec.EXACTLY) { ListAdapter listAdapter = getAdapter(); if (listAdapter != null && !listAdapter.isEmpty()) { int listPosition = 0; for (listPosition = 0; listPosition < listAdapter.getCount() && listPosition < MAXIMUM_LIST_ITEMS_VIEWABLE; listPosition++) { View listItem = listAdapter.getView(listPosition, null, this); //now it will not throw a NPE if listItem is a ViewGroup instance if (listItem instanceof ViewGroup) { listItem.setLayoutParams(new LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); } listItem.measure(widthMeasureSpec, heightMeasureSpec); newHeight += listItem.getMeasuredHeight(); } newHeight += getDividerHeight() * listPosition; } if ((heightMode == MeasureSpec.AT_MOST) && (newHeight > heightSize)) { if (newHeight > heightSize) { newHeight = heightSize; } } } else { newHeight = getMeasuredHeight(); } setMeasuredDimension(getMeasuredWidth(), newHeight); } @Override public boolean onTouch(View v, MotionEvent event) { if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) { if (listViewTouchAction == MotionEvent.ACTION_MOVE) { scrollBy(0, 1); } } return false; } }
He intentado hacer esta estructura exacta (un ListView
dentro de un ListView
) y tenía el mismo problema de que sólo muestra el primer elemento de la ListView
interior. Lo arreglé cambiando el layout_height
de la lista interna de match_parent
a un conjunto dp
.
Parecía que funcionaba exactamente como yo quería.