SwipeRefreshLayout wrap_content not working with ListView in Dialogfragment

668 views Asked by At

I'm trying to set SwipeRefreshLayout which contains children ListView to wrap_content in a DialogFragment.

to actually make the Dialog wrap the height of it's childrens, because it's always filling the window height even if the ListView has only one item.

Layout :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:id="@+id/footer"
        android:layout_alignParentBottom="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="@color/devider_line"/>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="@string/myButton" />

    </RelativeLayout>

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:layout_above="@id/footer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ListView
            android:id="@+id/listview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

</RelativeLayout>

Result :

enter image description here

I need to make the DialogFragment window scale height depending on the ListView items, not always fill the window height.

by making either the SwipeRefreshLayout or the ListView to wrap the content (items).

I've tried alot of ways to do that but nothing worked.

How can i achieve this?

Update :

The SwipeRefreshLayout itself is filling the entire window height and ignoring wrap_content.

i replaced ListView with RecyclerView and the RecyclerView is wrapping content height, which is good. but still SwipeRefreshLayout is filling height forcing the DialogFragment to cover all the Window.

i'm setting the dialog height to wrap_content :

@Override
public void onResume() {
    getDialog().getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);

    super.onResume();
}

Here's list_item.xml :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="18dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="0.4"
                android:gravity="start"
                android:orientation="horizontal"
                android:weightSum="1">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:gravity="start"
                    android:text="@string/default_text" />

            </LinearLayout>

            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="0.6"
                android:gravity="end"
                android:orientation="horizontal"
                android:weightSum="1">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@string/default_text"
                    android:textAlignment="center" />

            </LinearLayout>

        </LinearLayout>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_below="@+id/container"
        android:background="@color/devider_color" />

</RelativeLayout>

Update 2 :

Using RecyclerView and Wrapping it with LinearLayout so wrap_content works on it.

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

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#00ffff">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <androidx.recyclerview.widget.RecyclerView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="#ff00ff" />

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/myButton" />

        </LinearLayout>

    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

</LinearLayout>

But still SwipeRefreshLayout is filling the height.

enter image description here

1

There are 1 answers

11
snachmsm On

ListView is behaving like this, try to override this behavior with this subclass

public class WrapingHeightListView extends ListView {

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

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

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

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }

}

use <com.yourpackage.WrapingHeightListView... in your XML instead of current <ListView ... tag

or you may switch to RecyclerView, it handles wrap_content height properly (but this will need also some small adapter refactoring)