android - RecyclerView 中不正确的图像回收

标签 android imageview android-recyclerview porter-duff

我有一个 RecyclerView,每行都有一个图标。图标应该动态着色,所以我使用白色图标并在绑定(bind) View 时应用颜色过滤器。奇怪的是,我最终在结果 View 中发现了很多差异。

在这个例子中,我尝试将每三行设置为红色,其余行设置为绿色(注释 #18):

enter image description here

下面是适配器。如您所见,每次我重新绑定(bind) holder 时,我都会将更改后的图标应用于 ImageView,大概没有为旧的回收图像留出空间。

public class TestAdapter extends RecyclerView.Adapter<TestAdapter.ViewHolder> {

    private final Context context;

    public TestAdapter(Context context) {
        this.context = context;
    }

    @Override
    public TestAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false);
        return new ViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(TestAdapter.ViewHolder holder, int position) {
        holder.bindItem(position);
    }

    @Override
    public int getItemCount() {
        return 200;
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        private final ImageView image;
        private final TextView text;

        public ViewHolder(View itemView) {
            super(itemView);

            image = (ImageView) itemView.findViewById(R.id.image);
            text = (TextView) itemView.findViewById(R.id.text);
        }

        public void bindItem(int position) {
            // pick color depending on the position
            final int color = ContextCompat.getColor(context,
                    position%3 == 0 ? android.R.color.holo_red_light : android.R.color.holo_green_light
            );

            // set text content and color
            text.setText("#" + position);
            text.setTextColor(color);

            // create icon from the resource and set filter
            final Drawable icon = ResourcesCompat.getDrawable(context.getResources(), R.drawable.ic_brightness, null);
            icon.setColorFilter(color, PorterDuff.Mode.MULTIPLY);

            image.setImageDrawable(icon);
        }
    }

}

item_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/image"
        android:layout_width="18dp"
        android:layout_height="wrap_content"
        android:scaleType="fitStart"
        android:adjustViewBounds="true" />

    <TextView
        android:id="@+id/text"
        android:textSize="18sp"
        android:textColor="@android:color/black"
        android:layout_marginLeft="48dp"
        android:layout_marginStart="48dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        tools:text="text" />

</LinearLayout>

什么给了?

谢谢。

最佳答案

看了你的评论,不知道是否符合你的要求。但是,我能够通过在布局文件中使用 android:src 元素设置可绘制的“亮度”来复制预期的行为,然后将过滤器应用于 ImageView (而不是图标):

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {

    public RecyclerViewAdapter() {
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.rv_row, viewGroup, false);
        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, int i) {
        viewHolder.bindItem(i);
    }

    @Override
    public int getItemCount() {
        return 200;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        private final ImageView image;
        private final TextView text;

        public ViewHolder(View itemView) {
            super(itemView);

            image = (ImageView) itemView.findViewById(R.id.image);
            text = (TextView) itemView.findViewById(R.id.text);
        }

        public void bindItem(int position) {

            final int color = ContextCompat.getColor(itemView.getContext(),
                    position % 3 == 0 ? android.R.color.holo_red_light : android.R.color.holo_green_light
            );

            text.setText("#" + position);
            text.setTextColor(color);

            image.setColorFilter(color, PorterDuff.Mode.MULTIPLY);
        }
    }
}

编辑:

如果您动态设置图标,但将滤镜应用于 ImageView,它也有效:

public static class ViewHolder extends RecyclerView.ViewHolder {

    private final ImageView image;
    private final TextView text;

    public ViewHolder(View itemView) {
        super(itemView);

        image = (ImageView) itemView.findViewById(R.id.image);
        text = (TextView) itemView.findViewById(R.id.text);
    }

    public void bindItem(int position) {

        final int color = ContextCompat.getColor(itemView.getContext(),
                position % 3 == 0 ? android.R.color.holo_red_light : android.R.color.holo_green_light
        );

        text.setText("#" + position);
        text.setTextColor(color);

        Drawable icon = getIcon();

        image.setImageDrawable(icon);
        image.setColorFilter(color, PorterDuff.Mode.MULTIPLY);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private Drawable getIcon() {
        return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
                ? image.getContext().getResources().getDrawable(R.drawable.ic_brightness_1_white_24dp, null)
                : image.getContext().getResources().getDrawable(R.drawable.ic_brightness_1_white_24dp);
    }
}

关于android - RecyclerView 中不正确的图像回收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34632812/

相关文章:

android - 单击后退按钮时在 RecyclerView 中获得相同的项目位置

Android - 在谷歌驱动器中可以完成的最大下载数量是多少?

java - 在 Webview 中加载 TXT 中的 URL

android - TimePicker 调用的读出标记

android - 在 Android Imageview 上禁用抗锯齿

android - 如何在 NestedScrollView 中使用 RecyclerView

android - 使用 ffmpeg 进行视频转换以针对 Android 和 iOS 移动设备

java - 以编程方式设置GridView和ImageView的宽度和高度

Android UI 滞后于设置图像

android - RecyclerView 适合屏幕时不要折叠 Toolbar