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
Android Marshmallow Request Permission
Android Asynctask Sending Callbacks to Ui
Example: Communication Between Activity and Service Using Messaging
Android Accelerometer Accuracy (Inertial Navigation)
How to Send Image Via Mms in Android
How to Build a Horizontal Listview With Recyclerview
Android Completely Transparent Status Bar
Detect Application Heap Size in Android
Determining the Size of an Android View At Runtime
How to Stop Edittext from Gaining Focus When an Activity Starts in Android
Why 'Pageradapter::Notifydatasetchanged' Is Not Updating the View
Replace Fragment Inside a Viewpager
Android Check Internet Connection
How to Send a Json Object Over Request With Android
Android - Implementing Startforeground For a Service