Android - RecyclerView重复以编程方式添加的图像视图

时间:2016-09-21 05:21:02

标签: android android-recyclerview recycler-adapter

在我的项目中,我需要每行添加不同数量的ImageView,具体取决于来自Web服务的响应,我设法做到这一点,但是当我滚动recyclerView {{1}时从行重复自己。

我的应用程序的想法是能够创建和共享组合(视频游戏的输入集)。这是我的适配器代码。

ImageView

至于XML文件是一个简单的LinearLayout,其中没有任何内容。

我使用配对功能为每个创建的@Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == TYPE_COMBO) { View row = LayoutInflater.from(parent.getContext()).inflate(R.layout.row, parent,false); ComboViewHolder comboViewHolder = new ComboViewHolder(row); return comboViewHolder; } else { View row = LayoutInflater.from(parent.getContext()).inflate(R.layout.progress_footer, parent, false); FooterViewHolder footerViewHolder = new FooterViewHolder(row); return footerViewHolder; } } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (holder instanceof ComboViewHolder) { ComboViewHolder comboViewHolder = (ComboViewHolder) holder; ComboImp comboImp = (ComboImp) data.get(position); ComboConverter comboConverter = new ComboConverter(); comboConverter.convertToPS4(comboImp.getCombo()); LinearLayout LinearLayout = new LinearLayout(mContext); LinearLayout.LayoutParams imageViewParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); int[] comboItems = comboConverter.convertToPS4(comboImp.getCombo()); PairingFunction pairingFunction = new PairingFunction(); for (int i = 0; i < comboItems.length; i++) { int id = pairingFunction.pair(i + 1, position + 1); comboViewHolder.imageView = new ImageView(mContext); comboViewHolder.imageView.setId(id); comboViewHolder.imageView.setImageResource(0); comboViewHolder.imageView.setLayoutParams(imageViewParams); comboViewHolder.imageView.setImageResource(comboConverter.getPs4Picture(Control.getByCode(comboItems[i]))); linearLayout.addView(comboViewHolder.imageView); } comboViewHolder.linearLayout.addView(linearLayout); } } @Override public int getItemCount() { return data.size(); } public static class ComboViewHolder extends RecyclerView.ViewHolder{ private TextView combo,postDate; private View circleView; private LinearLayout linearLayout; private ImageView imageView; public ComboViewHolder(View itemView) { super(itemView); linearLayout = (LinearLayout)itemView.findViewById(R.id.LinearRow); linearLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { imageView.setImageResource(R.drawable.ps4_square_30x30); } }); } public TextView getCombo() { return combo; } public TextView getPostDate() { return postDate; } public View getCircleView() { return circleView; } public View getImageView() { return imageView; } public LinearLayout getLinearLayout(){return linearLayout;} } 设置唯一ID,它不完美(有足够的行和ImageView整数将最大化)但现在可以使用

3 个答案:

答案 0 :(得分:0)

以编程方式添加了视图,Recycler / Grid / List视图是一个糟糕的组合。它真的与回收有关,因为你将它们添加到视图中,但它们在回收时不会被删除。为了使它们工作,每次调用onBindViewHolder时,你必须删除所有以编程方式添加的视图并读取它们。这与视图回收的想法相反,并且在时间上非常昂贵,所以它的确没有建议。

唯一的另一个想法是将您自己的回收逻辑写入布局,以便您从单独的回收池手动回收添加的视图。这是可行的,但颈部真的很痛。

要成为一个好人 - 这是我的LinearLayout替代品,可用于回收再利用。它仍然不是100%有效(它需要在行之间共享甚至更好,我会让它在某一天做到这一点),但它至少会最小化在回收布局中添加新行的性能损失。随意调整它以使用RelativeLayout,就像它看起来你需要的那样:

public class RecycledLinearLayout extends LinearLayout {

    public interface RecyledLinearLayoutAdapter<ItemType, HolderType> {
        View createView(ViewGroup parent);
        HolderType createHolder(View view);
        void assignToView(View view, HolderType holder, ItemType item);
    }

    private List<View> mRecycledTaskViews;
    private List<Object> mRecycledTaskHolders;
    private RecyledLinearLayoutAdapter mAdapter;

    public RecycledLinearLayout(Context context) {
        super(context);
        init(context, null, 0);
    }

    public RecycledLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public RecycledLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }

    public void init(Context context, AttributeSet attrs, int defStyleAttr) {
        mRecycledTaskViews = new ArrayList<>();
        mRecycledTaskHolders = new ArrayList<>();
    }

    public void setAdapter(RecyledLinearLayoutAdapter adapter) {
        mAdapter = adapter;
    }

    public void setItems(List items) {
        removeAllViews();
        if(mAdapter == null || items == null) {
            return;
        }
        for(int i = mRecycledTaskViews.size(); i < items.size(); i++) {
            View view = mAdapter.createView(this);
            mRecycledTaskViews.add(view);
            mRecycledTaskHolders.add(mAdapter.createHolder(view));
        }
        for(int i=0; i < items.size(); i++) {
            Object item = items.get(i);
            View currentView = mRecycledTaskViews.get(i);
            Object currentHolder = mRecycledTaskHolders.get(i);
            mAdapter.assignToView(currentView, currentHolder, item);
            addView(currentView);
        }
    }

}

答案 1 :(得分:0)

您需要在顶部的onBindViewHolder()方法中添加这样的一行

comboViewHolder.linearLayout.removeAllViews();

答案 2 :(得分:0)

试试这个......

   for (int i = 0; i < comboItems.length; i++) {
              int id = pairingFunction.pair(i + 1, position + 1);
              ImageView imageView = new ImageView(mContext);
              imageView.setId(id);
              imageView.setImageResource(0);
              imageView.setLayoutParams(imageViewParams);
              imageView.setImageResource(comboConverter.getPs4Picture(Control.getByCode(comboItems[i])));
              relativeLayout.addView(imageView);
    }