2016-01-06 96 views
3

我有一個RecyclerView,每行有一個圖標。該圖標應該動態着色,所以我使用白色圖標並在綁定視圖時應用顏色過濾器。奇怪的是,我最終在結果中看到了很多不一致。RecyclerView中的圖像回收不正確

在這個例子中,我試圖使每三排紅,其餘綠色(注意#18):

enter image description here

下面是適配器。正如你所看到的,我每次重新綁定持有者時,都會將修改過的圖標應用到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> 

是怎麼回事?

謝謝。

+0

,而不是選擇位置,可以考慮重寫'getItemViewType'方法。 –

+0

問題是,在真實的項目中,顏色可能是任意的,它來自服務器。 – SqueezyMo

+0

這很有趣。你是否用不同的圖標而不是過濾器來測試它,看看你是否仍然得到相同的結果? – PPartisan

回答

2

使用此代碼段讀過您的意見,我不知道這是否是適合您的需求。但是,我能夠通過在佈局文件與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); 
    } 
} 
+1

謝謝,它完美的作品! 同時,我開始閱讀「BitmapDrawable」的源代碼,並偶然發現了一個非常有用的評論: 「可變的BitmapDrawable仍與其他任何來自同一資源的Drawable共享其位圖」。 因此,另一個工作是在設置setColorFilter()之前調用'icon = icon.mutate()',但我更喜歡你的解決方案。 – SqueezyMo

0

嘗試在你的bindview

int color; 
if(position%3 == 0){ 
    color = android.R.color.holo_red_light; 
    text.setText("#" + position); 
    text.setTextColor(color); 
    Drawable icon = ResourcesCompat.getDrawable(context.getResources(), R.drawable.ic_brightness, null); 
    icon.setColorFilter(color, PorterDuff.Mode.MULTIPLY); 
    image.setImageDrawable(icon); 

} else{ 
    color = android.R.color.holo_red_light; 
    text.setText("#" + position); 
    text.setTextColor(color); 
    Drawable icon = ResourcesCompat.getDrawable(context.getResources(), R.drawable.ic_brightness, null); 
    icon.setColorFilter(color, PorterDuff.Mode.MULTIPLY); 
    image.setImageDrawable(icon); 
} 
+2

謝謝,但它幾乎是相同的邏輯。不幸的是,問題依然存在。 – SqueezyMo

+0

你試過這個嗎? –

+0

是的,我確實嘗試過。 – SqueezyMo