Comment mettre un ListView dans un ScrollView sans qu'il s'effondre?

j'ai cherché des solutions à ce problème, et la seule réponse que je puisse trouver semble être " ne mettez pas de ListView dans un ScrollView ". Je n'ai pas encore vu d'explication réelle pour pourquoi cependant. La seule raison pour laquelle je peux sembler de trouver est que Google ne pense pas que vous devriez vouloir faire cela. Eh bien, je ne, je l'ai fait.

donc la question est, comment pouvez-vous placer un ListView dans un ScrollView sans qu'il s'effondre à son hauteur minimale?

334
demandé sur Celeo 2010-08-16 22:00:58

27 réponses

utiliser un ListView pour le faire ne pas faire défiler est extrêmement coûteux et va à l'encontre de l'ensemble de l'objectif de ListView . Vous devriez et non . Il suffit d'utiliser un LinearLayout à la place.

188
répondu Romain Guy 2016-01-25 08:16:30

voici ma solution. Je suis assez nouveau sur la plateforme Android, et je suis sûr que c'est un peu hackish, surtout dans la partie sur les appels .mesurer directement, et définir la propriété LayoutParams.height directement, mais cela fonctionne.

Tout ce que vous avez à faire est d'appeler Utility.setListViewHeightBasedOnChildren(yourListView) et il sera redimensionné pour accommoder exactement la hauteur de ses articles.

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);
    }
}
252
répondu DougW 2016-08-22 03:02:42

Ce sera certainement le travail............

Vous devez juste remplacer votre <ScrollView ></ScrollView> dans le fichier de mise en page XML avec ce Custom ScrollView comme <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;
    }
}
86
répondu Atul Bhardwaj 2014-07-24 09:45:34

inscrit de mettre ListView dans un ScrollView , nous pouvons utiliser ListView comme un ScrollView . Les choses qui doivent être dans ListView peuvent être mis à l'intérieur du ListView . D'autres layouts en haut et en bas de ListView peuvent être mis en ajoutant des layouts à l'en-tête et au pied de page de ListView . Ainsi, le ListView entier vous donnera une expérience de défilement .

24
répondu Arun 2015-04-20 11:57:44

Il y a beaucoup de choses des situations où il fait beaucoup de sens d'avoir de ListView dans un ScrollView.

voici le code basé sur la suggestion de DougW... travaille dans un fragment, prend moins de mémoire.

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

call setListViewHeightBasedOnChildren(listview) sur chaque listview intégré.

20
répondu djunod 2013-08-01 11:34:48

ListView est en fait déjà capable de se mesurer pour être assez grand pour afficher tous les articles, mais il ne le fait pas quand vous spécifiez simplement wrap_content (MeasureSpec.INDÉTERMINÉ.) Il le fera si on lui donne une hauteur avec MeasureSpec.Presque. Avec cette connaissance, vous pouvez créer une sous-classe très simple pour résoudre ce problème qui fonctionne beaucoup mieux que n'importe laquelle des solutions affichées ci-dessus. Vous devez toujours utiliser wrap_content avec cette sous-classe.

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

la Manipulation de la heightMeasureSpec être AT_MOST avec une très grande taille (Entier.MAX_VALUE >> 4) fait que le ListView mesure tous ses enfants jusqu'à la hauteur donnée (très grande) et règle sa hauteur en conséquence.

Cela fonctionne mieux que les autres solutions pour quelques raisons:

  1. Il mesure tout correctement (rembourrage, intercalaires)
  2. à la mesure de la ListView au cours de la mesure pass
  3. en raison de #2, il gère correctement les changements de largeur ou de nombre d'articles sans aucun code supplémentaire

du côté négatif, vous pourriez soutenir que faire cela dépend d'un comportement non documenté dans le SDK qui pourrait changer. D'un autre côté, vous pourriez argumenter que c'est ainsi que wrap_content devrait fonctionner avec ListView et que le comportement wrap_content actuel est juste cassé.

Si vous êtes inquiet que le comportement pourrait changer à l'avenir, vous devrez simplement copier la fonction onMeasure et les fonctions connexes à partir de ListView.java et dans votre propre sous-classe, puis faire le chemin AT_MOST through onMeasure Exécuter pour UNSPECIFIED aussi bien.

Par ailleurs, je crois que c'est parfaitement valable lorsque vous travaillez avec de petits nombres d'éléments de la liste. Il peut être inefficace par rapport à LinearLayout, mais lorsque le nombre d'articles est faible, L'utilisation de LinearLayout est l'optimisation inutile et donc complexité inutile.

15
répondu Jason Y 2015-04-21 00:38:47

il y a un cadre intégré pour cela. Sur le ScrollView:

android:fillViewport="true"

En Java,

mScrollView.setFillViewport(true);

Romain Guy l'explique en profondeur ici: http://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/

12
répondu TalkLittle 2014-08-04 05:50:14

nous ne pouvions pas utiliser deux défilement simultanément.Nous aurons obtenir la longueur totale de ListView et étendre listview avec la hauteur totale .Ensuite, nous pouvons ajouter ListView dans ScrollView directement ou en utilisant LinearLayout parce que ScrollView ont directement un enfant . copiez la méthode setListViewHeightBasedOnChildren(lv) dans votre code et développez listview puis vous pouvez utiliser listview à l'intérieur de scrollview. \layout fichier xml

<?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éthode onCreate dans la classe D'activité:

 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);
      }
8
répondu Ashish Saini 2014-07-12 11:07:13

vous créez ListView personnalisé qui est non Scrollable

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

Dans Votre Fichier De Ressources De Mise En Page

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

Dans Le Fichier Java

créez un objet de votre customListview au lieu de ListView comme : Nonscrollllistview non_scroll_list = (Nonscrollistview) findViewById (R. id.lv_nonscroll_list);

8
répondu Dedaniya HirenKumar 2016-05-24 10:28:39

il s'agit d'une combinaison des réponses de DougW, Good Guy Greg, et Paul. J'ai trouvé qu'il était tout nécessaire en essayant d'utiliser ceci avec un adaptateur listview personnalisé et des éléments de liste non standard sinon le listview a écrasé l'application (également écrasé avec la réponse par 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);
    }
4
répondu Abandoned Cart 2013-08-04 19:29:25

j'ai converti le Utility de @DougW en C# (Utilisé En Xamarin). Ce qui suit fonctionne bien pour les articles de hauteur fixe dans la liste, et va être la plupart du temps très bien, ou au moins un bon début, si seulement certains des éléments sont un peu plus grand que l'article standard.

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

Merci @DougW, cela m'a sorti d'une situation difficile quand j'ai dû travailler avec le code D'autres personnes. :- )

3
répondu Phil Ryan 2014-07-09 04:31:51

vous ne devez pas mettre un ListView dans un ScrollView car un ListView déjà est un ScrollView. Donc, ce serait comme mettre un ScrollView dans un ScrollView.

Qu'essayez-vous d'accomplir?

2
répondu Cheryl Simon 2010-08-16 18:02:45

hey, j'ai eu un problème similaire. Je voulais afficher une vue de liste qui ne défilait pas et j'ai trouvé que la manipulation des paramètres fonctionnait mais était inefficace et se comporterait différemment sur différents appareils.. en conséquence, il s'agit d'un élément de mon programme qui fait cela très efficacement.

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

Note: Si vous utilisez ceci, notifyDataSetChanged(); ne fonctionnera pas comme prévu car les vues ne seront pas redessinées. Faire cela que si vous avez besoin d'un travail autour de

adapter.registerDataSetObserver(new DataSetObserver() {

            @Override
            public void onChanged() {
                super.onChanged();
                removeAndRedrawViews();

            }

        });
2
répondu PSchuette 2014-02-25 02:23:29

il y a deux problèmes lors de l'utilisation d'un ListView à l'intérieur d'un ScrollView.

1 - ListView doit atteindre la hauteur de ses enfants. cette liste résoudre ce problème:

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 hauteur du diviseur doit être 0, utilisez le rembourrage dans les rangées à la place.

2 - le ListView consomme des événements tactiles donc ScrollView ne peut pas être scrollé comme d'habitude. Cette ScrollView résoudre ce problème:

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

C'est le meilleur moyen que j'ai trouvé faire l'affaire!

2
répondu Ali 2014-03-31 00:37:21

C'est la seule chose qui a fonctionné pour moi:

à partir de Lollipop, vous pouvez utiliser

yourtListView.setNestedScrollingEnabled(true);

ceci active ou désactive le défilement emboîté pour cette vue si vous avez besoin d'une rétrocompatibilité avec l'ancienne version de L'OS, vous devrez utiliser le RecyclerView.

2
répondu JackA 2016-11-07 07:30:27

grâce à Vinay code voici mon code pour quand vous ne pouvez pas avoir une liste à l'intérieur d'un scrollview pourtant vous besoin de quelque chose comme ça

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

le relativeLayout reste à l'intérieur d'un ScrollView de sorte qu'il devient de défilement :)

1
répondu max4ever 2017-05-23 12:18:33

Voici une petite modification sur @djunod 's réponse que je dois le faire fonctionner parfaitement:

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();
}
1
répondu Eng.Fouad 2017-05-23 11:55:19

essayez ceci, cela fonctionne pour moi, j'ai oublié où je l'ai trouvé, quelque part dans le débordement de pile, Je ne suis pas ici pour expliquer pourquoi cela ne fonctionne pas, Mais voici la réponse :).

    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 ! J'ai enfin trouvé où j'ai obtenu le code. ici ! : ListView à l'intérieur de ScrollView n'est pas le défilement sur Android

1
répondu Bhimbim 2017-05-23 11:55:19

bien que les méthodes suggérées setListViewHeightBasedOnChildren () fonctionnent dans la plupart des cas, dans certains cas, spécialement avec beaucoup d'articles, j'ai remarqué que les derniers éléments ne sont pas affichés. J'ai donc décidé d'imiter une version simple du comportement ListView afin de réutiliser n'importe quel code Adaptateur, voici L'alternative 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);

        }
    }
}
}
1
répondu Alécio Carvalho 2014-08-15 09:12:04

une solution que j'utilise est d'ajouter tout le contenu de ScrollView (ce qui devrait être au-dessus et sous listView) comme headerView et footerView dans ListView.

donc cela fonctionne comme, aussi convertview est resued comment il devrait être.

1
répondu brokedid 2015-07-24 07:52:01

Toutes ces réponses sont fausses!!! Si vous essayez de mettre un listview dans une vue scroll, vous devriez repenser votre conception. Vous essayez de mettre un ScrollView dans un ScrollView. Interférer avec la liste nuira à la performance de la liste. Il a été conçu pour être comme ça par Androïde.

si vous voulez vraiment que la liste soit dans le même rouleau que les autres éléments, tout ce que vous avez à faire est d'ajouter les autres éléments dans le haut de la liste en utilisant un simple switch statement dans votre adaptateur:

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


}

l'adaptateur de liste peut tout gérer puisqu'il ne rend que ce qui est visible.

1
répondu TacoEater 2016-02-10 20:56:27

avant c'était impossible. Mais avec la sortie de nouvelles bibliothèques Appcompat et Design libraries, cela est possible.

vous avez juste à utiliser NestedScrollView https://developer.android.com/reference/android/support/v4/widget/NestedScrollView.html

Je ne sais pas s'il fonctionnera avec Listview ou non, mais il fonctionne avec RecyclerView.

Extrait De Code:

<android.support.v4.widget.NestedScrollView 
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

</android.support.v4.widget.NestedScrollView>
1
répondu Shashank Kapsime 2017-10-10 05:25:33

Tout ce problème disparaîtrait si LinearLayout avait une méthode setAdapter, parce que quand vous avez dit à quelqu'un de l'utiliser à la place, l'alternative serait triviale.

si vous voulez réellement un ListView défilant dans une autre vue défilante, cela ne vous aidera pas, mais sinon cela vous donnera au moins une idée.

vous devez créer un adaptateur personnalisé pour combiner tout le contenu que vous voulez faire défiler et mettre l'adaptateur de ListView à que.

Je n'ai pas de code d'exemple à portée de main, mais si vous voulez quelque chose comme.

<ListView/>

(other content)

<ListView/>

ensuite, vous devez créer un adaptateur qui représente tout ce contenu. Les ListView / adaptateurs sont assez intelligents pour prendre en charge différents types, mais vous devez écrire vous-même l'adaptateur.

L'API Android UI N'est tout simplement pas aussi mature que presque tout le reste là-bas, donc il n'a pas les mêmes subtilités que les autres plates-formes. En outre, lorsque vous faites quelque chose sur android vous devez être dans un État d'esprit android (unix) où vous vous attendez à ce que pour faire quoi que ce soit, vous allez probablement avoir à assembler des fonctionnalités de plus petites pièces et d'écrire un tas de votre propre code pour le faire fonctionner.

0
répondu majinnaibu 2013-01-13 19:41:41

Lorsque nous place ListView à l'intérieur ScrollView deux problèmes se posent. L'un est ScrollView mesure ses enfants en mode non spécifié, donc ListView fixe sa propre taille pour accommoder un seul article(Je ne sais pas pourquoi), un autre est ScrollView intercepte l'événement touch de sorte que ListView ne défile pas.

mais nous can place ListView à l'intérieur ScrollView avec quelques contournements. Ce post , par moi, explique la solution de contournement. Par cette solution, nous pouvons également conserver une ListView fonction de recyclage.

0
répondu Durgadass S 2014-10-24 04:36:43

au lieu de placer listview dans Scrollview, placez le reste du contenu entre listview et l'ouverture de Scrollview comme une vue séparée et définissez cette vue comme l'en-tête de listview. Ainsi, vous finirez finalement par ne voir que la liste prise en charge de Scroll.

0
répondu Saksham 2016-03-14 14:55:30

cette bibliothèque est la solution la plus facile et la plus rapide au problème.

0
répondu Kashif Nazar 2017-04-05 11:57:03

voici ma version du code qui calcule la hauteur totale de la vue Liste. Celui-ci travaille pour moi:

   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();
}
-1
répondu myforums 2014-02-13 23:15:46