Android list view inside a scroll view

后端 未结 30 2091
一向
一向 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 14:03
    • It is not possible to use Scroll-view inside List-view as List-view already has scrolling property.
    • To use list-view inside Scroll-view you can follow these steps which worked for me :

      1) Create NonScrollListView java file that disable the default scrolling property of list-view. and code is below

      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) Now create xml file which which has NestedScrollView and inside this use NonScrollListView for listing your items. This will make your entire screen to scroll with all the views.

              <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="#ffffd"/>
              </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) Now in java class i.e, home.java define NonScrollListView instead of 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 extends 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: I used Fragments here.

    0 讨论(0)
  • 2020-11-21 14:05

    Don't do anything in Parent ScrollView. Only do this to child ListView. Everything will work perfectly.

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

    If for some reason you don't want to use addHeaderView and addFooterView, e.g. when you have several lists, a good idea would be to reuse ListAdapter to populate a simple LinearLayout so there's no scrolling functionality.

    If you already have a whole fragment derived from ListFragment and want to convert it to a similar fragment with simple LinearLayout without scrolling instead (e.g. to put it in ScrollView), you can implement an adapter fragment like this:

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

    You may also want to forward onCreate, onPause, onResume, etc. to the original fragment depending on your needs or try inheritance instead of composition (but override certain methods so original fragment is not actually attached to layout hierarchy); but I wanted to isolate original fragment as much as possible, because we only need to extract its ListAdapter. If you call original fragment's setListAdapter in onAttach, that's probably enough.

    Here's how to use ListAsArrayFragment to include OriginalListFragment without scrolling. In parent activity's 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()
    
    0 讨论(0)
  • 2020-11-21 14:08

    Just call this function after assign adapter to 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 讨论(0)
  • 2020-11-21 14:09

    You Create Custom ListView Which is 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();    
                }
            }
    

    In Your Layout Resources File

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

    In Java File Create a object of your customListview instead of ListView like : NonScrollListView non_scroll_list = (NonScrollListView) findViewById(R.id.lv_nonscroll_list);

    0 讨论(0)
  • 2020-11-21 14:09

    You may solve it by adding android:fillViewport="true" to your 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>
    


    before use that property, there was only one child of my list view is visible. after using that all the rows or child of list are visible.

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