Android List View Inside a Scroll View

Android list view inside a scroll view

For any Child view to scroll inside a ScrollView. Anything like ListView, RecyclerView, etc. You just have to replace ScrollView with androidx.core.widget.NestedScrollView in your current xml and then magic happens.

Below is a sample xml code :

<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">

<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp"
android:paddingBottom="20dp">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Recycler View inside a Scroll View"
android:textColor="@color/black"
android:textSize="@dimen/_20sp"
android:textStyle="bold" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Below is a Recycler View as an example."
android:textSize="16sp" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@id/et_damaged_qty" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="This textview automatically goes below the Recycler View."
android:textSize="16sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.core.widget.NestedScrollView>

Now you can get rid of all the ugly hacks you did to get around with nested scrolling.

Android: Listview inside ScrollView

Don't put ListView inside ScrollView - first rule of android clud :)
Instead you can use simple LinearLayout and manage you ListView items inside it.
Or you can add Header/Footer Views to the ListView and using it without scrollview.

ListView inside ScrollView in android

You need to use ExpandableHeightListView.

https://github.com/paolorotolo/ExpandableHeightListView

ListView inside ScrollView is not scrolling on Android

You shouldn't put a ListView inside a ScrollView because the ListView class implements its own scrolling and it just doesn't receive gestures because they all are handled by the parent ScrollView. I strongly recommend you to simplify your layout somehow. For example you can add views you want to be scrolled to the ListView as headers or footers.

UPDATE:

Starting from API Level 21 (Lollipop) nested scroll containers are officially supported by Android SDK. There're a bunch of methods in View and ViewGroup classes which provide this functionality. To make nested scrolling work on the Lollipop you have to enable it for a child scroll view by adding android:nestedScrollingEnabled="true" to its XML declaration or by explicitly calling setNestedScrollingEnabled(true).

If you want to make nested scrolling work on pre-Lollipop devices, which you probably do, you have to use corresponding utility classes from the Support library. First you have to replace you ScrollView with NestedScrollView. The latter implements both NestedScrollingParent and NestedScrollingChild so it can be used as a parent or a child scroll container.

But ListView doesn't support nested scrolling, therefore you need to subclass it and implement NestedScrollingChild. Fortunately, the Support library provides NestedScrollingChildHelper class, so you just have to create an instance of this class and call its methods from the corresponding methods of your view class.

Android ListView inside ScrollView not proper

Putting the ListView inside a ScrollView means the ListView will not go to its full height. Take out the ScrollView surrounding the ListView and this should work for you :) ListView itself is scrollable.

ListView inside scrollView

You do not have to do anything special in layout.xml file nor handle anything on the parent ScrollView. You only have to handle the child ListView. You can also use this code to use any type of child view inside a ScrollView & perform Touch operations.

Just add these lines of code in your java class :

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

If you put ListView inside a ScrollView then all the ListView does not stretch to its full height. Below is a method to fix this issue.

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

To use this method just pass the ListView inside this method :

ListView list = (ListView) view.findViewById(R.id.ls);
setListViewHeightBasedOnChildren(list);
For using with ExpandableListView - credit 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);

For ListView with variable items height use the below link :

ListView inside ScrollView is not scrolling on Android

For Library to directly implementing in your code - credit Paolo Rotolo

https://github.com/PaoloRotolo/ExpandableHeightListView

How can I put a ListView into a ScrollView without it collapsing?

Using a ListView to make it not scroll is extremely expensive and goes against the whole purpose of ListView. You should NOT do this. Just use a LinearLayout instead.

Android: Scroll whole fragment with ListView inside

Alright, after combining multiple answers, I have the solution that I needed.

First

I needed to use a NestedScrollView instead of a regular ScrollView.

It solves the conflict between the two scroll containers (ScrollView and ListView).

Reference: Android: ScrollView vs NestedScrollView

NOTE: My list content is dynamic, so it can be too short to fill the remaining space. I had to set android:fillViewport="true" on the NestedScrollView. If the list is longer than the remaining space, it will not cause any trouble.

layout.xml

<?xml version="1.0" encoding="utf-8"?>

<androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<androidx.cardview.widget.CardView
android:id="@+id/card1"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- NOTE: constraints properties are missing from here for easier reading -->

<!-- card content here -->

</androidx.cardview.widget.CardView>

<androidx.cardview.widget.CardView
android:id="@+id/card2"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- NOTE: constraints properties are missing from here for easier reading -->

<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- NOTE: this will change in step 3 -->

</androidx.cardview.widget.CardView>

</androidx.constraintlayout.widget.ConstraintLayout>

</androidx.core.widget.NestedScrollView>

Second

Following the steps above will make the ListView collapse to the height of its first item. To solve this, I needed to create a subclass from ListView and override its onMeasure() method, so it can calculate the proper height at runtime.

Reference: Android - NestedScrollView which contains ExpandableListView doesn't scroll when expanded

NonScrollListView.java

package my.package.name

import ...

public class NonScrollListView extends ListView {

// NOTE: right click -> create constructors matching super

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

Third

I needed to use my custom View instead of the regular ListView in my layout XML.

layout.xml excerpt

<my.package.name.NonScrollListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

This way I managed to make it work. Both cards move together on scroll, even if I tap the ListView area.

I don't know whether it causes performance issues with really long lists, because mine contains a few dozen items at most, but I have no problem on a low end Galaxy A20e.



Related Topics



Leave a reply



Submit