Shakil Mahmud Shanto
Shakil Mahmud Shanto

Reputation: 545

RecyclerView item height and width change dynamically Android

I am new to android development and I am developing an app where the app downloads pictures from server and show them in a gridView. But some extra spaces are coming up when the app is run on a bigger screen phone. Here are some screenshots. How do I solve this ? I have the model of each item with a fixed height and width of 110dp

My image model :

<?xml version="1.0" encoding="utf-8"?>
<ImageView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="110dp"
    android:layout_height="110dp"
    app:srcCompat="@drawable/post2"
    android:id="@+id/imageView2"
    android:adjustViewBounds="true"
    android:scaleType="centerCrop"
    android:layout_margin="1.5dp" />

My Recycler View :

<android.support.v7.widget.RecyclerView
                android:id="@+id/gallerygrid"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginTop="4dp"
                android:numColumns="auto_fit"
                android:stretchMode="columnWidth"
                android:visibility="visible"
                android:layout_gravity="center">

            </android.support.v7.widget.RecyclerView>

On smaller screen phone

On bigger screen phone

Upvotes: 30

Views: 76712

Answers (4)

Saad Ali Shujaat
Saad Ali Shujaat

Reputation: 469

  • If you are using Constraint layout use constraint Dimens ratio as mentioned above.

    <ImageView
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     app:layout_constraintDimensionRatio="1:1"/>
    
  • else if you are using linear or relative layout.

    <ImageView
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:adjustViewBounds="true" />
    

both will solve your problem but both of them are only recommend if you have small amount of data to populate, these tricks are not recommended for thousands of images, as this will calculate and set height of each item at run time which means this will run on main thread and for thousands of images this will create a laggy scrolling and may result in ANR on low end devices.

There is another work around to minimize this lag.

You can get the width of the imageView at runtime in onBindViewHolder and set the height equals to width or any multiple of width to attain your desired ratio.

 CoroutineScope(Dispatchers.IO).launch {
      val width = holder.image.width

      withContext(Dispatchers.Main){
           holder.image.layoutParams.height = width
      }
  }

Getting the width at background thread will take the load off of Main thread which ultimately results in smooth scrolling.

Upvotes: 1

CoolMind
CoolMind

Reputation: 28783

You can also get RecyclerView width after it's measurement. See How to find width of item in recyclerview?, How to know when the RecyclerView has finished laying down the items?.

For instance,

recyclerView.post {
    val width = recyclerView.width
    ...
}

Upvotes: 1

Aleyam
Aleyam

Reputation: 1245

for those who want to do it in the xml layout (recyclerView item) file you can use a ConstraintLayout by combining

            android:layout_width="match_parent"
            android:layout_height="wrap_content"

and the following code for having a square item

            app:layout_constraintDimensionRatio="4:4"

and don't forget to provide all the constraint that way you can set

            android:layout_width="0dp"
            android:layout_height="0dp"

hence the complete code will be as follow

<androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="1dp"
        android:layout_marginEnd="1dp"
        >

        <ImageView
            android:id="@+id/img_view"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginTop="1dp"
            android:layout_marginBottom="1dp"
            app:layout_constraintDimensionRatio="4:4"
            app:srcCompat="@drawable/event_placeholder"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            android:scaleType="centerCrop"
            />
</androidx.constraintlayout.widget.ConstraintLayout>

Upvotes: 26

Zaki Pathan
Zaki Pathan

Reputation: 1782

Set height and width dynamically according to the screen size. this is the best way to get perfect result.

DisplayMetrics displaymetrics = new DisplayMetrics();
        ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        //if you need three fix imageview in width
        int devicewidth = displaymetrics.widthPixels / 3;

        //if you need 4-5-6 anything fix imageview in height
        int deviceheight = displaymetrics.heightPixels / 4;

        holder.image_view.getLayoutParams().width = devicewidth;

        //if you need same height as width you can set devicewidth in holder.image_view.getLayoutParams().height
        holder.image_view.getLayoutParams().height = deviceheight;

try this in adapter in getview hope you get better result in all device

EDIT: Or to set same height same as width you can set devicewidth in height also like below:

holder.image_view.getLayoutParams().height = devicewidth;

Upvotes: 60

Related Questions