防止适配器在滚动时回收视图(编辑永远不会这样做。)

Posted

技术标签:

【中文标题】防止适配器在滚动时回收视图(编辑永远不会这样做。)【英文标题】:Prevent the adapter from recycling views on scroll ( Edit do not ever do this.) 【发布时间】:2014-01-10 09:15:43 【问题描述】:

我有一个自定义的基本适配器,它将接收数据数组列表。从这里它将使用自定义按钮填充网格视图。它完美地完成并填满了gridview。问题是。我想设置一个按钮来改变颜色。当我这样做时,由于视图被回收,它也会改变下一个被回收的视图。前任。单击位置 0 处的按钮一。同时更改位置 13 处的按钮。现在当我进行一些调试时,我发现它也更改了一些属性。我想知道是否可以按原样创建我的视图,而无需回收视图的任何部分。

我已经看到了一些关于使用 stableID 的事情,但即使我已经将其覆盖为 true。它目前仍然没有改变它。

static class CategoryButtonAdapter extends BaseAdapter

    private Context mContext;
    private ArrayList<DishCategory> dishCategories;
    private ArrayList<Dish> dishItems;
    static ArrayList<DishCategoryButton> mDishCategoryButtons;
    //will take in an array list created in the orderlayout that will be the 
    //dish category. This will be the from where we will the count for the adapter
    public CategoryButtonAdapter(Context context, ArrayList<DishCategory> dishCategories)
    
        this.mContext = context;
        this.dishCategories = dishCategories;

        dishItems  = dishCategories.get(0).getDishes();
    

    public int getCount() 
    
        return dishCategories.size();
    

    //to be implementated later so it can b3e used to find menu categories
    @Override
    public DishCategory getItem(int position) 
    
        return dishCategories.get(position);
    

    public void getDishCategoryButtons()
    
        if(mDishCategoryButtons.size() == 0)
        
             System.out.println("The number of buttons in this adapapter is " + mDishCategoryButtons.size());
        
        else
        
            System.out.println("The number of buttons in this adapapter is " + mDishCategoryButtons.size());
        
    

    public long getItemId(int position) 
    
        return dishCategories.get(position).getDishCategoryID();
    

    @Override
    public boolean hasStableIds() 
        //return super.hasStableIds(); //To change body of generated methods, choose Tools | Templates.
        return true;
    

    public View getView(int position, View convertView, ViewGroup parent) 
    
        ViewHolder holder;
        DishCategoryButton button = null;
        //button to be created
        if(convertView == null )
        
            holder = new ViewHolder();
            //if it is not recycled, initialize some new attributes
            button = new DishCategoryButton(this.mContext,dishCategories.get(position));
            button.setLayoutParams(new GridView.LayoutParams(100,100));
            button.setPadding(2,2,2,2);
            //convertView.setTag(holder);
            button.setTag(holder);
        
        else
        
            //holder = (ViewHolder)convertView.getTag();
            button = (DishCategoryButton) convertView;
        
        //setButton to the description of the category
        //mDishCategoryButtons.add(button);
        button.setText((dishCategories.get(position).getDescription()));
        //this can be changed later to change the sex appeal of the app
        //for now it will be plain
        button.setId(position);

        //.setOnClickListener(new View.OnClickListener() 
        button.setOnClickListener(new View.OnClickListener() 
         public void onClick(View v) 
             // Perform action on click
            DishCategoryButton dishCategoryButton = (DishCategoryButton)v;
            PaintDrawable drawable = (PaintDrawable) dishCategoryButton.getBackground();
            System.out.println("Dish button position is " + dishCategoryButton.getId());
            //System.out.println("The position from the array says it is at " + position);
            System.out.println("Dish Category is " + dishCategoryButton.getDishCategory().getDescription());
            System.out.println("Is it currently selected  " + dishCategoryButton.getIsSelected());

            int color = drawable.getPaint().getColor();
                    System.out.println("Color is  " + color);
                    dishCategoryButton.setIsSelected(true);
                    drawable = (PaintDrawable) dishCategoryButton.getBackground();
                    color = drawable.getPaint().getColor();
                    System.out.println("Color is  " + color);
                        System.out.println("hi");

                    // The toggle is enabled

            
        );
        //new loadDishItems(categoryButtons.get(position).getDescription()));
        return button;
    

不用担心视图持有者。这是企图阻止回收。关于如何获得这个的任何线索或想法?

这是我的按钮

public class DishCategoryButton extends Button 

private DishCategory dishCategory = new DishCategory();
private Boolean isSelected = false;


public DishCategoryButton(Context context, DishCategory dishCategory) 

   super(context);
   this.dishCategory = dishCategory;
   isSelected = false;
   setTextColor(Color.WHITE);
   setBackgroundDrawable(new PaintDrawable(Color.BLACK));

public DishCategory getDishCategory()

     return dishCategory;

public void setDishCategory(DishCategory dishCategory)

    this.dishCategory = dishCategory;


public Boolean getIsSelected() 
    return isSelected;


public void setIsSelected(Boolean isSelected) 
    this.isSelected = isSelected;
    if(isSelected == true)
    
        setTextColor(Color.WHITE);
        setBackgroundDrawable(new PaintDrawable(Color.GREEN));
    
    else
    
        setTextColor(Color.WHITE);
        setBackgroundDrawable(new PaintDrawable(Color.BLACK));
    

【问题讨论】:

不,它应该回收视图以提高性能和平滑滚动。相反,您需要更改 gridview 的实现 你能解释一下我可以对实现做些什么吗? ***.com/questions/20611123/…。对于列表视图。现在您可以使用 gridview 实现相同的功能 【参考方案1】:

更好的方法是使用

recyclerView.getRecycledViewPool().setMaxRecycledViews(VIEW_TYPE,0);

您必须注意,这可能会降低 RecyclerView 的性能。

您可以重写 getItemViewType 方法,如下所述

@Override
public int getItemViewType(int position) 
    if (position == feedElements.size())
        return 3;
    else if (feedElements.get(position).getType() == 1)
        return 1;
    else
        return 2;

【讨论】:

各位,我们如何获取视图类型?【参考方案2】:

防止适配器在滚动时回收视图

只是不要使用传递给getView()convertView 参数并始终返回新生成的View

但是,就性能而言,这是一个糟糕的解决方案。相反,您的目标不应该是阻止回收,而是正确地回收:您的getView() 应该将convertView 重置为原始状态。

因此,如果您的 Button 的某些属性从它们的非默认值发生更改,请将它们重置为 getView() 中的默认值。

【讨论】:

【参考方案3】:
  public View getView(int position, View convertView, ViewGroup parent) 
        View itemview = null;

        itemview = getLayoutInflater().inflate(R.layout.ordermini, parent,false);

    

这将有助于扩充新视图

【讨论】:

【参考方案4】:

我遇到了这个确切的问题 所以我添加了一些代码来检查每个视图 它没有突出显示 当它找到突出显示的视图时,它会改回来。

//--------SET-FOREGROUND-IMAGE-(BORDER)------------
    /*If the user clicks on an item and then scrolls down so the selected item is no longer in view Then the
    Item that the user clicked on will be recycled with the foreground image.
    This is BAD because when the user sees the selected item (as distinguished by it's different border)
    it will be holding different data from a different data model item.
    These following lines of code will change the colour of any non selected item back to normal and they will
    colour of the selected views appropriately*/
        if(currentLine.getLineId() == clickedId)
        recycleHolder.cardView.setForeground(parentActivity.getResources().getDrawable(R.drawable.card_view_border_selected));
        else
        recycleHolder.cardView.setForeground(parentActivity.getResources().getDrawable(R.drawable.card_view_border));

这个代码放在里面

 @Override
public void onBindViewHolder(final RecyclableViewHolder recycleHolder, int i)

 

【讨论】:

以上是关于防止适配器在滚动时回收视图(编辑永远不会这样做。)的主要内容,如果未能解决你的问题,请参考以下文章

滚动回收站视图时如何防止项目重复

滚动回收器视图中的滞后

添加新列表时,回收站视图开始自动滚动

有没有办法防止 Xamarin Forms 滚动视图在打开选择器控件时自动滚动到最后编辑的条目?

插入数据时Recyclerview自动向上滚动

在顶部添加新项目后,回收器视图未滚动到顶部,因为尚未发生对列表适配器的更改