美文网首页AndroidAndroid 开发必备
RecyclerView实现多行多列item单选点击变色

RecyclerView实现多行多列item单选点击变色

作者: 聽媽媽的话 | 来源:发表于2017-03-28 17:52 被阅读906次

    今天工作的时候遇到一个需求,需要实现多行多列单选,并且点击变色的功能,一开始我是想用RadioButton来实现的,但是RadioGroup只能是单行纵向或者横向,如果要实现多行多列的话,必须自定义一个RadioGroup,最终我还是选择用RecyclerView来实现。

    思路

    1、首先自定义一个适配器,将列表的子项的布局设置好,并设置好点击事件,同时定义一个Map用来存储每个子项的ViewHolder,在Adapter中定义一个函数,用来实现子项点击后刷新自身背景的功能;

    2、RecyclerView设置布局管理器为网格布局管理器GridLayoutManager,设置adapter的点击事件,设置间距

    实现

    自定义Adapter

    public class FilterBureauAdapter extends RecyclerView.Adapter<FilterBureauAdapter.FilterBureauHolder> {
    
        private Context mContext;
        private String[] mList;
        private Map<Integer,FilterBureauHolder> mHolderMap;
    
        public FilterBureauAdapter(Context context, @NonNull String[] list) {
            mContext = context;
            mList = list;
            mHolderMap = new HashMap<>();
        }
        @Override
        public FilterBureauHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(mContext).inflate(R.layout.list_item_filter_bureau,parent,false);
            FilterBureauHolder holder = new FilterBureauHolder(view);
            return holder;
        }
    
        @Override
        public int getItemCount() {
            return mList.length;
        }
    
        @Override
        public void onBindViewHolder(final FilterBureauHolder holder, final int position) {
            holder.btnBureau.setText(mList[position]);
            holder.btnBureau.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onItemClickListener.onItemClick(v,position);
                }
            });
            // 保存子项的ViewHolder
            mHolderMap.put(position,holder);
        }
    
        /**
         * 刷新区局按钮点击状态
         */
        public void refreshBureau(int position){
            for (Map.Entry<Integer,FilterBureauHolder> entry: mHolderMap.entrySet()) {
                FilterBureauHolder holder = entry.getValue();
                // 点击项背景以及字体变色,其它项背景及字体设置为默认颜色
                if (entry.getKey() == position){
                    holder.btnBureau.setBackgroundResource(R.mipmap.icon_filterbox_on);
                    holder.btnBureau.setTextColor(mContext.getResources().getColor(R.color.main_blue));
                } else {
                    holder.btnBureau.setBackgroundResource(R.mipmap.icon_filterbox_off);
                    holder.btnBureau.setTextColor(mContext.getResources().getColor(R.color.main_gray));
                }
            }
        }
    
        class FilterBureauHolder extends RecyclerView.ViewHolder{
            Button btnBureau;
            public FilterBureauHolder(View itemView) {
                super(itemView);
                btnBureau = (Button) itemView.findViewById(R.id.btn_bureau);
            }
        }
    
        private OnItemClickListener onItemClickListener;
    
        public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
            this.onItemClickListener = onItemClickListener;
        }
    }
    

    其中OnItemClickListener 为自定义的接口

    public interface OnItemClickListener {
        void onItemClick(View view, int position);
        void onItemLongClick(View view , int position);
    }
    

    布局文件比较简单,就放了一个按钮

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <Button
            android:id="@+id/btn_bureau"
            android:layout_width="60dp"
            android:layout_height="32dp"
            android:background="@mipmap/icon_filterbox_off"
            android:textColor="@color/main_gray"/>
    </LinearLayout>
    

    然后就在Fragment中实例一个RecyclerView,设置好布局管理器、间距、适配器以及每一项的点击事件,这里我设置为网格布局,3列,然后设置子项间的间距为16dp

     public void initFilterBureau() {
            rvBbureau.setLayoutManager(new GridLayoutManager(getActivity(),3,GridLayoutManager.VERTICAL,false));
            rvBbureau.addItemDecoration(new GridSpacingItemDecoration(3, Util.dip2px(getActivity(),16),true));
            final FilterBureauAdapter adapter = new FilterBureauAdapter(getActivity(), Constant.BUREAUS);
            adapter.setOnItemClickListener(new OnItemClickListener() {
                @Override
                public void onItemClick(View view, int position) {
                    // 点击项后刷新每一项的背景及字体颜色
                    adapter.refreshBureau(position);
                }
    
                @Override
                public void onItemLongClick(View view, int position) {
    
                }
            });
            rvBbureau.setAdapter(adapter);
    
        }
    

    这里的间距设置是需要自定义的

    public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {
        private int spanCount;
        private int spacing;
        private boolean includeEdge;
    
        public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
            this.spanCount = spanCount;
            this.spacing = spacing;
            this.includeEdge = includeEdge;
        }
    
        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            int position = parent.getChildAdapterPosition(view); // item position
            int column = position % spanCount; // item column
    
            if (includeEdge) {
                outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
                outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)
    
                if (position < spanCount) { // top edge
                    outRect.top = spacing;
                }
                outRect.bottom = spacing; // item bottom
            } else {
                outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
                outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f /    spanCount) * spacing)
                if (position >= spanCount) {
                    outRect.top = spacing; // item top
                }
            }
        }
    }
    

    以上就是所有的实现过程了

    相关文章

      网友评论

      本文标题:RecyclerView实现多行多列item单选点击变色

      本文链接:https://www.haomeiwen.com/subject/jntsottx.html