web-dev-qa-db-fra.com

Affichage de la liste Android dans un affichage par défilement

J'ai une mise en page Android qui a une scrollView avec un certain nombre d'éléments avec en elle. Au bas de la scrollView, j'ai une listView qui est ensuite renseignée par un adaptateur.

Le problème que je rencontre est qu'Android exclut la listView de la scrollView car la scrollView a déjà une fonction de défilement. Je veux que la listView soit aussi longue que le contenu et que la vue de défilement principale puisse défiler.

Comment puis-je obtenir ce comportement?

Voici ma mise en page principale:

<ScrollView
    Android:id="@+id/scrollView1"
    Android:layout_width="match_parent"
    Android:layout_height="0dp"
    Android:layout_weight="2"
    Android:fillViewport="true"
    Android:gravity="top" >

    <LinearLayout
        Android:id="@+id/foodItemActvity_linearLayout_fragments"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:orientation="vertical" >
    </LinearLayout>

</ScrollView>

J'ajoute ensuite par programmation mes composants à linearlayour avec l'id: foodItemActvity_linearLayout_fragments. Vous trouverez ci-dessous l’une des vues chargées dans cette représentation linéaire. C'est celui qui me pose problème avec les parchemins.

<?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="wrap_content"
    Android:orientation="vertical" >

    <TextView
       Android:id="@+id/fragment_dds_review_textView_label"
       Android:layout_width="wrap_content"
       Android:layout_height="wrap_content"
       Android:text="Reviews:"
       Android:textAppearance="?android:attr/textAppearanceMedium" />

   <ListView
       Android:id="@+id/fragment_dds_review_listView"
       Android:layout_width="match_parent"
       Android:layout_height="wrap_content">
   </ListView>
</LinearLayout>

Mon adaptateur remplit alors cette vue liste.

Voici une image du visualiseur de hiérarchie Android lorsque je clique sur le scrollView principal:

 Android List View inside a scroll view

Comme vous pouvez le constater, cela exclut les avis listView.

Je devrais pouvoir faire défiler la page vers le bas et voir 8 avis, mais au lieu de cela, il ne me montre que les 3, et je peux faire défiler la toute petite partie où se trouvent les avis. Je veux un défilement de page global

241
Zapnologica

Le solution la plus courte et la plus simple pour le ListView dans un problème ScrollView.

Vous ne devez rien faire de spécial dans le fichier layout.xml ni manipuler quoi que ce soit sur le ScrollView parent. _ {Vous devez seulement gérer l'enfant ListView}. Vous pouvez également utiliser ce code pour utiliser tout type de vue enfant à l'intérieur d'un objet ScrollView et effectuer des opérations tactiles.

Ajoutez simplement ces lignes de code dans votre classe Java:

ListView lv = (ListView) findViewById(R.id.layout_lv);
lv.setOnTouchListener(new OnTouchListener() {
    // Setting on Touch Listener for handling the touch inside ScrollView
    @Override
    public boolean onTouch(View v, MotionEvent event) {
    // Disallow the touch request for parent scroll on touch of child view
    v.getParent().requestDisallowInterceptTouchEvent(true);
    return false;
    }
});

Si vous mettez ListView à l'intérieur d'un ScrollView, le ListView ne s'étire pas à sa hauteur maximale}. Vous trouverez ci-dessous une méthode pour résoudre ce problème.

/**** Method for Setting the Height of the ListView dynamically.
 **** Hack to fix the issue of not showing all the items of the ListView
 **** when placed inside a ScrollView  ****/
public static void setListViewHeightBasedOnChildren(ListView listView) {
    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter == null)
        return;

    int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.UNSPECIFIED);
    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);
}

Pour utiliser cette méthode, il suffit de passer le ListView à l'intérieur de cette méthode:

ListView list = (ListView) view.findViewById(R.id.ls);
setListViewHeightBasedOnChildren(list);

Pour utiliser avec ExpandableListView - crédit Benny

ExpandableListView: view = listAdapter.getView(0, view, listView);
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.MATCH_PARENT, View.MeasureSpec.EXACTLY);
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.WRAP_CONTENT, View.MeasureSpec.EXACTLY);
view.measure(widthMeasureSpec, heightMeasureSpec);

Pour ListView avec des éléments variables height, utilisez le lien ci-dessous:

ListView dans ScrollView ne défile pas sur Android

Pour que la bibliothèque soit directement implémentée dans votre code - crédit Paolo Rotolo

https://github.com/PaoloRotolo/ExpandableHeightListView

533
arshu

La réponse est simple et je suis surpris qu'il n'ait pas encore été répondu ici.

Utilisez un Header View ou/et Footer View sur la liste elle-même . Ne mélangez pas une ScrollView avec une ListView ou quoi que ce soit qui puisse défiler. Il est destiné à être utilisé avec les en-têtes et les pieds de page :)

Essentiellement, prenez tout le contenu au-dessus de votre ListView, placez-le dans un autre fichier .xml en tant que mise en page, puis gonflez-le dans le code et ajoutez-le à la liste en tant qu'en-tête.

c'est à dire.

View header = getLayoutInflater().inflate(R.layout.header, null);
View footer = getLayoutInflater().inflate(R.layout.footer, null);
listView.addHeaderView(header);
listView.addFooterView(footer);
213
ericosg

Je sais que ça fait si longtemps, mais j'ai aussi ce problème, j'ai essayé cette solution et ça marche. Donc, je suppose que cela peut aider les autres aussi.

J'ajoute Android: fillViewport = "true" dans la mise en page XML de scrollView . Donc, dans l'ensemble, mon ScrollView sera comme ceci.

<ScrollView
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:id="@+id/scrollView6" 
    Android:fillViewport="true">

Et cela fonctionne comme par magie pour moi. le ListView situé à l'intérieur de mon ScrollView s'agrandit à sa taille.

Voici l'exemple de code complet pour ScrollView et ListView.

<ScrollView
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:id="@+id/scrollView6" Android:fillViewport="true">
    <LinearLayout
        Android:orientation="vertical"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent">
        ....
        <ListView
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:id="@+id/lv_transList" Android:layout_gravity="top"
            Android:layout_marginTop="5dp"/>
        ....
    </LinearLayout>
</ScrollView>
33
acyn

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>

Dans le fichier Java Créez un objet de votre customListview au lieu de ListView, comme: NonScrollListView non_scroll_list = (NonScrollListView) findViewById (R.id.lv_nonscroll_list);

15
    public static void setListViewHeightBasedOnChildren(ListView listView) {
    // 获取ListView对应的Adapter
    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter == null) {
        return;
    }

    int totalHeight = 0;
    for (int i = 0, len = listAdapter.getCount(); i < len; i++) { // listAdapter.getCount()返回数据项的数目
        View listItem = listAdapter.getView(i, null, listView);
        listItem.measure(0, 0); // 计算子项View 的宽高
        totalHeight += listItem.getMeasuredHeight(); // 统计所有子项的总高度
    }

    ViewGroup.LayoutParams params = listView.getLayoutParams();
    params.height = totalHeight
            + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
    // listView.getDividerHeight()获取子项间分隔符占用的高度
    // params.height最后得到整个ListView完整显示需要的高度
    listView.setLayoutParams(params);
}

vous pouvez utiliser ce code pour listview dans scrollview

8
Su Zhenpeng

Vous pouvez le résoudre en ajoutant Android:fillViewport="true" à votre ScrollView.

<ScrollView
      Android:layout_width="match_parent"
      Android:layout_height="match_parent"
      Android:background="@color/white"
      Android:fillViewport="true"
      Android:scrollbars="vertical">

<ListView
      Android:id="@+id/statusList"
      Android:layout_width="fill_parent"
      Android:layout_height="wrap_content"
      Android:animationCache="false"
      Android:divider="@null"
      Android:scrollingCache="false"
      Android:smoothScrollbar="true" />

</ScrollView>


avant d’utiliser cette propriété, il n’y avait qu’un enfant de ma liste. après utilisation, toutes les lignes ou enfants de la liste sont visibles.

8
MV53

Ce code résoudra votre problème si vous avez implémenté seulement un ListView dans un code.

Si vous utilisez RelativeLayout comme enfant ListView, ce code renvoie une exception NullPointerException ici listItem.measure (0, 0); , à cause de RelativeLayout.Et la solution est de placer votre Relativelayout dans un LinearLayout et tout se passera bien.

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);
    listView.requestLayout();
}
6
krunal shah

Je vais le laisser ici au cas où quelqu'un serait confronté au même problème. Je devais mettre un ListView à l'intérieur d'un ScrollView. ListView avec en-tête n'était pas une option pour plusieurs raisons. Ni était une option d'utiliser LinearLayout au lieu de ListView. J'ai donc suivi la solution acceptée, mais cela n'a pas fonctionné, car les éléments de la liste avaient une mise en page complexe avec plusieurs lignes et chaque élément de la vue liste avait une hauteur variable. La taille n'a pas été mesurée correctement. La solution consistait à mesurer chaque élément de la méthode getView () de ListView Adapter.

@Override
public View getView(int position, View view, ViewGroup parent) {
    ViewHolder holder;
    if (view == null) {
        . . .
        view.setTag(holder);
    } else holder = (ViewHolder)view.getTag();
    . . .

    // measure ListView item (to solve 'ListView inside ScrollView' problem)
    view.measure(View.MeasureSpec.makeMeasureSpec(
                    View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED),
            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
    return view;
}
5
Alexander Zhak

Vous pouvez facilement mettre ListView dans ScrollView! Il suffit de changer la hauteur de ListView par programmation , comme ceci:

    ViewGroup.LayoutParams listViewParams = (ViewGroup.LayoutParams)listView.getLayoutParams();
    listViewParams.height = 400;
    listView.requestLayout();

Cela fonctionne parfaitement!

4
Taras Okunev

Fait après beaucoup de R & D:

fragment_one.xml devrait ressembler à:

<?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:id="@+id/scrollViewParent"
    Android:orientation="vertical" >

    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:orientation="vertical" >

        <RelativeLayout
            Android:layout_width="match_parent"
            Android:layout_height="400dip" >

            <ListView
                Android:id="@+id/listView"
                Android:layout_width="match_parent"
                Android:layout_height="match_parent" />

            <View
                Android:id="@+id/customView"
                Android:layout_width="fill_parent"
                Android:layout_height="fill_parent"
                Android:background="@Android:color/transparent" />
        </RelativeLayout>

        <!-- Your other elements are here -->

    </LinearLayout>

</ScrollView>

Votre classe Java de FragmentOne.Java ressemble à:

private ListView listView;
private View customView

onCreateView

listView = (ListView) rootView.findViewById(R.id.listView);
scrollViewParent = (ScrollView)rootView.findViewById(R.id.scrollViewParent);
customView = (View)rootView.findViewById(R.id.customView);

customView.setOnTouchListener(new View.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.
                        scrollViewParent.requestDisallowInterceptTouchEvent(true);
                        // Disable touch on transparent view
                        return false;

                    case MotionEvent.ACTION_UP:
                        // Allow ScrollView to intercept touch events.
                        scrollViewParent.requestDisallowInterceptTouchEvent(false);
                        return true;

                    case MotionEvent.ACTION_MOVE:
                        scrollViewParent.requestDisallowInterceptTouchEvent(true);
                        return false;

                    default:
                        return true;
                }
            }
        });
4
Hiren Patel

Ne faites rien dans Parent ScrollView. Faites ceci uniquement à l'enfant ListView. Tout fonctionnera parfaitement. 

mListView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                mScrollView.requestDisallowInterceptTouchEvent(true);
               int action = event.getActionMasked();
                switch (action) {
                    case MotionEvent.ACTION_UP:
                        mScrollView.requestDisallowInterceptTouchEvent(false);
                        break;
                }
                return false;
            }
        });
4
Sibin

J'ai eu un problème similaire au problème posé par l'affiche originale - comment faire défiler la liste dans le défilement - et cette réponse a résolu mon problème . Désactiver le défilement d'un ListView contenu dans un ScrollView

Je n'ai pas appelé de nouveaux fragments dans des mises en page existantes ou quoi que ce soit, comme le faisait l'OP, afin que mon code ressemble à ceci:

<ScrollView
    Android:id="@+id/scrollView1"
    Android:layout_width="match_parent"
    Android:layout_height="0dp"
    Android:layout_weight="2"
    Android:fillViewport="true"
    Android:gravity="top" >

 <LinearLayout
        Android:id="@+id/foodItemActvity_linearLayout_fragments"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:orientation="vertical" >


    <TextView
       Android:id="@+id/fragment_dds_review_textView_label"
       Android:layout_width="wrap_content"
       Android:layout_height="wrap_content"
       Android:text="Reviews:"
       Android:textAppearance="?android:attr/textAppearanceMedium" />

   <ListView
       Android:id="@+id/my_listView"
       Android:layout_width="match_parent"
       Android:layout_height="wrap_content">
   </ListView>

</LinearLayout>

</ScrollView>

Essentiellement, je vérifie la longueur de la liste avant de l'appeler et, lorsque je l'appelle, je la fixe à cette longueur. Dans votre classe Java, utilisez cette fonction:

public static void justifyListViewHeightBasedOnChildren (ListView listView) {

    ListAdapter adapter = listView.getAdapter();

    if (adapter == null) {
        return;
    }
    ViewGroup vg = listView;
    int totalHeight = 0;
    for (int i = 0; i < adapter.getCount(); i++) {
        View listItem = adapter.getView(i, null, vg);
        listItem.measure(0, 0);
        totalHeight += listItem.getMeasuredHeight();
    }

    ViewGroup.LayoutParams par = listView.getLayoutParams();
    par.height = totalHeight + (listView.getDividerHeight() * (adapter.getCount() - 1));
    listView.setLayoutParams(par);
    listView.requestLayout();
}

Et appelez la fonction comme ceci:

justifyListViewHeightBasedOnChildren(listView);

Le résultat est une liste sans barre de défilement, la totalité de la liste étant affichée, qui défile avec la barre de défilement de la vue.

3
CHarris

Vous pouvez tout mettre en disposition linéaire. C'est-à-dire, créez une disposition linéaire et il aura 2 enfants, scrollview et une autre disposition linéaire Donnez-leur des poids de mise en page et voilà:

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="fill_parent"
Android:orientation="vertical" >

<ScrollView
    Android:layout_width="fill_parent"
    Android:layout_height="0dip" Android:layout_weight="0.8">

    <LinearLayout
        Android:id="@+id/seTaskActivityRoot"
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:background="@color/white"
        Android:orientation="vertical" >

        <TextView
            Android:id="@+id/textView1"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:layout_weight="1"
            Android:text="@string/taskName" />


        <Spinner
            Android:id="@+id/seTaskPrioritiesSP"
            Android:layout_width="fill_parent"
            Android:layout_height="wrap_content"
            Android:layout_weight="1" />

        <TextView
            Android:id="@+id/textView4"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:layout_weight="1"
            Android:text="@string/taskTargetInNumeric" />

        <Spinner
            Android:id="@+id/seTaskUnitsSP"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:layout_weight="1" />

        <TextView
            Android:id="@+id/textView6"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:layout_weight="1"
            Android:text="@string/newTaskCurrentStatus" />

        <EditText
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:layout_weight="1"
            Android:ems="10"
            Android:hint="@string/addTaskCurrentStatus"
            Android:inputType="numberDecimal" />


    </LinearLayout>
</ScrollView>

<LinearLayout
    Android:layout_width="match_parent"
    Android:layout_height="0dip"
    Android:orientation="vertical" Android:layout_weight="0.2">

    <TextView
        Android:id="@+id/textView8"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="TextView" />

    <ListView
        Android:id="@+id/logList"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content" >
    </ListView>

</LinearLayout>

3
Jeyhun Karimov

Comme d'autres l'avaient déjà mentionné, n'utilisez pas ListView dans un ScrollView.

Pour contourner le problème, vous pouvez utiliser LinearLayout, tout en conservant un aspect ordonné - remplissez votre LinearLayout avec un adaptateur, comme vous le feriez avec un ListView

Vous pouvez utiliser cette classe comme remplacement de LinearLayout prenant en charge les adaptateurs.

import Android.content.Context;
import Android.database.DataSetObserver;
import Android.util.AttributeSet;
import Android.view.View;
import Android.view.ViewGroup;
import Android.widget.BaseAdapter;
import Android.widget.LinearLayout;

public class AdaptableLinearLayout extends LinearLayout {

private BaseAdapter mAdapter;

private int mItemCount = 0;

private boolean mDisableChildrenWhenDisabled = false;

private int mWidthMeasureSpec;
private int mHeightMeasureSpec;


public AdaptableLinearLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    // TODO Auto-generated constructor stub
}

public BaseAdapter getAdapter() {
    return mAdapter;
}

public void setAdapter(BaseAdapter adapter) {
    mAdapter = adapter;
    adapter.registerDataSetObserver(new DataSetObserver() {
        @Override
        public void onChanged() {
            updateLayout();
            super.onChanged();
        }

        @Override
        public void onInvalidated() {
            updateLayout();
            super.onInvalidated();
        }
    });
    updateLayout();
}

private void updateLayout() {
    mItemCount = mAdapter.getCount();
    requestLayout();
    invalidate();
}

/**
 * set size for the current View
 */
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    mWidthMeasureSpec = widthMeasureSpec;
    mHeightMeasureSpec = heightMeasureSpec;

    removeAllViewsInLayout();
    for (int i = 0; i < mItemCount; i++) {
        makeAndAddView(i);
    }
}

private View makeAndAddView(int position) {
    View child;

    // Nothing found in the recycler -- ask the adapter for a view
    child = mAdapter.getView(position, null, this);

    // Position the view
    setUpChild(child, position);

    return child;

}

private void setUpChild(View child, int position) {

    ViewGroup.LayoutParams lp = child.getLayoutParams();
    if (lp == null) {
        lp = generateDefaultLayoutParams();
    }
    addViewInLayout(child, position, lp);

    // Get measure specs
    int childHeightSpec = ViewGroup.getChildMeasureSpec(mHeightMeasureSpec, getPaddingTop() + getPaddingBottom(), lp.height);
    int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec, getPaddingLeft() + getPaddingRight(), lp.width);

    // Measure child
    child.measure(childWidthSpec, childHeightSpec);

    int childLeft;
    int childRight;

    // Position vertically based on gravity setting
    int childTop = getPaddingTop() + ((getMeasuredHeight() - getPaddingBottom() - getPaddingTop() - child.getMeasuredHeight()) / 2);
    int childBottom = childTop + child.getMeasuredHeight();

    int width = child.getMeasuredWidth();
    childLeft = 0;
    childRight = childLeft + width;

    child.layout(childLeft, childTop, childRight, childBottom);

    if (mDisableChildrenWhenDisabled) {
        child.setEnabled(isEnabled());
    }
}
}
3
AAverin

Vous ne devez jamais utiliser un objet ScrollView avec un objet ListView, car ListView prend en charge son propre défilement vertical. Plus important encore, cette opération annule toutes les optimisations importantes dans ListView pour traiter les grandes listes, car cela oblige effectivement ListView à afficher la liste complète des éléments pour remplir le conteneur infini fourni par ScrollView.

http://developer.Android.com/reference/Android/widget/ScrollView.html

3
Muhammad Asim

Mettre à jour

<ScrollView
Android:id="@+id/scrollView1"
Android:layout_width="match_parent"
Android:layout_height="0dp"
Android:layout_weight="2"
Android:fillViewport="true"
Android:gravity="top" >

<LinearLayout
    Android:id="@+id/foodItemActvity_linearLayout_fragments"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:orientation="vertical" >
</LinearLayout>

à 

<ScrollView
Android:id="@+id/scrollView1"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_weight="2"
Android:fillViewport="true"
Android:gravity="top" >

<LinearLayout
    Android:id="@+id/foodItemActvity_linearLayout_fragments"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:orientation="vertical" >
</LinearLayout>

Le point ici est que vous essayez de définir la hauteur à 0dp (fixe)

2
Rajnish Mishra

trouvé une solution pour scrollview -> viewpager -> FragmentPagerAdapter -> fragment -> listview dynamique, mais je ne suis pas l'auteur. il y a des bugs, mais au moins ça marche

public class CustomPager extends ViewPager {

    private View mCurrentView;

    public CustomPager(Context context) {
        super(context);
    }

    public CustomPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mCurrentView == null) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }
        int height = 0;
        mCurrentView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        int h = mCurrentView.getMeasuredHeight();
        if (h > height) height = h;
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    public void measureCurrentView(View currentView) {
        mCurrentView = currentView;
        this.post(new Runnable() {
            @Override
            public void run() {
                requestLayout();
            }
        });
    }

    public int measureFragment(View view) {
        if (view == null)
            return 0;

        view.measure(0, 0);
        return view.getMeasuredHeight();
    }
}


public class MyPagerAdapter extends FragmentPagerAdapter {

    private List<Fragment> fragments;
    private int mCurrentPosition = -1;


    public MyPagerAdapter(FragmentManager fm) {
        super(fm);//or u can set them separately, but dont forget to call notifyDataSetChanged()
        this.fragments = new ArrayList<Fragment>();
        fragments.add(new FirstFragment());
        fragments.add(new SecondFragment());
        fragments.add(new ThirdFragment());
        fragments.add(new FourthFragment());
    }

    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        super.setPrimaryItem(container, position, object);
        if (position != mCurrentPosition) {
            Fragment fragment = (Fragment) object;
            CustomPager pager = (CustomPager) container;
            if (fragment != null && fragment.getView() != null) {
                mCurrentPosition = position;
                pager.measureCurrentView(fragment.getView());
            }
        }
    }

    @Override
    public Fragment getItem(int position) {
        return fragments.get(position);
    }

    @Override
    public int getCount() {
        return fragments.size();
    }
}

fragments disposition peut être n'importe quoi

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools" Android:layout_width="match_parent"
Android:orientation="vertical"
    Android:layout_height="match_parent" tools:context="nevet.me.wcviewpagersample.FirstFragment">


    <ListView
        Android:id="@+id/lv1"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:background="#991199"/>
</LinearLayout>

alors quelque part juste

lv = (ListView) view.findViewById(R.id.lv1);
        lv.setAdapter(arrayAdapter);
        setListViewHeightBasedOnChildren(lv);
    }

    public static void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null)
            return;

        int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),
                View.MeasureSpec.UNSPECIFIED);
        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,
                        LinearLayout.LayoutParams.WRAP_CONTENT));

            view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
            totalHeight += view.getMeasuredHeight();
        }
        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight
                + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
        listView.requestLayout();
    }
2
bedman

Mon exigence est d'inclure un ListView d'éléments de taille égale dans un ScrollView. J'ai essayé quelques-unes des autres solutions énumérées ici, aucune ne semblait dimensionner correctement le ListView (trop peu d'espace ou trop). Voici ce qui a fonctionné pour moi:

    public static void expandListViewHeight(ListView listView) {
    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter == null)
        return;

    ViewGroup.LayoutParams params = listView.getLayoutParams();
    listView.measure(0, 0);
    params.height = listView.getMeasuredHeight() * listAdapter.getCount() + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
    listView.setLayoutParams(params);
}

J'espère que ça aide quelqu'un.

2
Malcolm Bryant

En XML:

<com.example.util.NestedListView
                    Android:layout_marginTop="10dp"
                    Android:id="@+id/listview"
                    Android:layout_width="fill_parent"
                    Android:layout_height="fill_parent"
                    Android:divider="@null"

                    Android:layout_below="@+id/rl_delivery_type" >
                </com.example.util.NestedListView>

En Java:

public class NestedListView extends ListView implements View.OnTouchListener, AbsListView.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;
    }
}
1
Makvin

Ok, voici ma réponse. La méthode qui corrige la hauteur de ListView est suffisamment fermée, mais pas parfaite. Si la plupart des objets ont la même hauteur, cela fonctionne bien. Mais au cas où ce ne serait pas le cas, il y aurait un gros problème. J'ai essayé plusieurs fois, et quand j'ai mis la valeur de listItem.getMeasureHeight et de listItem.getMeasuerWidth dans le journal, j'ai vu que les valeurs de largeur variaient beaucoup, ce qui n'est pas prévu ici, car tout l'élément dans la même liste devrait avoir la même largeur. Et voilà le bogue: 

Certaines utilisaient la mesure (0, 0), ce qui rendait la vue non liée, dans les deux sens, et la largeur devenait sauvage. Certains ont essayé d’obtenirWidth of listView, mais ensuite, il renvoie 0, sans signification. 

Lorsque je lis plus en détail la manière dont Android rend la vue, je me rends compte que toutes ces tentatives ne permettent pas d’obtenir la réponse recherchée, à moins que cette fonction ne soit exécutée après le rendu de la vue. 

Cette fois, j'utilise getViewTreeObserver sur le ListView que je veux corriger, puis addOnGlobalLayoutListener. Dans cette méthode, je déclare un nouvel objet OnGlobalLayoutListener, dans lequel, cette fois, getWidth renvoie la largeur réelle de ListView. 

private void getLayoutWidth(final ListView lv, final int pad){
        //final ArrayList<Integer> width = new ArrayList<Integer>();

        ViewTreeObserver vto = lv.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                lv.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                //width.add(layout.getMeasuredWidth());
                int width = lv.getMeasuredWidth();
                ListUtils.setDynamicHeight(lv, width, pad);
            }
        });
    }

public static class ListUtils {
        //private static final int UNBOUNDED = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        public static void setDynamicHeight(ListView mListView, int width, int pad) {
            ListAdapter mListAdapter = mListView.getAdapter();
            mListView.getParent();
            if (mListAdapter == null) {
                // when adapter is null
                return;
            }
            int height = 0;


            int desiredWidth = View.MeasureSpec.makeMeasureSpec(width - 2*pad, View.MeasureSpec.EXACTLY);
            for (int i = 0; i < mListAdapter.getCount(); i++) {
                View listItem = mListAdapter.getView(i, null, mListView);

                listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
                //listItem.measure(UNBOUNDED, UNBOUNDED);
                height += listItem.getMeasuredHeight() + 2*pad;
                Log.v("ViewHeight :", mListAdapter.getClass().toString() + " " + listItem.getMeasuredHeight() + "--" + listItem.getMeasuredWidth());
            }
            ViewGroup.LayoutParams params = mListView.getLayoutParams();
            params.height = height + (mListView.getDividerHeight() * (mListAdapter.getCount() - 1));
            mListView.setLayoutParams(params);
            mListView.requestLayout();
        }
    }

Le pavé de valeur est le remplissage que j'ai défini dans la présentation ListView. 

1
Nguyen Quang Anh

en utilisant ce ListView a travaillé pour moi

   package net.londatiga.Android.widget;

      import Android.util.AttributeSet;
      import Android.view.ViewGroup;
      import Android.widget.ListView;
      import Android.content.Context;

   public class ExpandableHeightListView extends ListView
      {

    boolean expanded = false;

      public ExpandableHeightListView(Context context)
    {
    super(context);
}

public ExpandableHeightListView(Context context, AttributeSet attrs)
{
    super(context, attrs);
}

public ExpandableHeightListView(Context context, AttributeSet attrs,
        int defStyle)
{
    super(context, attrs, defStyle);
}

public boolean isExpanded()
{
    return expanded;
}

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
    // HACK! TAKE THAT Android!
    if (isExpanded())
    {
        // Calculate entire height by providing a very large height hint.
        // But do not use the highest 2 bits of this integer; those are
        // reserved for the MeasureSpec mode.
        int expandSpec = MeasureSpec.makeMeasureSpec(
                Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);

        ViewGroup.LayoutParams params = getLayoutParams();
        params.height = getMeasuredHeight();
    }
    else
    {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}

public void setExpanded(boolean expanded)
{
    this.expanded = expanded;
}
}

et en xml

            <com.pakagename.ExpandableHeightListView
                Android:id="@+id/expandableHeightListView"
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content" >
            </com.Example.ExpandableHeightListView>

et dans MainActivity 

  ExpandableHeightListView listView = new ExpandableHeightListView(this);
    listview=(ExpandableHeightListView)findViewById(R.id.expandableHeightListView);
   listView.setAdapter(adapter); //set your adaper
   listView.setExpanded(true);

Reportez-vous à cet article pour plus d'informations et savoir comment conserver gridview dans la vue par défilement

1
Manohar Reddy

Si, pour une raison quelconque, vous ne souhaitez pas utiliser addHeaderView et addFooterView, par ex. Lorsque vous avez plusieurs listes, une bonne idée serait de réutiliser ListAdapter pour remplir une simple LinearLayout afin de ne pas avoir de fonctionnalité de défilement.

Si vous possédez déjà un fragment entier dérivé de ListFragment et souhaitez le convertir en un fragment similaire avec LinearLayout simple sans faire défiler (par exemple, pour le mettre dans ScrollView), vous pouvez implémenter un fragment d'adaptateur comme ceci:

// converts listFragment to linearLayout (no scrolling)
// please call init() after fragment is inflated to set listFragment to convert
public class ListAsArrayFragment extends Fragment {
    public ListAsArrayFragment() {}

    private ListFragment mListFragment;
    private LinearLayout mRootView;


    // please call me!
    public void init(Activity activity, ListFragment listFragment){
        mListFragment = listFragment;
        mListFragment.onAttach(activity);
        mListFragment.getListAdapter().registerDataSetObserver(new DataSetObserver() {
            @Override
            public void onChanged() {
                super.onChanged();
                refreshView();
            }
        });
    }


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // create an empty vertical LinearLayout as the root view of this fragment
        mRootView = new LinearLayout(getActivity());
        mRootView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        mRootView.setOrientation(LinearLayout.VERTICAL);
        return mRootView;
    }

    // reusing views for performance
    // todo: support for more than one view type
    ArrayList<View> mViewsToReuse = new ArrayList<>();
    ArrayList<View> mCurrentViews = new ArrayList<>();

    // re-add views to linearLayout
    void refreshView(){

        // remove old views from linearLayout and move them to mViewsToReuse
        mRootView.removeAllViews();
        mViewsToReuse.addAll(mCurrentViews);
        mCurrentViews.clear();

        // create new views
        for(int i=0; i<mListFragment.getListAdapter().getCount(); ++i){
            View viewToReuse = null;
            if(!mViewsToReuse.isEmpty()){
                viewToReuse = mViewsToReuse.get(mViewsToReuse.size()-1);
                mViewsToReuse.remove(mViewsToReuse.size()-1);
            }
            final View view = mListFragment.getListAdapter().getView(i, viewToReuse, mRootView);
            ViewGroup.LayoutParams oldParams = view.getLayoutParams();
            view.setLayoutParams(new LinearLayout.LayoutParams(oldParams.width, oldParams.height));
            final int finalI = i;

            // pass click events to listFragment
            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mListFragment.onListItemClick(null, view, finalI, finalI);
                }
            });
            mRootView.addView(view);
            mCurrentViews.add(view);
        }
    }

Vous pouvez également vouloir transférer onCreate, onPause, onResume, etc. vers le fragment d'origine en fonction de vos besoins ou essayez l'héritage au lieu de la composition (mais remplacez certaines méthodes afin que le fragment d'origine ne soit pas réellement lié à la hiérarchie de présentation); mais je voulais isoler le fragment original autant que possible, car nous n'avons besoin que d'extraire sa ListAdapter. Si vous appelez la variable setListAdapter du fragment original dans onAttach, c'est probablement suffisant.

Voici comment utiliser ListAsArrayFragment pour inclure OriginalListFragment sans défilement. Dans l'activité parent onCreate:

ListAsArrayFragment fragment = (ListAsArrayFragment) getFragmentManager().findFragmentById(R.id.someFragmentId);
OriginalListFragment originalFragment = new OriginalListFragment();
fragment.init(this, originalFragment);

// now access originalFragment.getListAdapter() to modify list entries
// and remember to call notifyDatasetChanged()
1
atablash

trouvé une solution pour scrollview -> viewpager -> FragmentPagerAdapter -> fragment -> listview dynamique, mais je ne suis pas l'auteur. 

public class CustomPager extends ViewPager {

    private View mCurrentView;

    public CustomPager(Context context) {
        super(context);
    }

    public CustomPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mCurrentView == null) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }
        int height = 0;
        mCurrentView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        int h = mCurrentView.getMeasuredHeight();
        if (h > height) height = h;
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    public void measureCurrentView(View currentView) {
        mCurrentView = currentView;
        this.post(new Runnable() {
            @Override
            public void run() {
                requestLayout();
            }
        });
    }

    public int measureFragment(View view) {
        if (view == null)
            return 0;

        view.measure(0, 0);
        return view.getMeasuredHeight();
    }
}


public class MyPagerAdapter extends FragmentPagerAdapter {

    private List<Fragment> fragments;
    private int mCurrentPosition = -1;


    public MyPagerAdapter(FragmentManager fm) {
        super(fm);//or u can set them separately, but dont forget to call notifyDataSetChanged()
        this.fragments = new ArrayList<Fragment>();
        fragments.add(new FirstFragment());
        fragments.add(new SecondFragment());
        fragments.add(new ThirdFragment());
        fragments.add(new FourthFragment());
    }

    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        super.setPrimaryItem(container, position, object);
        if (position != mCurrentPosition) {
            Fragment fragment = (Fragment) object;
            CustomPager pager = (CustomPager) container;
            if (fragment != null && fragment.getView() != null) {
                mCurrentPosition = position;
                pager.measureCurrentView(fragment.getView());
            }
        }
    }

    @Override
    public Fragment getItem(int position) {
        return fragments.get(position);
    }

    @Override
    public int getCount() {
        return fragments.size();
    }
}

fragments disposition peut être n'importe quoi

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools" Android:layout_width="match_parent"
Android:orientation="vertical"
    Android:layout_height="match_parent" tools:context="nevet.me.wcviewpagersample.FirstFragment">


    <ListView
        Android:id="@+id/lv1"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:background="#991199"/>
</LinearLayout>

alors quelque part juste

 lv = (ListView) view.findViewById(R.id.lv1);
        lv.setAdapter(arrayAdapter);
        setListViewHeightBasedOnChildren(lv);
    }

    public static void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null)
            return;

        int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),
                View.MeasureSpec.UNSPECIFIED);
        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,
                        LinearLayout.LayoutParams.WRAP_CONTENT));

            view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
            totalHeight += view.getMeasuredHeight();
        }
        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight
                + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
        listView.requestLayout();
    }
1
qwerty

Cela a fonctionné pour moi ( link1 , link2 ):

  • 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 = View.MeasureSpec.makeMeasureSpec(
                        Integer.MAX_VALUE >> 2, View.MeasureSpec.AT_MOST);
                super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
                ViewGroup.LayoutParams params = getLayoutParams();
                params.height = getMeasuredHeight();
            }
        }
    
  • Dans votre fichier de mise en page

    <ScrollView 
     xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent"
    Android:fillViewport="true">
    
        <RelativeLayout
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content" >
    
            <!-- com.Example Changed with your Package name -->
    
            <com.thedeveloperworldisyours.view.NonScrollListView
                Android:id="@+id/lv_nonscroll_list"
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content" >
            </com.thedeveloperworldisyours.view.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>
    
  • Créez un objet de votre customListview au lieu de ListView comme:

     NonScrollListView non_scroll_list = (NonScrollListView) findViewById(R.id.lv_nonscroll_list);
    
1

Ne mettez JAMAIS une ListView dans une ScrollView! Vous pouvez trouver plus d'informations à ce sujet sur Google . Dans votre cas, utilisez une LinearLayout au lieu de ListView et ajoutez les éléments par programme.

1
SimonSays

Il suffit d'appeler cette fonction après avoir assigné l'adaptateur à listview 

public static void setListViewHeightBasedOnChildren
            (ListView listView) {
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null) return;

        int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),
                View.MeasureSpec.UNSPECIFIED);
        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,
                    ViewGroup.LayoutParams.WRAP_CONTENT));

            view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
            totalHeight += view.getMeasuredHeight();
        }

        ViewGroup.LayoutParams params = listView.getLayoutParams();

        params.height = totalHeight + (listView.getDividerHeight() *
                (listAdapter.getCount() - 1));

        listView.setLayoutParams(params);
        listView.requestLayout();
    } 
0
farshid bohlooli
  • Il n’est pas possible d’utiliser Scroll-view dans List-view car List-view a déjà une propriété scrolling.
  • Pour utiliser list-view dans Scroll-view, vous pouvez suivre ces étapes qui ont fonctionné pour moi:

    1) Créez NonScrollListView Java qui désactive la propriété de défilement par défaut de list-view. et le code est ci-dessous

    package your-package-structure;
    
    import Android.content.Context;
    import Android.util.AttributeSet;
    import Android.view.ViewGroup;
    import Android.widget.ListView;
    
    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();
      }
    }
    

    2) Créez maintenant un fichier XML contenant NestedScrollView et NonScrollListView à l'intérieur de cette liste pour lister vos éléments Cela fera défiler tout votre écran avec toutes les vues.

     

            <LinearLayout
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:layout_weight="1"
                Android:orientation="vertical">
                <ViewFlipper
    
                    Android:id="@+id/v_flipper"
                    Android:layout_width="match_parent"
                    Android:layout_height="130dp">
                </ViewFlipper>
                <TextView
                    Android:layout_width="match_parent"
                    Android:layout_height="wrap_content"
    
                    Android:text="SHOP"
                    Android:textSize="15dp"
                    Android:textStyle="bold"
                    Android:gravity="center"
                    Android:padding="5dp"
                    Android:layout_marginTop="15dp"
                    Android:layout_marginBottom="5dp"
                    Android:layout_marginLeft="8dp"
                    Android:layout_marginRight="8dp"/>
                <View
                    Android:layout_width="match_parent"
                    Android:layout_height="1dp"
    
                    Android:layout_marginBottom="8dp"
                    Android:layout_marginLeft="8dp"
                    Android:layout_marginRight="8dp"
                    Android:background="#ddd"/>
            </LinearLayout>
            <LinearLayout
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:orientation="vertical"
                Android:layout_weight="1"
                >
                <com.abc.xyz.NonScrollListView
                    Android:id="@+id/listview"
    
                    Android:divider="@null"
                    Android:layout_width="match_parent"
                    Android:layout_marginBottom="10dp"
                    Android:layout_height="match_parent"
                    Android:padding="8dp">
                </com.abc.xyz.NonScrollListView>
            </LinearLayout>
    
           <LinearLayout
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
    
                Android:gravity="bottom">
                <include layout="@layout/footer" />
            </LinearLayout>
    
        </LinearLayout>
    

     

    3) Maintenant dans la classe Java, home.Java définit NonScrollListView au lieu de Listview.

    package comabc.xyz.landscapeapp;
    import Android.content.Intent;
    import Android.support.annotation.NonNull;
    import Android.support.annotation.Nullable;
    import Android.support.v4.app.Fragment;
    import Android.os.Bundle;
    import Android.support.v4.app.FragmentTransaction;
    import Android.util.Log;
    import Android.view.LayoutInflater;
    import Android.view.View;
    import Android.view.ViewGroup;
    import Android.widget.AdapterView;
    import Android.widget.Button;
    import Android.widget.ImageView;
    
    import Android.widget.ListView;
    import Android.widget.Toast;
    import Android.widget.Toolbar;
    import Android.widget.ViewFlipper;
    

    public class home s'étend au fragment { int pos = 0; ViewFlipper v_flipper;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.activity_home, container, false);
        return view;
    }
    
    @Override
    public void onViewCreated(@NonNull final View view, @Nullable Bundle savedInstanceState) {
        NonScrollListView listView = (NonScrollListView) view.findViewById(R.id.listview);
        customAdapter customAdapter = new customAdapter(getActivity());
        listView.setAdapter(customAdapter);
        listView.setFocusable(false);
    
        customAdapter.notifyDataSetChanged();
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Log.d("listview click", "onItemClick: ");
               /* FragmentTransaction fr = getFragmentManager().beginTransaction().replace(R.id.fragment_container, new productdisplay());
    
                fr.putExtra("Position", position);
                fr.addToBackStack("tag");
                fr.commit();*/
                Intent intent = new Intent(getActivity(), productdisplay.class);
                intent.putExtra("Position", position);
                startActivity(intent);
            }
        });
    
    
        //image slider
        int images[] = {R.drawable.slide1, R.drawable.slide2, R.drawable.slide3};
        v_flipper = view.findViewById(R.id.v_flipper);
        for (int image : images) {
            flipperImages(image);
    
        }
    }
    
    private void flipperImages(int image) {
        ImageView imageView = new ImageView(getActivity());
        imageView.setBackgroundResource(image);
    
        v_flipper.addView(imageView);
        v_flipper.setFlipInterval(4000);
        v_flipper.setAutoStart(true);
    
        v_flipper.setInAnimation(getActivity(), Android.R.anim.slide_in_left);
        v_flipper.setOutAnimation(getActivity(), Android.R.anim.slide_out_right);
    }
    }
    

    Note: J'ai utilisé Fragments ici.

0
user8235005

Il suffit de définir la valeur de la hauteur requise dans un attribut height de listview dans une vue de défilement parent. Il défilera avec l'élément enfant des autres parents.

0
Shibu Tamang