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:
The cell's width can be found at activity/fragment level and passed to the adapter before rendering time. Use something like this:
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:
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()
Try This:- add this in your ImageView--> android:adjustViewBounds="true"
Instead of getting the view height and width from
onCreateViewHolder
get it fromonBindViewHolder
as below:I hope this will help you!!