1

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

Amr SubZero
  • 1,196
  • 5
  • 19
  • 30

1 Answers1

0

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)

snachmsm
  • 17,866
  • 3
  • 32
  • 74
  • The extended ListView class maybe working but i can't tell because the SwipeRefreshLayout still filling the entire window ignoring it's wrap_content. is that normal? i'll see RecyclerView but i wish i could stick with ListView. Maybe the RecyclerView it'self also fill parent because the SwipeRefreshLayout doesn't apply wrap_content to itself! – Amr SubZero Oct 12 '20 at 05:59
  • Confirmed that the SwipeRefreshLayout is the thing that filling the entire window, removed it and the RecyclerView wrap_content works. how to deal with SwipeRefreshLayout to wrap_content with RecyclerView within it! – Amr SubZero Oct 12 '20 at 06:27
  • [some](https://stackoverflow.com/questions/40945022/recyclerview-in-swiperefreshlayout-not-wrap-content) [answers](https://stackoverflow.com/questions/54649095/how-to-make-swiperefreshlayout-wrap-content) on stack overflow suggests wrapping `ListView` or `RecyclerView` in `LinearLayout`. And they are confirming that your wrong behavior comes from `SwipeRefreshLayout`, so above subclassed `WrapingHeightListView` may not be needed (still worth trying) – snachmsm Oct 12 '20 at 06:27
  • None of them worked.. i always see the ```SwipeRefreshLayout``` is filling the height ignoring ```wrap_content``` that's the issue, the ```RecyclerView``` works with wrap_content. – Amr SubZero Oct 12 '20 at 06:43
  • can you post list item XML? some another answers are suggesting setting `wrap_content` also to dialogs `Window` like this `dialog.getWindow().setAttributes(lp)` (`lp = new WindowManager.LayoutParams`) – snachmsm Oct 12 '20 at 06:52
  • I've added the ```list_item.xml``` to the above .. and i already set the dialog height to wrap content using ```getDialog().getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);``` on ```@Override onResume()``` – Amr SubZero Oct 12 '20 at 07:06
  • list item looks fine (all `ViewGroup`s have `wrap_content` for height). can you confirm that without `SwipeRefeshLayout` `ListView` is wraping content properly keeping footer visible? I'm asking because you are using `wrap_content` for `RelativeLayout`, in which you have view (footer) with `layout_alignParentBottom`. quote from the [doc](https://developer.android.com/reference/android/widget/RelativeLayout.html): – snachmsm Oct 12 '20 at 07:11
  • `Note that you cannot have a circular dependency between the size of the RelativeLayout and the position of its children. For example, you cannot have a RelativeLayout whose height is set to WRAP_CONTENT and a child set to ALIGN_PARENT_BOTTOM.` Maybe not `SwipeRefreshLayout`, but this one param set for footer makes your dialog expand? – snachmsm Oct 12 '20 at 07:11
  • See last update above.. you're right ```alignParentBottom``` may cause the dialog to fill the window.. but now i removed everything and left the ```SwipeRefreshLayout``` with ```RecyclerView``` and it's still filling the height. – Amr SubZero Oct 12 '20 at 07:32
  • sadly now I don't have a clue, sorry... tough case :/ – snachmsm Oct 12 '20 at 07:45
  • Nevermind, thanks anyway for the help! appreciate it. – Amr SubZero Oct 12 '20 at 07:49