【问题标题】:Item highlight not behaving as expected项目突出显示未按预期运行
【发布时间】:2021-09-08 07:07:23
【问题描述】:

我在使用 RecyclerView 制作的水平滚动条时遇到了一种奇怪的行为,

提示:

我在onItemClick接口中使用SharedPreferences将点击项的位置转移到我设置适配器的片段,然后我使用另一个接口将点击项的位置从片段转移到我设置当前的活动项目通过viewpager

当前行为:

问题 #1

当一个项目被选中时,背景(突出显示)颜色没有改变,必须再次点击它才能获得突出显示颜色。

问题 #2

当一个项目被点击时,滚动状态重置为 1

问题:

为什么会这样?以及如何解决?

预期行为

当一个项目被点击时,我想要以下行为(单个项目选择)

RecyclerView 适配器类

public class PlanetAdapter extends RecyclerView.Adapter<PlanetAdapter.PlanetViewHolder> {


        public interface OnItemClickListener {
            void onItemClick(PlanetModel item);
        }

    private ArrayList<PlanetModel> episodeslist;
    private OnItemClickListener listener;


    SharedPreferences getPref1x1 = getContext().getSharedPreferences("PlanetAdapter", Context.MODE_PRIVATE);
    int pos1x1 = getPref1x1.getInt("position",0);

    int isPlanetSelected=pos1x1;


    public PlanetAdapter(ArrayList<PlanetModel> episodeslist, OnItemClickListener listener) {
        this.episodeslist = episodeslist;
        this.listener = listener;
    }

    @Override
    public PlanetAdapter.PlanetViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v= LayoutInflater.from(parent.getContext()).inflate(R.layout.planet_row, parent,false);
        PlanetViewHolder vh=new PlanetViewHolder(v);
        return vh;
    }

    @Override
    public void onBindViewHolder(PlanetAdapter.PlanetViewHolder vh, int position) {
        TextView tv = (TextView) vh.itemView;
        tv.setText(episodeslist.get(position).getPlanetName());
        tv.setCompoundDrawablesWithIntrinsicBounds(R.drawable.bg, 0, 0, 0);

        vh.bind(episodeslist.get(position), listener);



        if (episodeslist.get(position).isPlanetSelected()) {
            vh.itemView.setBackgroundColor(getContext().getResources().getColor(R.color.colorPrimaryDark));
        }else{
            vh.itemView.setBackgroundColor(getContext().getResources().getColor(R.color.colorPrimaryLight));
        }



        //holder.image.setImageResource(R.drawable.planetimage);
        //vh.text.setText(episodeslist.get(position).toString());
    }


    @Override
    public int getItemCount() {
        return episodeslist.size();
    }


    public class PlanetViewHolder extends RecyclerView.ViewHolder{

        protected TextView text;
        public PlanetViewHolder(View itemView) {
            super(itemView);
            text= (TextView) itemView.findViewById(R.id.text_id);
        }
        public void bind(final PlanetModel item, final OnItemClickListener listener) {
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override public void onClick(View v) {
                    int position = getPosition();

                    int previousItem = isPlanetSelected;
                    isPlanetSelected = position;

                    notifyItemChanged(previousItem);
                    notifyItemChanged(position);




                    SharedPreferences setPref = v.getContext().getSharedPreferences("PlanetAdapter", Context.MODE_PRIVATE);
                    setPref.edit().putInt("position", position).apply ();



                     listener.onItemClick(item);
                    //Toast.makeText(getContext(), "You have clicked " + item, Toast.LENGTH_SHORT).show();
                    //Toast.makeText(getContext(), "You have clicked " + ((TextView) itemView).getText(), Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
}

【问题讨论】:

    标签: java android arraylist android-recyclerview


    【解决方案1】:

    SharedPreference 的位置值存储错误。要在ViewHolder 中获得正确的位置,您需要使用getBindingAdapterPosition() 而不是getPosition

    另外你应该在使用listener.onItemClick(item);之前更新item的值

    您还需要在使用notifyItemChanged() 之前切换对象上的选择布尔值以反映更改。

    itemView.setOnClickListener(new View.OnClickListener() {
        @Override public void onClick(View v) {
            int position = getBindingAdapterPosition();
    
            int previousItem = selectedPosition;
            selectedPosition = position;
            
            // Updating the selector boolean before notifying the changes to the adapter
            
            PlanetModel currentSelectedItem = episodeslist.get(position);
            currentSelectedItem.setPlanetSelected(true);
            PlanetModel previousSelectedItem = episodeslist.get(previousItem);
            previousSelectedItem.setPlanetSelected(false);
            
            // Notify the changes to the adapter
            
            notifyItemChanged(previousItem);
            notifyItemChanged(position);
    
    
            SharedPreferences setPref = v.getContext().getSharedPreferences("PlanetAdapter", Context.MODE_PRIVATE);
            setPref.edit().putInt("position", position).apply ();
    
    
            // Here you should define `item` before triggering the interface callback.
            
             listener.onItemClick(item);
            
        }
    }); 
    

    更新:

    点击监听器不应该在 bind() 中,因为它是从 onBindViewHolder 调用的,您正在迭代许多监听器,而您应该只需要一个,要解决这个问题,您需要将其转移到持有者构造函数:

    所以,将onBindViewHolder 更改为:

    @Override
    public void onBindViewHolder(PlanetAdapter.PlanetViewHolder vh, int position) {
        TextView tv = (TextView) vh.itemView;
        tv.setText(episodeslist.get(position));
        tv.setCompoundDrawablesWithIntrinsicBounds(R.drawable.bg, 0, 0, 0);
    
       
        // setting the highlight color
        if (episodeslist.get(position).isPlanetSelected()) {
            vh.itemView.setBackgroundColor(getContext().getResources().getColor(R.color.colorPrimaryLight));
            
        } else {
            vh.itemView.setBackgroundColor(getContext().getResources().getColor(R.color.colorPrimaryDark));
        }
    
    }
    

    并将ViewHolder 更改为:

    public class PlanetViewHolder extends RecyclerView.ViewHolder{
    
        protected TextView text;
        public PlanetViewHolder(View itemView) {
            super(itemView);
            text= (TextView) itemView.findViewById(R.id.text_id);
            
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override public void onClick(View v) {
                    
                int position = getAdapterPosition();
    
                int previousItem = selectedPosition;
                selectedPosition = position;
                
                // Updating the selector boolean before notifying the changes to the adapter
                
                PlanetModel currentSelectedItem = episodeslist.get(position);
                currentSelectedItem.setPlanetSelected(true);
                PlanetModel previousSelectedItem = episodeslist.get(previousItem);
                previousSelectedItem.setPlanetSelected(false);
                
                // Notify the changes to the adapter
                
                notifyItemChanged(previousItem);
                notifyItemChanged(position);
    
    
                SharedPreferences setPref = v.getContext().getSharedPreferences("PlanetAdapter", Context.MODE_PRIVATE);
                setPref.edit().putInt("position", position).apply ();
    
    
                // Here you should define `item` before triggering the interface callback.
                String item  = episodeslist.get(position);
                listener.onItemClick(item);
                    
                }
            });
            
            
        }
    
    }
    

    【讨论】:

    • 非常感谢,但是getBindingAdapterPosition不工作,是不是因为我使用java 1.7 and recyclerview-v7:21.0.3'
    • @cyberpunk 那么您应该改用getAdapterPosition(),但您应该迁移,因为getAdapterPosition() 现在已弃用
    • getAdapterPosition() 也不起作用,除了迁移还有其他解决方法吗?
    • mmm.. 可能还有其他问题。如果position 值是预期的单击项目位置,您能否调试并记录下来,那么存在问题。
    • 先生,我可以 100% 确认该位置正是我想要的,例如,当我单击第 3 集时,位置(索引)为 2 ,我使用断点检查了很多次,所以我我猜还有什么不对的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-17
    • 2017-06-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多