Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get width of CardView in Adapter.onBindViewHolder

I have a list of posts and most of them are pictures (simply put it is posts just like G+ or FB apps). Each post entry has an image aspect ratio, so I can set image height based on it's width even before image was loaded from server, so card layout wouldn't change on load.

The problem is layout_width="match_parent" set for both card and post image. When I get width of cardview it is zero. So i can't calculate height.

For now the only solution I see is to take width of parent container (RecyclerView) and deduct all paddings, but it doesn't look like a good solution.

Is there any other way to do it?

Here is an example of adapter code

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    ....
    int width = holder.itemView.getWidth();
    ....
    //do some calculations
}

Layouts (without irrelevant parts)

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:descendantFocusability="blocksDescendants"
    android:foreground="?android:attr/selectableItemBackground"
    card_view:cardBackgroundColor="#ffffff"
    card_view:cardCornerRadius="3dp">

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <include
            android:id="@+id/includedPost"
            layout="@layout/post_details" />    
    </RelativeLayout>
</android.support.v7.widget.CardView>

includedPost:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/postImage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/commenterImage"
        android:minHeight="120dp"
        android:scaleType="centerCrop" />

</RelativeLayout>
like image 534
Andrew Avatar asked Oct 28 '14 10:10

Andrew


1 Answers

when onBind or onViewAttachedToWindow is called, the child is not measured yet so you cannot get the width. Even if these calls were made after child is measured, what you are trying to do would not be a good practice because changing height will require a new measurement.

If you are using LinearLayoutManager, it will give the full width to the child (expect RecyclerView padding and child's margins). It is not great but OK to derive your height from there.

Another (more flexible) approach here is to create a custom ImageView that keeps your aspect ratio. When onBind is called, you'll set the desired aspect ratio of your custom ImageView. When on measure is called, it will measure depending on your aspect ratio.

class MyImageView extends ImageVIew {
      ....
      private float mScale = 1f;

      public void setScale(int scale) {
          mScale = scale;
      }

      @Override
      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

          super.onMeasure(widthMeasureSpec, heightMeasureSpec);

          int width = getMeasuredWidth();
          setMeasuredDimension(width, width * mScale);
      }
}

So in your onBind method, you call setScale on the ImageView depending on your w/h ratio.

I have not tested but this approach should work as desired.

like image 58
yigit Avatar answered Nov 13 '22 19:11

yigit