Android list view inside a scroll view

后端 未结 30 2092
一向
一向 2020-11-21 13:43

I have an android layout which has a scrollView with a number of elements with in it. At the bottom of the scrollView I have a listView

相关标签:
30条回答
  • 2020-11-21 13:46

    This code will solve your problem if you have implemented just a ListView in a code.

    If you are using RelativeLayout as ListView child than this code return a NullPointerException here listItem.measure(0, 0);, because of RelativeLayout.And the solution is put your Relativelayout inside a LinearLayout and it will work fine.

    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();
    }
    
    0 讨论(0)
  • 2020-11-21 13:46

    I'll leave it here in case anyone will face the same issue. I had to put a ListView inside a ScrollView. ListView with header was not an option by a number of reasons. Neither was an option to use LinearLayout instead of ListView. So I followed the accepted solution, but it didn't work because items in the list had complex layout with multiple rows and each listview item was of variable height. Height was measured not properly. The solution was to measure each item inside ListView Adapter's getView() method.

    @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;
    }
    
    0 讨论(0)
  • 2020-11-21 13:46

    I had a similar problem to the issue posed by the Original Poster - how to make the listview scroll inside the scrollview - and this answer solved my problem. Disable scrolling of a ListView contained within a ScrollView

    I didn't call new fragments into existing layouts or anything like that, like the OP was doing, so my code would look something like this :

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

    Basically what I am doing is checking the length of the listview before I call it and when I call it I make it into that length. In your java class use this function:

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

    And call the function like this:

    justifyListViewHeightBasedOnChildren(listView);
    

    The result is a listview with no scrollbar, the whole length of the listview being displayed, that scrolls with the scroll bar of the scrollview.

    0 讨论(0)
  • 2020-11-21 13:48

    found a solution for scrollview -> viewpager -> FragmentPagerAdapter -> fragment -> dynamic listview, but im not the author.

    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 layout can be anything

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

    then somewhere just

     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();
        }
    
    0 讨论(0)
  • 2020-11-21 13:50

    Just set the value of required height in a listview height attribute inside a parent scrollview. It will scroll along with other parents child item.

    0 讨论(0)
  • 2020-11-21 13:51

    using this ListView Worked for me

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

    and in xml

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

    and in MainActivity

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

    Refer This article for more info and also to know how to keep gridview inside scroll view

    0 讨论(0)
提交回复
热议问题