如何使用 gridlayout 在 recyclerview 中设置动态大小的占位符?

How to set a dynamically sized placeholder in a recyclerview with gridlayout?

我正在编写一段代码,允许用户 select 他们从 Facebook 中的一张照片,并在我们的应用程序中将其用作个人资料照片。逻辑搞定了,就是布局有点头疼

我的图片采用这种布局

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:layout_margin="5dp"
    >
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/imageView"
        />
</android.support.v7.widget.CardView>

我正在使用 RecyclerView,它将相册的每个图像加载到 2 列网格中(由 GridLayoutManager 提供)。这是使用 Picasso 完成的:

mImageLoader.load(image.getUrl()).resize(480, 480).centerCrop().into(holder.imageView);

因为加载包含数百张图片的相册需要一段时间,所以我想显示一个占位符。这可以使用 Picasso 中的 .placeholder 运算符来实现。

我的问题是我不知道我的一个 ViewHolder 有多高和多宽。

GridLayoutManager 将计算有多少 space 可用并为每个项目分配一个宽度值,因此我分配的数量将适合,这就是为什么我不能使用预定义的可绘制对象的原因我的占位符,因为我永远无法确定我的 240x240 可绘制对象是否适合所有设备。


那么,我的问题是:如何在我的 recyclerview 中获取每张卡片的宽度,以便我应用在运行时创建的位图作为占位符?

您需要动态添加布局管理器,您必须在 运行 时通过列数传递网格布局..

像这样

RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getApplicationContext(),2); recyclerView.setLayoutManager(layoutManager);

虽然这不是问题的确切答案,但我真正需要的是始终为正方形的 ImageView。那样的话,我可以简单地将我想要的任何东西加载到那个东西中并调整它的大小以适应使用 Picasso。

mImageLoader.load(image.getUrl()).fit().into(holder.imageView);

为了实现这一点,我子classed ImageView 并在 onMeasure 方法中,我将宽度值分配给视图的高度参数。

public class SquareImageView extends ImageView {

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int edgeLen = getMeasuredWidth();
        setMeasuredDimension(edgeLen, edgeLen);
    }
}

问题是,如果我使用水平滚动的Grid-Layout,它会把每个元素拉伸得异常长,所以我们需要添加一个属性来确定它的优势边,因为我很懒,我就简单地添加默认参数。

因为简单地将其定义为视图参数会很好,我们在 attr 文件中实现了一个样式化声明

<declare-styleable name="SquareImageView">
    <attr name="dominantSide" format="enum">
        <enum name="width" value="0"/>
        <enum name="height" value="1"/>
    </attr>
</declare-styleable>

现在,我们可以简单地将它添加到我们的 SquareImageView

<com.example.android.ui.custom.SquareImageView
    android:layout_width="match_parent"
    android:layout_height="0dp"
    app:dominantSide="width" />

自从我们宣布我们的主导方是 width 以来,我们可以随心所欲地控制身高。您可以将其指定为 0dp、match_parent、3.14159dp 或您想要的任何其他值。不过你需要给它分配一些东西,否则 IntelliJ 会骂你。

在我们的自定义class中,我们简单的获取参数dominantSide

public class SquareImageView extends ImageView {

    private int dominantSide;

    public SquareImageView(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SquareImageView);
        dominantSide = a.getInt(R.styleable.SquareImageView_dominantSide, 0);
        a.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int edgeLen = dominantSide == 0 ? getMeasuredWidth() : getMeasuredHeight();
        setMeasuredDimension(edgeLen, edgeLen);
    }
}