¿Cómo puedo poner un ListView en un ScrollView sin colapsar?

He buscado por soluciones para este problema, y ​​la única respuesta que puedo encontrar parece ser " no poner un ListView en un ScrollView ". Todavía no he visto ninguna explicación real de por qué sin embargo. La única razón que puedo parecer encontrar es que Google no piensa que usted debe desear hacer eso. Bueno lo hago, así que lo hice.

Así que la pregunta es, ¿cómo puede colocar un ListView en un ScrollView sin que se contraiga a su altura mínima?

El uso de un ListView para que no sea scroll es extremadamente caro y va en contra de todo el propósito de ListView . Usted NO debe hacer esto. Simplemente utilice un LinearLayout en LinearLayout lugar.

Aquí está mi solución. Soy bastante nuevo en la plataforma de Android, y estoy seguro de que esto es un poco hackish, especialmente en la parte acerca de la llamada .medida directamente, y el establecimiento de la propiedad LayoutParams.height directamente, pero funciona.

Todo lo que tiene que hacer es llamar a Utility.setListViewHeightBasedOnChildren(yourListView) y se redimensionará para acomodar exactamente la altura de sus elementos.

 public class Utility { public static void setListViewHeightBasedOnChildren(ListView listView) { ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) { // pre-condition return; } int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom(); for (int i = 0; i < listAdapter.getCount(); i++) { View listItem = listAdapter.getView(i, null, listView); if (listItem instanceof ViewGroup) { listItem.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); } listItem.measure(0, 0); totalHeight += listItem.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); listView.setLayoutParams(params); } } 

Esto definitivamente funcionará …………
Sólo tiene que reemplazar su <ScrollView ></ScrollView> en el archivo XML de diseño con esta Custom ScrollView como <com.tmd.utils.VerticalScrollview > </com.tmd.utils.VerticalScrollview >

 package com.tmd.utils; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.widget.ScrollView; public class VerticalScrollview extends ScrollView{ public VerticalScrollview(Context context) { super(context); } public VerticalScrollview(Context context, AttributeSet attrs) { super(context, attrs); } public VerticalScrollview(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { final int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: Log.i("VerticalScrollview", "onInterceptTouchEvent: DOWN super false" ); super.onTouchEvent(ev); break; case MotionEvent.ACTION_MOVE: return false; // redirect MotionEvents to ourself case MotionEvent.ACTION_CANCEL: Log.i("VerticalScrollview", "onInterceptTouchEvent: CANCEL super false" ); super.onTouchEvent(ev); break; case MotionEvent.ACTION_UP: Log.i("VerticalScrollview", "onInterceptTouchEvent: UP super false" ); return false; default: Log.i("VerticalScrollview", "onInterceptTouchEvent: " + action ); break; } return false; } @Override public boolean onTouchEvent(MotionEvent ev) { super.onTouchEvent(ev); Log.i("VerticalScrollview", "onTouchEvent. action: " + ev.getAction() ); return true; } } 

Insted de poner ListView dentro de un ScrollView , podemos usar ListView como ScrollView . Las cosas que tienen que estar en ListView se pueden poner dentro de ListView . Otros diseños en la parte superior e inferior de ListView se pueden agregar agregando diseños al encabezado y pie de página de ListView . Así que todo el ListView le dará una experiencia de desplazamiento.

Hay un montón de situaciones en las que tiene mucho sentido tener ListView en un ScrollView.

Aquí está el código basado en la sugerencia de DougW … funciona en un fragmento, toma menos memoria.

 public static void setListViewHeightBasedOnChildren(ListView listView) { ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) { return; } int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.AT_MOST); int totalHeight = 0; View view = null; for (int i = 0; i < listAdapter.getCount(); i++) { view = listAdapter.getView(i, view, listView); if (i == 0) { view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, LayoutParams.WRAP_CONTENT)); } view.measure(desiredWidth, MeasureSpec.UNSPECIFIED); totalHeight += view.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); listView.setLayoutParams(params); listView.requestLayout(); } 

Llame a setListViewHeightBasedOnChildren (listview) en cada vista de lista incrustada.

Hay un ajuste incorporado para ello. En ScrollView:

 android:fillViewport="true" 

En Java,

 mScrollView.setFillViewport(true); 

Romain Guy lo explica en profundidad aquí: http://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/

ListView es en realidad ya capaz de medir sí mismo para ser lo suficientemente alto para mostrar todos los elementos, pero no lo hace cuando se especifica simplemente wrap_content (MeasureSpec.UNSPECIFIED). Lo hará cuando se le da una altura con MeasureSpec.AT_MOST. Con este conocimiento, puede crear una subclase muy simple para resolver este problema que funciona mucho mejor que cualquiera de las soluciones publicadas anteriormente. Debería seguir utilizando wrap_content con esta subclase.

 public class ListViewForEmbeddingInScrollView extends ListView { public ListViewForEmbeddingInScrollView(Context context) { super(context); } public ListViewForEmbeddingInScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public ListViewForEmbeddingInScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 4, MeasureSpec.AT_MOST)); } } 

Manipular la alturaMeasureSpec como AT_MOST con un tamaño muy grande (Integer.MAX_VALUE >> 4) hace que ListView mida a todos sus hijos hasta la altura (muy grande) dada y ajuste su altura en consecuencia.

Esto funciona mejor que las otras soluciones por varias razones:

  1. Mide todo correctamente (relleno, divisores)
  2. Mide el ListView durante el pase de medida
  3. Debido a # 2, maneja los cambios en el ancho o número de elementos correctamente sin ningún código adicional

En el lado negativo, se podría argumentar que hacer esto es confiar en el comportamiento indocumentado en el SDK que podría cambiar. Por otro lado, podrías argumentar que así es como wrap_content debería funcionar realmente con ListView y que el comportamiento wrap_content actual está simplemente roto.

Si está preocupado de que el comportamiento podría cambiar en el futuro, simplemente debe copiar la función onMeasure y las funciones relacionadas fuera de ListView.java y en su propia subclase, a continuación, haga que la ruta AT_MOST a través de onMeasure se ejecute para UNSPECIFIED también.

Por cierto, creo que este es un enfoque perfectamente válido cuando se trabaja con un pequeño número de elementos de la lista. Puede ser ineficiente cuando se compara con LinearLayout, pero cuando el número de elementos es pequeño, el uso de LinearLayout es una optimización innecesaria y, por lo tanto, una complejidad innecesaria.

No podríamos utilizar dos scrolling simulteniuosly.Tendremos la longitud total de ListView y expandir listview con la altura total. Entonces podemos agregar ListView en ScrollView directamente o usar LinearLayout porque ScrollView tiene directamente un hijo. Copie el método setListViewHeightBasedOnChildren (lv) en su código y expanda listview entonces puede usar listview dentro de scrollview. \ Layout xml file

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ScrollView android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#1D1D1D" android:orientation="vertical" android:scrollbars="none" > <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#1D1D1D" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="40dip" android:background="#333" android:gravity="center_vertical" android:paddingLeft="8dip" android:text="First ListView" android:textColor="#C7C7C7" android:textSize="20sp" /> <ListView android:id="@+id/first_listview" android:layout_width="260dp" android:layout_height="wrap_content" android:divider="#00000000" android:listSelector="#ff0000" android:scrollbars="none" /> <TextView android:layout_width="fill_parent" android:layout_height="40dip" android:background="#333" android:gravity="center_vertical" android:paddingLeft="8dip" android:text="Second ListView" android:textColor="#C7C7C7" android:textSize="20sp" /> <ListView android:id="@+id/secondList" android:layout_width="260dp" android:layout_height="wrap_content" android:divider="#00000000" android:listSelector="#ffcc00" android:scrollbars="none" /> </LinearLayout> </ScrollView> </LinearLayout> 

Método onCreate en la clase de actividad:

  import java.util.ArrayList; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ListAdapter; import android.widget.ListView; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.listview_inside_scrollview); ListView list_first=(ListView) findViewById(R.id.first_listview); ListView list_second=(ListView) findViewById(R.id.secondList); ArrayList<String> list=new ArrayList<String>(); for(int x=0;x<30;x++) { list.add("Item "+x); } ArrayAdapter<String> adapter=new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1,list); list_first.setAdapter(adapter); setListViewHeightBasedOnChildren(list_first); list_second.setAdapter(adapter); setListViewHeightBasedOnChildren(list_second); } public static void setListViewHeightBasedOnChildren(ListView listView) { ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) { // pre-condition return; } int totalHeight = 0; for (int i = 0; i < listAdapter.getCount(); i++) { View listItem = listAdapter.getView(i, null, listView); listItem.measure(0, 0); totalHeight += listItem.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); listView.setLayoutParams(params); } 

Esta es una combinación de las respuestas de DougW, Good Guy Greg y Paul. Encontré que era todo necesario al intentar utilizar esto con un adaptador de listview personalizado y los elementos de lista no estándar de lo contrario el listview se estrelló la aplicación (también se estrelló con la respuesta de Nex):

 public void setListViewHeightBasedOnChildren(ListView listView) { ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) { return; } int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom(); for (int i = 0; i < listAdapter.getCount(); i++) { View listItem = listAdapter.getView(i, null, listView); if (listItem instanceof ViewGroup) listItem.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); listItem.measure(0, 0); totalHeight += listItem.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); listView.setLayoutParams(params); } 

No debería poner un ListView en un ScrollView porque un ListView ya es ScrollView. Así que sería como poner un ScrollView en un ScrollView.

¿Qué está tratando de lograr?

Hey yo tenía un problema similar. Quería mostrar una vista de lista que no se desplazaba y descubrí que la manipulación de los parámetros funcionaba, pero era ineficiente y se comportaría de manera diferente en diferentes dispositivos .. como resultado, este es un pedazo de mi código de programación que realmente hace esto muy eficientemente .

 db = new dbhelper(this); cursor = db.dbCursor(); int count = cursor.getCount(); if (count > 0) { LinearLayout linearLayout = (LinearLayout) findViewById(R.id.layoutId); startManagingCursor(YOUR_CURSOR); YOUR_ADAPTER(**or SimpleCursorAdapter **) adapter = new YOUR_ADAPTER(this, R.layout.itemLayout, cursor, arrayOrWhatever, R.id.textViewId, this.getApplication()); int i; for (i = 0; i < count; i++){ View listItem = adapter.getView(i,null,null); linearLayout.addView(listItem); } } 

Nota: si utiliza esto, notifyDataSetChanged(); No funcionará según lo previsto, ya que las vistas no se volverán a dibujar. Haga esto si necesita un trabajo alrededor

 adapter.registerDataSetObserver(new DataSetObserver() { @Override public void onChanged() { super.onChanged(); removeAndRedrawViews(); } }); 

Hay dos problemas al usar un ListView dentro de ScrollView.

1- ListView debe expandirse completamente a la altura de sus hijos. Este ListView resolver esto:

 public class ListViewExpanded extends ListView { public ListViewExpanded(Context context, AttributeSet attrs) { super(context, attrs); setDividerHeight(0); } @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST)); } } 

La altura del divisor debe ser 0, utilice relleno en filas en su lugar.

2- El ListView consume eventos táctiles para que ScrollView no se pueda desplazar como de costumbre. Este ScrollView resolver este problema:

 public class ScrollViewInterceptor extends ScrollView { float startY; public ScrollViewInterceptor(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onInterceptTouchEvent(MotionEvent e) { onTouchEvent(e); if (e.getAction() == MotionEvent.ACTION_DOWN) startY = e.getY(); return (e.getAction() == MotionEvent.ACTION_MOVE) && (Math.abs(startY - e.getY()) > 50); } } 

Esta es la mejor manera que encontré para hacer el truco!

Convertido @ Utilidad de DougW en C # (utilizado en Xamarin). Lo siguiente funciona bien para los elementos de altura fija de la lista, y va a ser mayormente bien, o al menos un buen comienzo, si sólo algunos de los elementos son un poco más grande que el elemento estándar.

 // You will need to put this Utility class into a code file including various // libraries, I found that I needed at least System, Linq, Android.Views and // Android.Widget. using System; using System.Linq; using Android.Views; using Android.Widget; namespace UtilityNamespace // whatever you like, obviously! { public class Utility { public static void setListViewHeightBasedOnChildren (ListView listView) { if (listView.Adapter == null) { // pre-condition return; } int totalHeight = listView.PaddingTop + listView.PaddingBottom; for (int i = 0; i < listView.Count; i++) { View listItem = listView.Adapter.GetView (i, null, listView); if (listItem.GetType () == typeof(ViewGroup)) { listItem.LayoutParameters = new LinearLayout.LayoutParams (ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent); } listItem.Measure (0, 0); totalHeight += listItem.MeasuredHeight; } listView.LayoutParameters.Height = totalHeight + (listView.DividerHeight * (listView.Count - 1)); } } } 

Gracias @DougW, esto me sacó de un punto apretado cuando tuve que trabajar con OtherPeople'sCode. Todos los derechos reservados

Gracias al código de Vinay aquí es mi código para cuando usted no puede tener un listview dentro de un scrollview pero necesita algo así

 LayoutInflater li = LayoutInflater.from(this); RelativeLayout parent = (RelativeLayout) this.findViewById(R.id.relativeLayoutCliente); int recent = 0; for(Contatto contatto : contatti) { View inflated_layout = li.inflate(R.layout.header_listview_contatti, layout, false); inflated_layout.setId(contatto.getId()); ((TextView)inflated_layout.findViewById(R.id.textViewDescrizione)).setText(contatto.getDescrizione()); ((TextView)inflated_layout.findViewById(R.id.textViewIndirizzo)).setText(contatto.getIndirizzo()); ((TextView)inflated_layout.findViewById(R.id.textViewTelefono)).setText(contatto.getTelefono()); ((TextView)inflated_layout.findViewById(R.id.textViewMobile)).setText(contatto.getMobile()); ((TextView)inflated_layout.findViewById(R.id.textViewFax)).setText(contatto.getFax()); ((TextView)inflated_layout.findViewById(R.id.textViewEmail)).setText(contatto.getEmail()); RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT); if (recent == 0) { relativeParams.addRule(RelativeLayout.BELOW, R.id.headerListViewContatti); } else { relativeParams.addRule(RelativeLayout.BELOW, recent); } recent = inflated_layout.getId(); inflated_layout.setLayoutParams(relativeParams); //inflated_layout.setLayoutParams( new RelativeLayout.LayoutParams(source)); parent.addView(inflated_layout); } 

El relativoLayout permanece dentro de un ScrollView por lo que todo se puede desplazar 🙂

Aquí hay una pequeña modificación en la respuesta de @djunod que necesito para que funcione perfectamente:

 public static void setListViewHeightBasedOnChildren(ListView listView) { ListAdapter listAdapter = listView.getAdapter(); if(listAdapter == null) return; if(listAdapter.getCount() <= 1) return; int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.AT_MOST); int totalHeight = 0; View view = null; for(int i = 0; i < listAdapter.getCount(); i++) { view = listAdapter.getView(i, view, listView); view.measure(desiredWidth, MeasureSpec.UNSPECIFIED); totalHeight += view.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); listView.setLayoutParams(params); listView.requestLayout(); } 

Prueba esto, esto funciona para mí, me olvidé donde lo encontré, en algún lugar en el desbordamiento de pila, no estoy aquí para explicar por qué no funciona, pero esta es la respuesta :).

  final ListView AturIsiPulsaDataIsiPulsa = (ListView) findViewById(R.id.listAturIsiPulsaDataIsiPulsa); AturIsiPulsaDataIsiPulsa.setOnTouchListener(new ListView.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: // Disallow ScrollView to intercept touch events. v.getParent().requestDisallowInterceptTouchEvent(true); break; case MotionEvent.ACTION_UP: // Allow ScrollView to intercept touch events. v.getParent().requestDisallowInterceptTouchEvent(false); break; } // Handle ListView touch events. v.onTouchEvent(event); return true; } }); AturIsiPulsaDataIsiPulsa.setClickable(true); AturIsiPulsaDataIsiPulsa.setAdapter(AturIsiPulsaDataIsiPulsaAdapter); 

EDIT !, finalmente encontré donde conseguí el código. aquí ! : ListView dentro de ScrollView no se desplaza en Android

Aunque los métodos de setListViewHeightBasedOnChildren () sugeridos funcionan en la mayoría de los casos, en algunos casos, especialmente con una gran cantidad de elementos, noté que los últimos elementos no se muestran. Así que decidí imitar una versión simple del comportamiento ListView para reutilizar cualquier código de adaptador, aquí es la alternativa ListView:

 import android.content.Context; import android.database.DataSetObserver; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.widget.LinearLayout; import android.widget.ListAdapter; public class StretchedListView extends LinearLayout { private final DataSetObserver dataSetObserver; private ListAdapter adapter; private OnItemClickListener onItemClickListener; public StretchedListView(Context context, AttributeSet attrs) { super(context, attrs); setOrientation(LinearLayout.VERTICAL); this.dataSetObserver = new DataSetObserver() { @Override public void onChanged() { syncDataFromAdapter(); super.onChanged(); } @Override public void onInvalidated() { syncDataFromAdapter(); super.onInvalidated(); } }; } public void setAdapter(ListAdapter adapter) { ensureDataSetObserverIsUnregistered(); this.adapter = adapter; if (this.adapter != null) { this.adapter.registerDataSetObserver(dataSetObserver); } syncDataFromAdapter(); } protected void ensureDataSetObserverIsUnregistered() { if (this.adapter != null) { this.adapter.unregisterDataSetObserver(dataSetObserver); } } public Object getItemAtPosition(int position) { return adapter != null ? adapter.getItem(position) : null; } public void setSelection(int i) { getChildAt(i).setSelected(true); } public void setOnItemClickListener(OnItemClickListener onItemClickListener) { this.onItemClickListener = onItemClickListener; } public ListAdapter getAdapter() { return adapter; } public int getCount() { return adapter != null ? adapter.getCount() : 0; } private void syncDataFromAdapter() { removeAllViews(); if (adapter != null) { int count = adapter.getCount(); for (int i = 0; i < count; i++) { View view = adapter.getView(i, null, this); boolean enabled = adapter.isEnabled(i); if (enabled) { final int position = i; final long id = adapter.getItemId(position); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (onItemClickListener != null) { onItemClickListener.onItemClick(null, v, position, id); } } }); } addView(view); } } } } 

Una solución que uso es, para agregar todo el contenido del ScrollView (lo que debería estar por encima y bajo el listView) como headerView y footerView en el ListView.

Así que funciona como, también el convertview es resued cómo debe ser.

¡Todas estas respuestas están equivocadas! Si usted está intentando poner un listview en una visión del enrollamiento usted debe repensar su diseño. Usted está intentando poner un ScrollView en ScrollView. Interferir con la lista dañará el rendimiento de la lista. Fue diseñado para ser así por Android.

Si realmente desea que la lista esté en el mismo desplazamiento que los otros elementos, todo lo que tiene que hacer es agregar los otros elementos a la parte superior de la lista mediante una instrucción switch simple en su adaptador:

 class MyAdapter extends ArrayAdapter{ public MyAdapter(Context context, int resource, List objects) { super(context, resource, objects); } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewItem viewType = getItem(position); switch(viewType.type){ case TEXTVIEW: convertView = layouteInflater.inflate(R.layout.textView1, parent, false); break; case LISTITEM: convertView = layouteInflater.inflate(R.layout.listItem, parent, false); break; } return convertView; } } 

El adaptador de lista puede manejar todo, ya que sólo representa lo que es visible.

Crea ListView personalizado que no es desplazable

 public class NonScrollListView extends ListView { public NonScrollListView(Context context) { super(context); } public NonScrollListView(Context context, AttributeSet attrs) { super(context, attrs); } public NonScrollListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec( Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom); ViewGroup.LayoutParams params = getLayoutParams(); params.height = getMeasuredHeight(); } } 

En el archivo de recursos de diseño

 <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <!-- com.Example Changed with your Package name --> <com.Example.NonScrollListView android:id="@+id/lv_nonscroll_list" android:layout_width="match_parent" android:layout_height="wrap_content" > </com.Example.NonScrollListView> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/lv_nonscroll_list" > <!-- Your another layout in scroll view --> </RelativeLayout> </RelativeLayout> 

En archivo Java

Cree un objeto de su vista personalizada en lugar de ListView como: NonScrollListView non_scroll_list = (NonScrollListView) findViewById (R.id.lv_nonscroll_list);

This whole problem would just go away if LinearLayout had a setAdapter method, because then when you told someone to use it instead the alternative would be trivial.

If you actually want a scrolling ListView inside another scrolling view this won't help, but otherwise this will at least give you an idea.

You need to create a custom adapter to combine all the content you want to scroll over and set the ListView's adapter to that.

I don't have sample code handy, but if you want something like.

 <ListView/> (other content) <ListView/> 

Then you need to create an adapter that represents all of that content. The ListView/Adapters are smart enough to handle different types as well, but you need to write the adapter yourself.

The android UI API just isn't as mature as pretty much everything else out there, so it doesn't have the same niceties as other platforms. Also, when doing something on android you need to be in an android (unix) mindset where you expect that to do anything you're probably going to have to assemble functionality of smaller parts and write a bunch of your own code to get it to work.

When we place ListView inside ScrollView two problems arise. One is ScrollView measures its children in UNSPECIFIED mode, so ListView sets its own height to accommodate only one item(I don't know why), another is ScrollView intercepts the touch event so ListView does not scrolls.

But we can place ListView inside ScrollView with some workaround. This post , by me, explains the workaround. By this workaround we can also retain ListView 's recycling feature as well.

This is the only thing that worked for me:

on Lollipop onwards you can use

 yourtListView.setNestedScrollingEnabled(true); 

This enable or disable nested scrolling for this view if you need backwards compatibility with older version of the OS you'll have to use the RecyclerView.

This library is the easiest and quickest solution to the problem.

Here is my version of the code that calculates total height of the list view. This one works for me:

  public static void setListViewHeightBasedOnChildren(ListView listView) { ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null || listAdapter.getCount() < 2) { // pre-condition return; } int totalHeight = 0; int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(BCTDApp.getDisplaySize().width, View.MeasureSpec.AT_MOST); int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); for (int i = 0; i < listAdapter.getCount(); i++) { View listItem = listAdapter.getView(i, null, listView); if (listItem instanceof ViewGroup) listItem.setLayoutParams(lp); listItem.measure(widthMeasureSpec, heightMeasureSpec); totalHeight += listItem.getMeasuredHeight(); } totalHeight += listView.getPaddingTop() + listView.getPaddingBottom(); totalHeight += (listView.getDividerHeight() * (listAdapter.getCount() - 1)); ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight; listView.setLayoutParams(params); listView.requestLayout(); } 

Instead of putting the listview inside Scrollview, put the rest of the content between listview and the opening of the Scrollview as a separate view and set that view as the header of the listview. So you will finally end up only list view taking charge of Scroll.

  • Android - ¿Cómo hacer una restricción desplazable?
  • ViewPager dentro de ScrollView - el desplazamiento vertical no funciona
  • Visor dinámico de altura
  • (Android) ScrollView no se desplazará todo el camino hasta la parte inferior de mi LinearLayout
  • Cambiar el color de ScrollView mediante programación
  • Cómo configurar OnClickListener para ScrollView?
  • Relleno de ScrollView
  • ¿Puedo desplazar un ScrollView de forma programática en Android?
  • Establecer la altura de Viewpager dentro de Scrollview en android
  • Hacer un scrollView autodescrollar con arrastrar y soltar en Android
  • Android: el salto de Listview a scrollview
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.