RecyclerView实现单选、多选

其实多选和单选,还有一种就是利用RecyclerView的单条刷新方法,notifyItemChanged().
只是单选的时候不是很好看,会出现选择了新的一个item之后,上一个item会出现一个上次被选择消失很慢的动画。
单选思路:保存前一次点击的item,每次判断是否被点击过,先将前一次的状态置为未选中,然后选中新的一条,就实现了单选。
多选思路:给一个selected状态,每次修改单条数据的状态,利用notifyItemChanged()刷新,然后将选中状态的数据遍历出来。(也可以在创建Adapter时候初始化一个selectedList,选中就增加,取消就删除)

另一个博主的文章,讲解的比较清楚==》Android RecyclerView、ListView实现单选列表的优雅之路.

在我们平时的开发中可能会用到简单的列表单选功能,ListView没有去尝试过,这里介绍下RecyclerView的单选功能。

我们是在Adapter中实现单选

public class ChoicePopupwindowAdapter extends RecyclerView.Adapter<ChoicePopupwindowAdapter.ChoicePopupwindowViewHolder> {
    private Context context;
    private List<HashMap<String,Object>> list;
    private LayoutInflater inflater;
    private OnPopupwindowItemListener listener = null;
    //被选中的item的位置,设置初始值为-1是为了解决默认第一个被选中的问题
    private int layoutPosition = -1;

    public ChoicePopupwindowAdapter(Context context,List<HashMap<String,Object>> list){
        this.context = context;
        this.list = list;
        this.inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    /**
     * 设置点击事件
     * @param listener
     */
    public void setOnItemClickListener(OnPopupwindowItemListener listener){
        this.listener = listener;
    }

    @Override
    public ChoicePopupwindowViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new ChoicePopupwindowViewHolder(inflater.inflate(R.layout.choice_popupwindow_list_item,null));
    }

    @Override
    public void onBindViewHolder(final ChoicePopupwindowViewHolder holder, int position) {
        //item的点击事件
        holder.itemView.setTag(position);
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                layoutPosition = holder.getLayoutPosition();
                notifyDataSetChanged();
                if(listener != null){
                    listener.onItemClick(v, (Integer) v.getTag());
                }
            }
        });

        holder.tvChoice.setText(list.get(position).get("name").toString());
        //更新单选之后的效果
        if(position == layoutPosition){
            holder.tvChoice.setTextColor(context.getResources().getColor(R.color.all_actionbar_color));
            holder.ivChoice.setVisibility(View.VISIBLE);
            holder.ivChoice.setImageResource(R.drawable.select_hook_icon);
        }else{
            holder.tvChoice.setTextColor(context.getResources().getColor(R.color.text_balck));
            holder.ivChoice.setVisibility(View.INVISIBLE);
            holder.ivChoice.setImageResource(R.drawable.select_hook_icon);
        }
    }

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

    public class ChoicePopupwindowViewHolder extends RecyclerView.ViewHolder{
        TextView tvChoice;
        ImageView ivChoice;

        public ChoicePopupwindowViewHolder(View itemView) {
            super(itemView);
            tvChoice = (TextView) itemView.findViewById(R.id.tv_choice);
            ivChoice = (ImageView) itemView.findViewById(R.id.iv_choice);
        }
    }

    //==================此处代码就是更新选中位置====================
    /**
     * 更新选中位置
     * @param selectedPosition
     */
    public void setSelectedPosition(int selectedPosition) {
        this.layoutPosition = selectedPosition;
    }
}

我是在PopupWindow实现的单选,顺便将PopupWindow的代码贴出来,可以实现给PopupWindow添加暗色背景的效果。

public class ChoicePopupWindow extends PopupWindow {
    private Activity activity;
    private List<HashMap<String,Object>> list;

    private LayoutInflater inflater;
    private View view;
    private int width;
    private int height;
    private RecyclerView rvList;
    private RecyclerView.LayoutManager layoutManager;
    private DividerListItemDecoration decoration;
    private ChoicePopupwindowAdapter adapter;
    private OnPopupwindowSelectListener listener = null;

    public ChoicePopupWindow(Activity activity, List<HashMap<String,Object>> list) {
        super(activity);
        this.activity = activity;
        this.list = list;
        init();
    }

    private void init() {
        inflater = LayoutInflater.from(activity);
        view = inflater.inflate(R.layout.choice_popupwindow_layout, null);
        this.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
        this.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
        view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        //  获取测量后的宽度
        width = view.getMeasuredWidth();
        //获取测量后的高度
        height = view.getMeasuredHeight();
        //设置背景为透明
        this.setBackgroundDrawable(new ColorDrawable(0x66000000));
        setBackGround(0.5f);
        //在PopupWindow里面就加上下面代码,让键盘弹出时,不会挡住pop窗口。
        this.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        this.setFocusable(true);
        this.setOutsideTouchable(true);
        this.setContentView(view);

        rvList = (RecyclerView) view.findViewById(R.id.rv_list);
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
                ScreenUtils.getScreenWidth(activity)/2, ViewGroup.LayoutParams.WRAP_CONTENT);
        rvList.setLayoutParams(params);

        layoutManager = new LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false);
        rvList.setLayoutManager(layoutManager);
        decoration = new DividerListItemDecoration(activity, DividerListItemDecoration.VERTICAL_LIST, R.drawable.divider_vertical_list);
        rvList.addItemDecoration(decoration);
        adapter = new ChoicePopupwindowAdapter(activity, list);
        rvList.setAdapter(adapter);
        adapter.setOnItemClickListener(itemListener);
        //需要在PopupWindow消失的时候,将窗口的背景修改为不透明
        this.setOnDismissListener(dismissListener);
    }

    /**
     * 设置背景透明度
     *
     * @param alpha
     */
    private void setBackGround(float alpha) {
        Window window = activity.getWindow();
        WindowManager.LayoutParams params = window.getAttributes();
        params.alpha = alpha;
        if (alpha == 1f) {
            //不移除该Flag的话,在有视频的页面上的视频会出现黑屏的bug
            window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
        } else {
            //解决在华为手机上半透明效果无效的bug
            window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
        }
        window.setAttributes(params);
    }

    /**
     * PopupWindow消失监听
     */
    OnDismissListener dismissListener = new OnDismissListener() {
        @Override
        public void onDismiss() {
	    //修改窗口透明度为不透明
            setBackGround(1f);
        }
    };

    /**
     * item点击事件
     */
    OnPopupwindowItemListener itemListener = new OnPopupwindowItemListener() {
        @Override
        public void onItemClick(View view, int position) {
            if(listener != null){
                listener.onSelectValue(position);
            }
        }
    };

    /**
     * 设置选中监听
     *
     * @param listener
     */
    public void setOnSelectListener(OnPopupwindowSelectListener listener) {
        this.listener = listener;
    }

    /**
     * 判断选择窗是否正在运行
     *
     * @return
     */
    public boolean isPopupWindowShowing() {
        return this.isShowing();
    }

    /**
     * 显示方法 并且控制显示位置
     *
     * @param view
     */
    public void show(View view) {
        this.showAsDropDown(view,width,height,Gravity.RIGHT|Gravity.TOP);
    }

    /**
     * 取消选择窗
     */
    public void cancel() {
        if (isPopupWindowShowing()) {
            this.dismiss();
            adapter = null;
        }
    }

    /**
     * 更新选中位置
     *
     * @param selectedPosition 选中位置
     */
    public void updatePosition(int selectedPosition) {
        if (adapter != null) {
	    //设置单选位置,并且刷新列表
            adapter.setSelectedPosition(selectedPosition);
            adapter.notifyDataSetChanged();
        }
    }
}

注意:有的时候我们在使用PopupWindow或者Dialog(DialogFragment)的时候,可能存在输入窗,我们需要在dialog或者PopupWindow消失的时候隐藏键盘,可以在声明周期方法的onDestroy()中调用隐藏键盘。

@Override
    public void onDestroy() {
        super.onDestroy();
        KeyboardUtils.hideSoftInput(activity);
        if(dialog != null){
            dialog.dismiss();
            dialog = null;
        }
    }
    //============隐藏软键盘的方法===========
    /**
     * 动态隐藏软键盘
     *
     * @param activity activity
     */
    public static void hideSoftInput(final Activity activity) {
        View view = activity.getCurrentFocus();
        if (view == null) {
            view = new View(activity);
        }
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
        if (imm == null) {
            return;
        }
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }
RecyclerView实现多选
可以在这里说一下多选的功能的思路,实现多选我们可以给列表的实体类中增加一个select(Boolean型,初始化为false)状态,实现点击事件的时候修改select状态并且adapter.notifyDataSetChanged()刷新列表就欧克。
public class NewServiceTaskAdapter extends RecyclerView.Adapter<NewServiceTaskAdapter.NewServiceTaskViewHolder> {
    private Context context;
    private List<NewCreateService> list;
    private LayoutInflater inflater;
    private OnRecyclerItemListener listener = null;

    public NewServiceTaskAdapter(Context context,List<NewCreateService> list){
        this.context = context;
        this.list = list;
        this.inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    /**
     * 设置监听
     * @param listener
     */
    public void setOnItemClickListener(OnRecyclerItemListener listener){
        this.listener = listener;
    }

    /**
     * 刷新列表数据
     * @param list
     */
    public void updateList(List<NewCreateService> list){
        this.list = list;
        notifyDataSetChanged();
    }

    @Override
    public NewServiceTaskViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new NewServiceTaskViewHolder(inflater.inflate(R.layout.create_service_task_item_layout,null));
    }

    @Override
    public void onBindViewHolder(final NewServiceTaskViewHolder holder, int position) {
        holder.itemView.setTag(position);
        holder.itemView.setOnClickListener(onClickListener);

        holder.tvName.setText(list.get(position).getName());
        holder.tvNum.setText("数量"+list.get(position).getNum()+"个");
        if(list.get(position).isSelect()){
            holder.ivCheck.setImageResource(R.drawable.select_icon);
        }else{
            holder.ivCheck.setImageResource(R.drawable.circle_icon);
        }
    }

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

    class NewServiceTaskViewHolder extends RecyclerView.ViewHolder{
        TextView tvName;
        TextView tvNum;
        ImageView ivCheck;

        public NewServiceTaskViewHolder(View itemView) {
            super(itemView);
            tvName = (TextView) itemView.findViewById(R.id.tv_name);
            tvNum = (TextView) itemView.findViewById(R.id.tv_num);
            ivCheck = (ImageView) itemView.findViewById(R.id.iv_check);
        }
    }

    View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(listener != null){
                listener.onItemClick(v, (Integer) v.getTag());
            }
        }
    };

    /**
     * 遍历取出选中数据
     * @return
     */
    public List<NewCreateService> getList(){
        List<NewCreateService> services = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            if(list.get(i).isSelect()){
                NewCreateService service = list.get(i);
                service.setPosition(i);
                services.add(service);
            }
        }
        return services;
    }
}

然后在RecyclerView的点击事件中去修改多选状态

createService = list.get(position);
//修改多选状态,选中或者未选中
createService.setSelect(!createService.isSelect());
//将修改的数据设置进list
list.set(position,createService);
//更新列表
adapter.updateList(list);
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是在RecyclerView实现单选的示例代码: 1. 首先,在RecyclerView的Adapter中添加一个成员变量来保存当前选中的位置: ```java private int mSelectedPosition = -1; ``` 2. 在ViewHolder的构造函数中设置itemView的点击事件,用于处理单选逻辑: ```java public MyViewHolder(View itemView) { super(itemView); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 获取当前点击的位置 int position = getAdapterPosition(); // 如果当前位置已经选中,则不做处理 if (position == mSelectedPosition) { return; } // 取消上一个选中的状态 notifyItemChanged(mSelectedPosition); // 设置新的选中状态 mSelectedPosition = position; notifyItemChanged(mSelectedPosition); } }); } ``` 3. 在Adapter的onBindViewHolder方法中根据当前位置是否选中来设置itemView的状态: ```java @Override public void onBindViewHolder(MyViewHolder holder, int position) { // 设置itemView的状态 if (position == mSelectedPosition) { holder.itemView.setSelected(true); } else { holder.itemView.setSelected(false); } // 其他操作 } ``` 注意:在itemView的布局文件中需要将android:background属性设置为可选中状态,例如: ```xml <LinearLayout android:id="@+id/item_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?android:attr/selectableItemBackground" android:orientation="vertical"> <!-- 其他控件 --> </LinearLayout> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吃骨头不吐股骨头皮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值