2

So, I'm trying to change the height of a ImageView in the onBindViewHolder method of my recycler view depending on the height of another object in the same view holder. When I access the height with getHeight() I get back 0 as a result for the first few elements - most probably because they are not drawn right now.

The general solution to this problem doesn't work for me, because the recycler view creates and binds a lot of views adding a GlobalLayoutListener to each of them, which seems to mess the thing up giving me wrong results (e.g. just changing the height of the first element).

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

    final ViewHolderDouble doubleHolder = (ViewHolderDouble) holder;

    if (secProduct != null) {
        final ViewTreeObserver observer = doubleHolder.linearLayoutSD.getViewTreeObserver();
        observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {

                int difference = doubleHolder.firstCardView.getHeight() - doubleHolder.secCardView.getHeight();

                if (difference > 0) {
                    ImageView rightImage = doubleHolder.imageViewR;
                    rightImage.getLayoutParams().height = rightImage.getHeight() + difference;
                    rightImage.requestLayout();
                } else if (difference < 0) {
                    ImageView leftImage = doubleHolder.imageViewL;
                    leftImage.getLayoutParams().height = leftImage.getHeight() + (difference * -1);
                    leftImage.requestLayout();
                }

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    doubleHolder.linearLayoutSD.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                    doubleHolder.linearLayoutSD.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                }
            }
        });
    }
}

Is there any way I can access the height of doubleHolder.firstCardView & doubleHolder.secCardView after the views are drawn, so I get the correct height and not 0?

Community
  • 1
  • 1
dabo248
  • 3,367
  • 4
  • 27
  • 37

1 Answers1

0

I had pretty similar task a while ago, so here's how I did it.

First, the adapter. I didn't do much in onBindViewHolder, I just run the method "displayItem" with content - to fill the actual View

@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
    if (position >= contentItems.size()) {
        return;
    }

    ((ContentItemCardView)viewHolder.itemView).displayItem(contentItems.get(position));
}

The key part happens in the ContentItemCardView which extends CardView in my case. Here's short version of it:

public class ContentItemCardView extends CardView {

    @InjectView(R.id.previewImageView)
    ImageView previewImageView;

    @InjectView(R.id.titleTextView)
    TextView titleTextView;

    public ContentItemCardView(Context context){
        super(context);
        ButterKnife.inject(this);
    }

    .....

    public void displayItem(ContentItem contentItem) {
        ....
        titleTextView.setText(contentItem.Title);
        displayPreview(contentItem);
        ....
    }

    public void displayPreview(ContentItem contentItem) {
        int requiredHeight = determineHeight(.....);
        previewImageView.getLayoutParams().height = requiredHeight;
        previewImageView.requestLayout();
        ....
    }

    public int determineHeight() {
        ....
    }
}

So all we have left is to have proper determineHeight() (let's say it should be twice higher, than filled titleTextView):

public int determineHeight() {
    final Resources resources = getResources();
    int screenWidth = resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT ?
            resources.getDisplayMetrics().widthPixels :
            resources.getDisplayMetrics().heightPixels; 

    int widthMeasureSpec = MeasureSpec.makeMeasureSpec(screenWidth, MeasureSpec.AT_MOST);
    int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);

    titleTextView.measure(widthMeasureSpec, heightMeasureSpec);

    return titleTextView.getMeasuredHeight() * 2;
}               

So all you need is to set explicitly the calculated height and requestLayout().

        int requiredHeight = determineHeight(.....);
        previewImageView.getLayoutParams().height = requiredHeight;
        previewImageView.requestLayout();

I hope, it helps.

Konstantin Loginov
  • 15,802
  • 5
  • 58
  • 95