【问题标题】:Get width of CardView in Adapter.onBindViewHolder在 Adapter.onBindViewHolder 中获取 CardView 的宽度
【发布时间】:2014-10-28 10:34:29
【问题描述】:

我有一个帖子列表,其中大部分是图片(简单来说就是帖子,就像 G+ 或 FB 应用程序一样)。每个帖子条目都有一个图像纵横比,因此即使在从服务器加载图像之前,我也可以根据它的宽度设置图像高度,因此卡片布局不会在加载时改变。

问题是layout_width="match_parent" 同时设置了卡片和帖子图像。当我得到卡片视图的宽度时,它为零。所以我无法计算高度。

目前我看到的唯一解决方案是获取父容器(RecyclerView)的宽度并扣除所有填充,但这看起来不是一个好的解决方案。

还有其他方法吗?

这是一个适配器代码示例

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

布局(没有不相关的部分)

<?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>

包含的帖子:

<?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>

【问题讨论】:

  • 你能把部分代码放在你调用getWidth方法的地方吗(结果为0)?
  • 用示例代码更新了我的问题
  • 也许您可以尝试根据文档在onViewAttachedToWindow 中调用getWidth() 方法:“这可以用作用户即将看到视图的合理信号”跨度>
  • 刚试过。它适用于被回收但新创建的视图仍具有等于 0 的宽度。

标签: android android-layout android-recyclerview android-cardview


【解决方案1】:

onBindonViewAttachedToWindow 被调用时,孩子没有测量,所以你不能得到宽度。即使这些电话是在测量孩子之后进行的,您尝试做的也不是一个好习惯,因为改变身高需要重新测量。

如果您使用的是 LinearLayoutManager,它将为孩子提供完整的宽度(预计 RecyclerView 填充和孩子的边距)。从那里得出你的身高不是很好,但可以。

这里的另一种(更灵活)方法是创建一个自定义 ImageView 以保持您的纵横比。调用 onBind 时,您将设置自定义 ImageView 的所需纵横比。 当调用 on measure 时,它​​将根据您的纵横比进行测量。

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);
      }
}

因此,在您的 onBind 方法中,您根据 w/h 比率在 ImageView 上调用 setScale。

我还没有测试过,但这种方法应该可以正常工作。

【讨论】:

  • 真的很棒,但 setMeasuredDimension 在您的示例中有点令人困惑: int width = getMeasuredWidth(); int 高度 = getMeasuredHeight(); setMeasuredDimension((int)(width * mScale), height);
【解决方案2】:

您可以使用毕加索变换来实现这一点。

FitToTargetViewTransformation 类:

import android.graphics.Bitmap;
import android.view.View;

import com.squareup.picasso.Transformation;

/**
 * Picasso Transformation class to fit image to target View size
 */
public class FitToTargetViewTransformation implements Transformation {
  private View view;

  public FitToTargetViewTransformation(View view) {
    this.view = view;
  }

  @Override
  public Bitmap transform(Bitmap source) {
    int targetWidth = view.getWidth();

    double aspectRatio = (double) source.getHeight() / (double) source.getWidth();
    int targetHeight = (int) (targetWidth * aspectRatio);
    if (source.getHeight() >= source.getWidth()) {
      return source;
    }
    Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
    if (result != source) {
      // Same bitmap is returned if sizes are the same
      source.recycle();
    }
    return result;
  }

  @Override
  public String key() {
    return "transformation" + " desiredWidth";
  }
}

在 onBindViewHolder 的某个地方,您可以执行以下操作:

Picasso.with(context)
    .load(AVATAR_ENDPOINT)
    .transform(new FitToTargetViewTransformation(feedViewHolder.icAvatar))
    .into(feedViewHolder.icAvatar);

【讨论】:

  • 我不相信它可以解决我的问题。我对缩放图像没有问题。我的问题是在加载图像之前设置 ImageView 的大小,以防止在加载某些图像时进一步调整卡片大小
猜你喜欢
  • 2018-09-14
  • 1970-01-01
  • 1970-01-01
  • 2017-09-15
  • 2020-02-16
  • 1970-01-01
  • 2015-07-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多