52

I have an item layout where I display an image, product name, and product image. I must display image in 1:1.5 ration using constraint layout. But when I load a small image, below texts not displaying.

Below is my code of item XML:-

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/coordinatorLayoutCartRoot"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.jackandphantom.circularimageview.RoundedImage
            android:id="@+id/imageViewSlider"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:scaleType="centerCrop"
            app:layout_constraintBottom_toTopOf="@id/tvTitle"
            app:layout_constraintDimensionRatio="WH,1:1.4"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:rounded_radius="0"
            tools:src="@tools:sample/avatars" />

        <TextView
            android:id="@+id/tvTitle"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="4dp"
            android:text="Fitted crew neck sweater"
            android:textColor="@color/colorBlack"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/imageViewSlider" />

        <TextView
            android:id="@+id/tvPrice"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="4dp"
            android:text="$34.00"
            android:textColor="@color/colorBlack"
            android:textStyle="bold"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tvTitle" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
  1. Output with long image:- https://i.stack.imgur.com/lm5mX.jpg
  2. Output with small image:- https://i.stack.imgur.com/fGFXu.jpg

And if I replace match_parent with wrap_content, app crashes with below error :-

java.lang.IllegalStateException: Pages must fill the whole ViewPager2 (use match_parent)

Mahesh Babariya
  • 685
  • 2
  • 8
  • 12

23 Answers23

54

I have found out that the problem is in inflating view holder.

I had the same issue and solved it changing

ViewBinding.inflate(inflater)

to

ViewBinding.inflate(inflater, parent, false)
Bresiu
  • 2,123
  • 2
  • 19
  • 31
  • 6
    this not the answer, viewPagger2 always required item layout to match parent height and width. fix contrainstlayout. – Indra As Lesmana Jan 25 '20 at 01:24
  • 3
    This fixed the problem for me. Perhaps without proper reference to the parent view group the view is unable to match_parent. Hence it gets interpreted as wrap_content and throws the above mentioned error. – Alt-Cat Oct 29 '20 at 17:37
27

While struggling with this problem, I figured it out what's the problem was. My use case was I was using androidx.viewpager2.widget.ViewPager2, and calling normal Views in RecyclerView.

If you notice the error carefully you would see something like this:

 java.lang.IllegalStateException: Pages must fill the whole ViewPager2 (use match_parent)
    at androidx.viewpager2.widget.ViewPager2$2.onChildViewAttachedToWindow(ViewPager2.java:170)

Second line is the key to main issue. If you open ViewPager2.java you would see

 private RecyclerView.OnChildAttachStateChangeListener enforceChildFillListener() {
    return new RecyclerView.OnChildAttachStateChangeListener() {
        @Override
        public void onChildViewAttachedToWindow(@NonNull View view) {
            RecyclerView.LayoutParams layoutParams =
                    (RecyclerView.LayoutParams) view.getLayoutParams();
            if (layoutParams.width != LayoutParams.MATCH_PARENT
                    || layoutParams.height != LayoutParams.MATCH_PARENT) {
                throw new IllegalStateException(
                        "Pages must fill the whole ViewPager2 (use match_parent)");
            }
        }

        @Override
        public void onChildViewDetachedFromWindow(@NonNull View view) {
            // nothing
        }
    };
}

Android is not taking the match_parent assigned in xml to attach views. May be future improvements would be done in next release of ViewPager2.

Anyways, for now to fix it, set layout params as MATCH_PARENT explicity.

 view.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

This view is the parent view holding View Pager childs.

In you case it would be androidx.constraintlayout.widget.ConstraintLayout.

 view.setLayoutParams(new ConstraintLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
androidStud
  • 532
  • 4
  • 9
  • Solved using this view.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); – Vishal Kottarathil Apr 30 '20 at 15:38
  • 1
    For me i resolved the issue by using the above line to set params in onCreateViewHolder of the View pager adapter. – Ajith M A Nov 19 '20 at 06:59
  • Good explanation and this solution makes sense. Struggled with it a couple of hours, and finally tried your solution, in my specific situation ( I am using ComposeView in the viewPager) for some reason composeView has not occupied the whole Page. Just added the line for ConstraintLayout int The ViewHolder class and it worked. – Artiom Jun 14 '22 at 15:09
20

set width and height in your adapter item of ViewPager2 match_parent

Raana Yavari
  • 199
  • 1
  • 4
14

Use match_parent to your viewholder layout of ViewPager2

I have the same error, After sometimes I Found the issue in ViewPager2's adapter item, I changed it from wrap_content to match_parent, and it was Fixed.

<ImageView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/iv_banner"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/> <!--Change height here to match_parent-->
Nikunj Paradva
  • 15,332
  • 5
  • 54
  • 65
12

You should to write like this:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val view: View = inflater.inflate(R.layout.yourlayout, parent, false)
    view.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
    return ViewHolder(view)
}
inner class ViewHolder(itemView: View) :
    RecyclerView.ViewHolder(itemView) {
}
RedRainbowGuy
  • 170
  • 1
  • 8
6

For me, the issue was pages (i.e. parent/root layout of the adapter) in ViewPager2 were not match_parent hence the error was java.lang.IllegalStateException: Pages must fill the whole ViewPager2 (use match_parent)

Arpit J.
  • 1,108
  • 12
  • 20
5

viewpager2 item should have match_parent width and height. but IF you are using View Binding you should inflate layout such as fragments:

ViewBinding.inflate(inflater, parent, false)
Ali Zarei
  • 3,523
  • 5
  • 33
  • 44
3

i faced the same problem now , your adapter item width and height has to be match_parent

Amr263
  • 143
  • 2
  • 8
3

Possible scenario is also if you dont use parent in inflater. This crash with exception You have:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OnboardViewHolder {
        return OnboardViewHolder(parent.context.inflate(
                R.layout.view_onboard_item, null, false
        ))
    }

And this works :

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OnboardViewHolder {
        return OnboardViewHolder(parent.context.inflate(
                R.layout.view_onboard_item, parent, false
        ))
    }
Milan Jurkulak
  • 557
  • 3
  • 6
1

I had the same problem. I used ViewPager2 to display the slider. But its XML item was not MATCH_PARENT. After that change the problem was resolved.

saeedmpt
  • 144
  • 1
  • 7
1

I also faced the same issue, and the solution is to set the height as match_parent of your item view i.e layout used in adapter class must have height as MATCH_PARENT

sweet_vish
  • 141
  • 1
  • 8
1

set android:layout_width & android:layout_height to match_parent of ViewPager2 & adapter layout

Parth Desai
  • 196
  • 2
  • 10
1

Viewpager2 by default forces the pages to be MATCH_PARENT, or an exception will be thrown

A solution for that is to do the following before you do anything to the viewpager. This will prevent the viewpager from throwing an exception when the page size is not MATCH_PARENT. Of course you must make your layout wrap_content in order for this to work.

((RecyclerView) yourViewPager2Object.getChildAt(0)).clearOnChildAttachStateChangeListeners();

Further Explanation.

if you go to the viewpager2 code you will find the following, and what we actually do is disabling this behavior.


    /**
     * A lot of places in code rely on an assumption that the page fills the whole ViewPager2.
     *
     * TODO(b/70666617) Allow page width different than width/height 100%/100%
     */
    private RecyclerView.OnChildAttachStateChangeListener enforceChildFillListener() {
        return new RecyclerView.OnChildAttachStateChangeListener() {
            @Override
            public void onChildViewAttachedToWindow(@NonNull View view) {
                RecyclerView.LayoutParams layoutParams =
                        (RecyclerView.LayoutParams) view.getLayoutParams();
                if (layoutParams.width != LayoutParams.MATCH_PARENT
                        || layoutParams.height != LayoutParams.MATCH_PARENT) {
                    throw new IllegalStateException(
                            "Pages must fill the whole ViewPager2 (use match_parent)");
                }
            }

            @Override
            public void onChildViewDetachedFromWindow(@NonNull View view) {
                // nothing
            }
        };
    }

Resources:

https://issuetracker.google.com/issues/70666617 https://gist.github.com/safaorhan/1a541af729c7657426138d18b87d5bd4

هيثم
  • 791
  • 8
  • 11
1

If you are using Data binding, try this on the Adapter class

override fun onCreateViewHolder(
    parent: ViewGroup,
    viewType: Int
): BannerViewHolder {
    return BannerViewHolder(
        HomeShopsBannerCellBinding.inflate(LayoutInflater.from(parent.context),
            parent,  //add this line
            false),  //add this line
        mListener,

    )
}

Also set Match parent for adapter cell layout and viewpager2 layout

Navin Kumar
  • 3,393
  • 3
  • 21
  • 46
0

I solve this by using wrap_content in parent view of ViewPager2

Example:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    tools:context=".presentation.home.view.BannerFragment">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/view_pager_banner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

So it will take the height of the adapter layout.

GunSky7
  • 25
  • 8
0

If you are using the viewpager2 inside the constraint layout just wrap viewpager2 with a relative layout:

<RelativeLayout
    android:id="@+id/sub_service_list_view_cont"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintBottom_toTopOf="@+id/basket"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/view14">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/sub_service_list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>
Bruno Bieri
  • 9,724
  • 11
  • 63
  • 92
Arunachalam k
  • 734
  • 1
  • 7
  • 20
0

I was facing this problem because my viewpager2 was in to a FragmentContainerView with layout_height="wrap_content".

So I changed it to: layout_height="match_parent" and solved the problem :)

Kevin Perez
  • 667
  • 5
  • 17
0

I meet the error as you describe.

First,The problem occured in the recyclerview,so it's no matter with vipager2

Second,What is affected is recycleview's viewholder.

Last,Change the viewholder's width and height,make it is all match parent.

Good luck for you.

Longalei
  • 453
  • 3
  • 8
0

I also faced the same issue but when I change the item view height to match parent instead of wrap content it work fine.

0

for fixed error Pages must fill the whole ViewPager2 (use match_parent) :
Set enough height com.jackandphantom.circularimageview.RoundedImage to match_parent

android:layout_height="match_parent"
0

I faced this problem and I fixed it just by replacing the

android:layout_height="wrap_content" of item of view pager adapter to android:layout_height="match_parent"

Sana Ebadi
  • 6,656
  • 2
  • 44
  • 44
0

If you are using RecyclerView as main component and show viewpager2 in this you should use this way;

Main Body;

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="270dp" <!-- Set height to main body on here -->
    >

    <androidx.viewpager2.widget.ViewPager2
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Item Body;

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"  <!-- This one must be match_parent -->
    >
    <!-- Some components for your item -->
</androidx.constraintlayout.widget.ConstraintLayout>
-1

The layout_width and layout_height of adapter must be match_parent

DavidUps
  • 366
  • 3
  • 9