web-dev-qa-db-fra.com

ListView non-scrollable dans ScrollView

J'essaie de faire une mise en page comme ceci:

layout

Le problème est que je ne veux pas que les ListViews puissent défiler. Je veux qu’ils soient aussi hauts que nécessaire et que tout l’écran soit défilable. Si je règle la hauteur de ListView à wrap_content, cela ne fonctionnera pas. La seule façon de le faire fonctionner est de définir une hauteur spécifique - mais je ne sais pas combien d'éléments seront dans ListView.

Je sais que je ne devrais pas mettre ListView dans ScrollView - mais je ne veux pas que ListView puisse défiler, mais pour afficher tous les éléments.

Peut-être qu'il y a un meilleur moyen de le faire fonctionner?

61
Dennis

Vous créez un ListView personnalisé qui n'est pas 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

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:fadingEdgeLength="0dp"
    Android:fillViewport="true"
    Android:overScrollMode="never"
    Android:scrollbars="none" >

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

</ScrollView>

En fichier Java

Créez un objet de votre customListview au lieu de ListViewlike:
NonScrollListView non_scroll_list = (NonScrollListView) findViewById (R.id.lv_nonscroll_list);

145

Il n'y a pas du tout besoin d'utiliser une listview.

Si vous y réfléchissez vraiment, une listview peut être remplacée par une représentation linéaire dans votre cas. L’adaptateur est identique, mais au lieu d’attacher l’adaptateur à votre listview, appelez simplement la fonction getView de l’adaptateur dans une boucle for pour vos données et ajoutez les vues extraites à votre affichage linéaire vertical.

Cependant, cette approche n'est recommandée que si vous avez un petit nombre d'éléments dans votre liste et que votre représentation d'affichage de ces éléments ne nécessite pas beaucoup de mémoire.

7
Samarth Jain

La meilleure façon de procéder (en 2017) consiste à utiliser un RecyclerView avec un NestedScrollView. Aucun piratage requis et cela fonctionne comme vous le souhaitez.

2
Anthony Chuinard

Eh bien, il y a un gars cool sur Android nommé Mark Murphy de CommonsWare et il a construit un composant très utile nommé CWAC Merge Adapter qui vous permet de faire ce dont vous avez besoin. Vous devrez ajouter les vues de manière dynamique et non à partir de XML; mais compte tenu de votre interface utilisateur simple, cela ne devrait pas être un problème. Je l'utilise pour ce type de cas où je n'ai aucune idée du type de données que je suis censé faire défiler.

Si vous ne voulez pas l'utiliser (pour des raisons de licence peut-être), vous pouvez y avoir une seule liste (au lieu de ces 2 vues consécutives) et remplacer getItemViewsCount, getItemViewType et getView afin de donner la disposition ci-dessus. Si vous recherchez Android listview different rows sur Google, vous trouverez des informations utiles. Par exemple ce lien ou celui-ci .

Cependant, je choisirais un adaptateur de fusion.

0
gunar

Choisissez le ListView que vous voulez faire défiler, puis ajoutez la méthode 'setOnTouchListener' pour que le système insère automatiquement le défilement dans le ListView. 

final ListView listview = (ListView) findViewById(R.id.list);


    listview.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;
        }
    });
    listview.setClickable(true);

J'espère que ça marche pour toi

0
Houssem CH

J'ai une solution facile s'il est possible de calculer la hauteur de votre élément/largeur ... Il vous suffit de créer une représentation linéaire du parent de ListView, puis de fixer le parent hauteur à partir de Java.

 enter image description here

Supposons que vous ayez besoin de concevoir cette vue ... Maintenant, la taille de la mise en page parent est définie par Java ...

final LinearLayout parent=(LinearLayout)findViewById(R.id.parent);
final ListView  listview=(ListView)findViewById(R.id.listview);
parent.setLayoutParams(new LinearLayout.LayoutParams(parent.getLayoutParams().width, dpToPx( number_of_item_in_list * per_item_size_in_dp )));
//number_of_item_in_list is list side ~ listArray.size();
//per_item_size_in_dp = calculate item size in dp. Ex: 80dp

public static int dpToPx(int dp)
{
    return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}

c'est tout :)

0
Shohan Ahmed Sijan