StaggeredGridLayoutManager without ItemDecoration needs onScroll to arrange the items in matrix/Grid format. Is there a way to avoid ItemDecoration because I don't want decorator between items.
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL))
//Without addItemDecoration - it requires a scroll to occupy all the columns
recycler.addItemDecoration(new CustomInsetsDecoration(context));
without item decoration --
A
B
C
D
E
F
with item decoration (with min 1px/dp apart)
A B C
D E F
What I want:
ABC
DEF
A,B,C,D,E,F are all are ImageViews (of different sizes)
My item layout - a very simple - relativelayout and an Imageview:
<?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">
<ImageView
android:id="#+id/item_browse_cover"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop" />
</RelativeLayout>
Any input is appreciated.
Thanks in advance.
Use the following MarginDecorator class with a 0 margin
public class MarginDecorator extends RecyclerView.ItemDecoration {
private int margin;
public MarginDecorator(int margin) {
this.margin = margin;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.top = margin;
outRect.bottom = margin;
outRect.left = margin;
outRect.right = margin;
}
}
Also try using the setGapStrategy()
Related
I am using recylerview and gridlayout manager with cardviews for each row, my row view(childview) is not responsive at all.
I want to show 15 cardviews in such a way that in portrait mode all my 15 childview should be visible and my recyclerview should not be scrollable whereas in landscape mode it should act vise versa( should be scrollable)
I have tried many soultions suggested on SO but nothing seems to be working.
current behaviour on different screen sizes are as follows
In the above attached screen shot ,the 3rd column, 4th and 5th row are not visible
In the above given screen my ui fits perfectly in portrait mode but in landscape i can't see all the cardviews.
in the screenshot attached above ,5th row is not visible and in the landscape mode there are some responsivness errors.
cardview.xml
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cardview="http://schemas.android.com/apk/res-auto"
android:layout_width="127dp"
android:layout_height="118dp"
android:layout_margin="5dp"
cardview:cardCornerRadius="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="#+id/mReminder_Image_Id"
android:layout_width="match_parent"
android:layout_height="90dp"
android:scaleType="fitXY"
android:background="#ffffff"/>
<TextView
android:id="#+id/mReminder_Text_Id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textColor="#2d2d2d"
android:textSize="13sp"
android:text="Reminder texts"/>
</LinearLayout>
</android.support.v7.widget.CardView>
fragment_reminders.xml
<LinearLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".Fragments.Reminders">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#color/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Reminders"
android:textSize="20dp"
android:textStyle="bold"
android:textColor="#color/tab_background"
android:layout_gravity="center" />
</android.support.v7.widget.Toolbar>
<android.support.v7.widget.RecyclerView
android:id="#+id/mRecyclerView_id"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
Can anyone guide me to solve this .
Thanks .
you can use this:
recyclerView.setLayoutManager(new RecyclerView.GridLayoutManager(this, span_count)
You could have a
res/values/ints.xml file with <integer> elements, giving the integer a name (name attribute) and value (text of the <integer> node). You could also have res/values-w600dp/ints.xml or res/values-land or other variations of the resource, where you provide
different values to use for different screen sizes. Then, at runtime, call
getResources().getInteger() to retrieve the correct value of the resource to use
for the current device, and use that in your GridLayoutManager constructor. Now,
you are in control over how many columns there are, by controlling how many spans
are supplied to the constructor.
https://developer.android.com/training/multiscreen/screensizes
Another approach, suggested by Chiu-Ki Chan, is to create a subclass of
RecyclerView, on which you provide a custom attribute for a desired approximate
column width. Then, in your subclass’ onMeasure() method, you can calculate the
number of spans to use to give you the desired column width.
https://developer.android.com/reference/android/support/v7/widget/GridLayoutManager.html#GridLayoutManager(android.content.Context,%20int)
https://developer.android.com/reference/android/support/v7/widget/RecyclerView#setlayoutmanager
create a class as follows:
import android.graphics.Rect;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
public class EqualSpacingItemDecoration extends RecyclerView.ItemDecoration {
private final int spacing;
private int displayMode;
public static final int HORIZONTAL = 0;
public static final int VERTICAL = 1;
public static final int GRID = 2;
public EqualSpacingItemDecoration(int spacing) {
this(spacing, -1);
}
public EqualSpacingItemDecoration(int spacing, int displayMode) {
this.spacing = spacing;
this.displayMode = displayMode;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildViewHolder(view).getAdapterPosition();
int itemCount = state.getItemCount();
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
setSpacingForDirection(outRect, layoutManager, position, itemCount);
}
private void setSpacingForDirection(Rect outRect,
RecyclerView.LayoutManager layoutManager,
int position,
int itemCount) {
// Resolve display mode automatically
if (displayMode == -1) {
displayMode = resolveDisplayMode(layoutManager);
}
switch (displayMode) {
case HORIZONTAL:
outRect.left = spacing;
outRect.right = position == itemCount - 1 ? spacing : 0;
outRect.top = spacing;
outRect.bottom = spacing;
break;
case VERTICAL:
outRect.left = spacing;
outRect.right = spacing;
outRect.top = spacing;
outRect.bottom = position == itemCount - 1 ? spacing : 0;
break;
case GRID:
if (layoutManager instanceof GridLayoutManager) {
GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
int cols = gridLayoutManager.getSpanCount();
int rows = itemCount / cols;
outRect.left = spacing;
outRect.right = position % cols == cols - 1 ? spacing : 0;
outRect.top = spacing;
outRect.bottom = position / cols == rows - 1 ? spacing : 0;
}
break;
}
}
private int resolveDisplayMode(RecyclerView.LayoutManager layoutManager) {
if (layoutManager instanceof GridLayoutManager) return GRID;
if (layoutManager.canScrollHorizontally()) return HORIZONTAL;
return VERTICAL;
}
}
and for using it with your recycler view:
1)for grid view:
recyclerView.addItemDecoration(new EqualSpacingItemDecoration(<sizeofpixels>, EqualSpacingItemDecoration.GRID));
2)for vertical view:
recyclerView.addItemDecoration(new EqualSpacingItemDecoration(<sizeofpixels>, EqualSpacingItemDecoration.VERTICAL));
3)for horizontal view:
recyclerView.addItemDecoration(new EqualSpacingItemDecoration(<sizeofpixels>, EqualSpacingItemDecoration.HORIZONTAL));
hope this helps you.
I would like to inset a RecyclerView ItemDecorator divider to left align with a TextView (the item title) inside the list element that is constrained to be 72dp from the parent left side. Something like we see here in the Google Material Design Docs. I assume that I need to somehow reference the layout params on the titleTextView, but am not sure how to do that from my ItemDecorator code, as I seem to be able to only get the params which is the ConstraintLayout, and not the textview itself. Any help or pointers in the right direction would be greatly appreciated! The relevant ItemDecorator code, where I try to get the textView param looks something like this:
for (int i = 0; i < recyclerView.getChildCount() - 1; ++i) {
View child = recyclerView.getChildAt(i);
RecyclerView.LayoutParams params =(RecyclerView.LayoutParams) child.getLayoutParams();
//this just gives me the constraint layout, not the TextView params, how to reference the textViewParams!?
The RecyclerView looks like this:
<android.support.v7.widget.RecyclerView
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/myList"
android:name="com.example.Something"
android:layout_width="0dp"
android:layout_height="0dp"
app:layoutManager="LinearLayoutManager"
tools:context=".controllers.fragments.ExampleFragment"
tools:listitem="#layout/fragment_something"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
The list item xml is a constraint layout with some TextViews, and the relevant portion looks like this:
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="72dp">
<ImageView
android:id="#+id/myImageView"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginLeft="16dp"
app:layout_constraintLeft_toLeftOf="parent"
tools:src="#drawable/ic_menu_manage"
android:src="#drawable/ic_menu_manage"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="16dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="16dp" />
<TextView
android:id="#+id/titleTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginLeft="72dp"
android:layout_marginTop="20dp"
android:text="MyTitle"
android:textAppearance="#style/TextAppearance.AppCompat.Subhead"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="#+id/textView5"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="SampleTitle" />
...
</android.support.constraint.ConstraintLayout>
use a custom item decorator.
class CustomItemDecoration(context: Context) : RecyclerView.ItemDecoration()
{
private val mDivider: Drawable = context.resources.getDrawable(R.drawable.custom_item_divider) // this is a shape that i want to use
override fun onDrawOver(c: Canvas,
parent: RecyclerView,
state: RecyclerView.State)
{
val left = parent.paddingLeft // change to how much padding u want to add here .
val right = parent.width - parent.paddingRight
val childCount = parent.childCount
for (i in 0 until childCount)
{
val child = parent.getChildAt(i)
val params = child.layoutParams as RecyclerView.LayoutParams
val top = child.bottom + params.bottomMargin
val bottom = top + mDivider.intrinsicHeight
mDivider.setBounds(left, top, right, bottom)
mDivider.draw(c)
}
}
}
you set it like that
recyclerView.addItemDecoration(CustomItemDecoration(context))
Since the ConstraintLayout is a ViewGroup, it is possible to access the child of the ConstraintLayout from inside of the ItemDecorator by simply doing something like:
public class MyItemDivider extends RecyclerView.ItemDecoration {
....some code here
#Override
public void onDrawOver(Canvas canvas, RecyclerView recyclerView,
RecyclerView.State state) {
super.onDrawOver(canvas, recyclerView, state);
for (int i = 0; i < recyclerView.getChildCount() - 1; ++i) {
ViewGroup item = (ViewGroup) recyclerView.getChildAt(i);
//for now the titleText is at index 1 of constraint layout
TextView titleChild = (TextView) item.getChildAt(1);
int titleTextLeftMargin = titleChild.getLeft();
//this would probably be less brittle
//but I would need to somehow change the context for this to be doable?
//View titleChild = item.findViewById(R.id.contractListProductNameTextView);
...some more code here
divider.setBounds(titleTextLeftMargin, top, right, bottom);
divider.draw(canvas);
}
}
}
Since you already know by how much you have to inset the divider from the left side (calculate it from your layout if you don't know), all you need to do is convert that dp value to px as shown here and set it as the left bound in your custom ItemDecoration.
public class InsetDividerDecoration extends RecyclerView.ItemDecoration {
private final int insetValueInDp = 72; // in your case
#Override
public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
int dividerLeft = (int) (insetValueInDp * Resources.getSystem().getDisplayMetrics().density);
...
}
}
And use it in your recycler view -
recyclerView.addItemDecoration(new InsetDividerDecoration());
I am using GridLayoutManager of recyclerview to display custom gallery in my app. I have implementated all the features like gallery. But there is a small thing Im stuck with. In one row I have 3 images. But I need to reduce the space between the images. While doing so , I dont want to show more than 3 images in a row, but the image size (if needed) can increase.
You can use custom RecyclerViewItemDecorator:
public class RecyclerViewItemDecorator extends RecyclerView.ItemDecoration {
private int spaceInPixels;
public RecyclerViewItemDecorator(int spaceInPixels) {
this.spaceInPixels = spaceInPixels;
}
#Override
public void getItemOffsets(Rect outRect, View view,
RecyclerView parent, RecyclerView.State state) {
outRect.left = spaceInPixels;
outRect.right = spaceInPixels;
outRect.bottom = spaceInPixels;
if (parent.getChildLayoutPosition(view) == 0) {
outRect.top = spaceInPixels;
} else {
outRect.top = 0;
}
}
}
Then add it to your RecyclerView:
// For example 10 pixels
int spaceInPixels = 10;
mRecyclerView.addItemDecoration(new RecyclerViewItemDecorator(spaceInPixels));
Hope it helps!
Use this for the recycler view,
this.mRecyclerView.setLayoutManager(new GridLayoutManager(getContext(), 3));
this.mRecyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getContext())
.color(Color.DKGRAY)
.build());
this.mRecyclerView.addItemDecoration(new VerticalDividerItemDecoration.Builder(getContext())
.color(Color.DKGRAY)
.build());
and in your layout file for each item, set the Image in such a way to meet the edges of the container.
eg:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/RlayoutGrid"
android:layout_width="220dp"
android:layout_height="170dp"
android:background="#android:color/black">
<ImageView
android:id="#+id/prefence_imageButton"
android:layout_width="match_parent"
android:layout_height="170dp"
android:background="#android:color/black"
android:focusable="false"
android:focusableInTouchMode="false"
android:scaleType="fitXY"
/>
</RelativeLayout>
and add this to your build.gradle
compile 'com.yqritc:recyclerview-flexibledivider:1.2.4'
To remove spacing you can use outRect.setEmpty()
RecyclerView.ItemDecoration divider = new RecyclerView.ItemDecoration(){
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.setEmpty();
}
};
grid.addItemDecoration(divider);
I'm trying to create a dynamic RecyclerView layout. I am using a GridLayoutManager with three columns.
I need to wrap each grid item and center the columns (like attached).
I have tried a StaggeredGridLayout, I have tried a WrapGridLayoutManager but neither of these worked.
Here is my RecyclerView:
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/categories_grid"
android:layout_marginTop="#dimen/feed_item_margin"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
and my RecyclerView item:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:background="#drawable/first_time_category_unselected"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<TextView
android:id="#+id/category_name"
android:layout_marginLeft="#dimen/feed_item_margin"
android:layout_gravity="center_vertical"
android:textColor="#color/black_colour"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:id="#+id/category_status_icon"
android:layout_gravity="center_vertical"
android:background="#drawable/icon_follow"
android:layout_marginLeft="#dimen/feed_item_margin"
android:layout_marginRight="#dimen/feed_item_margin"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
This is the decoration I'm using to implement grid spacing:
public class SpacesItemDecoration extends RecyclerView.ItemDecoration {
private int halfSpace;
public SpacesItemDecoration(int space) {
this.halfSpace = space / 2;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
if (parent.getPaddingLeft() != halfSpace) {
parent.setPadding(halfSpace, halfSpace, halfSpace, halfSpace);
parent.setClipToPadding(false);
}
outRect.top = halfSpace;
outRect.bottom = halfSpace;
outRect.left = halfSpace;
outRect.right = halfSpace;
}
}
This is what I'm trying to achieve:
This is what I am getting:
If anyone can help on this I'd greatly appreciate it
You can use Staggered Grid Layout Manager
as
StagaggeredGridLayoutManager = new StaggeredGridLayoutManager(3, LinearLayoutManager.HORIZONTAL );
recyclerView.setLayoutManager(gaggeredGridLayoutManager);
Here is Link for reference
Use this in recyclerView you could not arrange as you shown
<cuneyt.example.com.tagview.Tag.TagView
android:id="#+id/tag_group"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp" />
Download repo from GIT https://github.com/Cutta/TagView
TagView tagGroup = (TagView)findviewById(R.id.tag_view);
//You can add one tag
tagGroup.addTag(Tag tag);
//You can add multiple tag via ArrayList
tagGroup.addTags(ArrayList tags);
//Via string array
addTags(String[] tags);
//set click listener
tagGroup.setOnTagClickListener(new OnTagClickListener() {
#Override
public void onTagClick(Tag tag, int position) {
}
});
//set delete listener
tagGroup.setOnTagDeleteListener(new OnTagDeleteListener() {
#Override
public void onTagDeleted(final TagView view, final Tag tag, final int position) {
}
});
How do I make WRAP_CONTENT work on a RecyclerView
I have a StaggeredGrid in a RecyclerView and I am trying to dynamically set the image height in the onBindViewHolder. I thought the StaggeredGrid was supposed to handle all this automatically, so I set android:layout_width="match_parent and android:scaleType="fitStart on the ImageView, but there is lots of gaps around the image.
Since the StaggeredGrid isn't living up to it, I'm trying to help it a bit by defining the image height dynamically in the onBindViewHolder. I have the width and height of the image ahead of time, but the cell width of the grid isn't available. I tried holder.cardView.getLayoutParams().width and getMeasuredWidth(), but they both return zero or small numbers. I know there are other places the cell width would be available, but I really need it in the onBindViewHolder event so I can set and adjust the image.
Any ideas on how to achieve this by leveraging the StaggeredGrid? Any advice or experience is appreciated!
In my activity is this:
mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(mLayoutManager);
In my adapter:
#Override
public void onBindViewHolder(MyAdapter.MyViewHolder holder, int position) {
MyModel item = mData.get(position);
int imageWidth = item.getFeatured_image().getWidth();
int imageHeight = item.getFeatured_image().getHeight();
int cellWidth = 540; // <==== how to find dynamically??!!
ViewGroup.LayoutParams imageLayoutParams = holder.thumbnailImageView.getLayoutParams();
imageLayoutParams.width = cellWidth;
imageLayoutParams.height = imageHeight * cellWidth / imageWidth;
holder.thumbnailImageView.setLayoutParams(imageLayoutParams);
MediaHelper.displayImage(item, holder.thumbnailImageView);
}
In my layout:
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/row_my_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
card_view:cardCornerRadius="2dp">
<ImageView
android:id="#+id/row_my_thumbnail_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:scaleType="fitStart" />
<TextView
android:id="#+id/row_my_title_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#CCFFFFFF"
android:textStyle="bold"
android:padding="5dp" />
</android.support.v7.widget.CardView>
I also tried to add this which does give me the cell width, but the onGlobalLayout event gets triggered way after the image is set and adjusted in the onBindViewHolder event so it's too late.
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
final View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.row_my_post, parent, false);
final MyViewHolder viewHolder = new MyViewHolder(view);
ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
int viewWidth = view.getWidth();
int viewHeight = view.getHeight();
}
});
}
return viewHolder;
}
Here is the gaps which are random due to the various image sizes. What I would like is for ALL images to be the width of the cell and let the height of the image and cell adjust dynamically:
Try This:- add this in your ImageView--> android:adjustViewBounds="true"
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/row_my_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
card_view:cardCornerRadius="2dp">
<ImageView
android:id="#+id/row_my_thumbnail_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:adjustViewBounds="true"/>
<TextView
android:id="#+id/row_my_title_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#CCFFFFFF"
android:textStyle="bold"
android:padding="5dp" />
</android.support.v7.widget.CardView>
Instead of getting the view height and width from onCreateViewHolder get it from onBindViewHolder as below:
#Override
public void onBindViewHolder(final MyAdapter.MyViewHolder holder, int position)
{
holder.itemView.post(new Runnable()
{
#Override
public void run()
{
MyModel item = mData.get(position);
int imageWidth = item.getFeatured_image().getWidth();
int imageHeight = item.getFeatured_image().getHeight();
int cellWidth = 540; // <==== how to find dynamically??!!
cellWidth = holder.itemView.getWidth();// this will give you width dynamically
ViewGroup.LayoutParams imageLayoutParams = holder.thumbnailImageView.getLayoutParams();
imageLayoutParams.width = cellWidth;
imageLayoutParams.height = imageHeight * cellWidth / imageWidth;
holder.thumbnailImageView.setLayoutParams(imageLayoutParams);
MediaHelper.displayImage(item, holder.thumbnailImageView);
}
});
}
I hope this will help you!!
The cell's width can be found at activity/fragment level and passed to the adapter before rendering time. Use something like this:
this.staggeredGridLayoutManager.getWidth() / this.staggeredGridLayoutManager.getSpanCount()
With this approach, you will be able to compute the cell's height before any rendering and avoid that initial flick introduced by post run approach.
Also, the image's aspect ratio will be preserved and you can reserve the required space before image load.
Be also aware that if any margins/paddings are present you should include them into previous calculation. Something like:
(this.staggeredGridLayoutManager.getWidth() - marginsAndOrPaddings) / this.staggeredGridLayoutManager.getSpanCount()
Update:
Starting with support packages 23.2.0, and at this point of lifecycle, this.staggeredGridLayoutManager.getWidth() returns 0. The total width can be achieved with this.recyclerView.getWidth()