Reputation: 545
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>
Upvotes: 30
Views: 76712
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
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
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
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