android: listview en listview

Estoy tratando de colocar una vista de lista dentro de un listado. la vista de lista interna no debe ser desplazable, pero tome todo el tamaño que necesita para mostrar todas sus filas. ¿Hay una mejor manera de esto? tabla, cuadrícula, …? El problema que estoy enfrentando ahora es que la lista de la lista interna no ocupa el espacio que necesita, por lo que se corta al final del primer elemento de lista. si trato de desplazarme, solo la vista de lista externa se desplaza, que es exactamente lo que quiero.

how_it_should_look_like gracias, mi solución final es

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); } 

De la documentación de Android – Vista de lista : ListView es un grupo de vista que muestra una lista de elementos desplazables

Realmente no desea desplazarse por la vista de lista interna, desea desplazarse por la vista de lista externa. Sin embargo, supongo que la vista de lista interna puede variar según la cantidad de elementos que contiene.

En lugar de la vista de lista interna, podría usar un

  • diseño lineal , consulte este tutorial o consulte Agregar contenido a un diseño lineal de forma dinámica?
  • disposición de la mesa

Para el diseño lineal (algunos ejemplos de código):

 // 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 vista (consulte Ver patrón de soporte ). Creo que removeAllViews() solo es necesario cuando la fila actual tiene menos filas internas que la reutilizada, por lo que también guardaría el número de filas en el titular de la vista.

Si la cantidad máxima de filas internas no es demasiado alta, también podría pensar en almacenarlas en el soporte de la vista para evitar el inflado y findByViewId (digamos en una ArrayList).

Tengo el mismo problema en mi aplicación, pero necesitaba usar un ListView porque era un elemento compartido y no quería replicar componentes iguales. Así que … Acabo de arreglar el tamaño de ListView interno programáticamente para mostrar 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 encuentre útil mi solución. 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 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(); } } }  

@Intente esta clase anidada

esto funciona para scroll listView inside listView Or 2 listview s en la misma activity

     

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; } } 

Intenté hacer esta estructura exacta (un ListView dentro de un ListView ) y tuve el mismo problema de que solo mostraba el primer elemento del ListView interno. Lo arreglé cambiando el layout_height de la lista interna de match_parent a un conjunto dp .

Parecía funcionar exactamente como yo quería.