Android RecyclerView 实现 GridView ,并实现点击效果及方向位置的显示

效果图


一、引入

复制代码
 implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30'

二、使用步骤

1.Adapter

java 复制代码
public class UnAdapter extends BaseQuickAdapter<UnBean.ResultBean, BaseViewHolder> {

    private int selectedPosition = RecyclerView.NO_POSITION; // 用于记录当前选中的位置
    private int lastSelectedPosition = RecyclerView.NO_POSITION; // 上一次选中的位置

    private int spanCount = 4; // 每行显示的列数

    // 处理item点击事件的方法
    public void onItemClick(int position) {
        // 如果点击的是当前选中的item,则不执行任何操作(或者执行特定的操作)
        if (position == selectedPosition) {
            return;
        }

        // 更新选中状态
        if (selectedPosition != RecyclerView.NO_POSITION) {
            // 如果之前有选中的item,先通知适配器刷新它,以恢复默认背景
            notifyItemChanged(selectedPosition);
        }

        // 更新选中位置
        lastSelectedPosition = selectedPosition;
        selectedPosition = position;

        // 通知适配器刷新新选中的item
        notifyItemChanged(selectedPosition);
    }

    // (可选)如果需要,可以添加一个方法来处理取消选中item的情况
    private void deselectItem(int position) {
        if (position == selectedPosition) {
            selectedPosition = RecyclerView.NO_POSITION;
        }
    }

    public  UnAdapter(int layoutResId, @Nullable List<UnBean.ResultBean> data) {
        super(layoutResId, data);
    }

    @SuppressLint("ResourceAsColor")
    @Override
    protected void convert(BaseViewHolder helper, UnBean.ResultBean item) {

        ImageView fx_rightImg = helper.getView(R.id.fx_right_img);
        ImageView fx_leftImg = helper.getView(R.id.fx_left_img);
        LinearLayout fx_upLayout = helper.getView(R.id.fx_up_layout);
        LinearLayout bgLayout = helper.getView(R.id.bg_layout);


        // 根据是否选中来设置背景
        if (helper.getLayoutPosition() == selectedPosition) {
          bgLayout.setBackgroundResource(R.drawable.shape_blue_8);
            helper.setTextColor(R.id.cd_tv, mContext.getColor(R.color.white));
        } else if (helper.getLayoutPosition() == lastSelectedPosition && lastSelectedPosition != RecyclerView.NO_POSITION) {
           bgLayout.setBackgroundResource(R.drawable.shape_bg_position_sel);
            helper.setTextColor(R.id.cd_tv, mContext.getColor(R.color.blue_text));
        } else {
           bgLayout.setBackgroundResource(R.drawable.shape_bg_position_sel);
            helper.setTextColor(R.id.cd_tv, mContext.getColor(R.color.blue_text));
        }

        // 设置点击监听器(注意:这里应该在ViewHolder的构造函数中设置,以避免重复设置)
        // 但为了简化示例,这里直接在convert中设置(不推荐)
       bgLayout.setOnClickListener(v -> {
            onItemClick(helper.getPosition());
        });

        // 计算当前项位于哪一行
        int position = helper.getAdapterPosition(); // 获取当前项的索引
        int row = position / spanCount; // 整数除法得到当前行号(注意:这里假设没有头部或脚部项)
        // 计算当前项在当前行的列索引(从0开始)
        int column = position % spanCount;
        // 判断是否是每行的首项
        boolean isFirstItemInRow = column == 0;

        // 判断是否是每行的尾项
        // 注意:这里的判断需要考虑是否是最后一行且不是整除spanCount的情况
        boolean isLastItemInRow = (position + 1) % spanCount == 0 || position == getItemCount() - 1;

        // 或者更精确地判断尾项(仅当当前项不是最后一行的唯一项时才需要额外检查)
        boolean isLastItemInRowPrecise = (position + 1) % spanCount == 0 ||
                (position == getItemCount() - 1 && position % spanCount != spanCount - 1);

        // 判断当前项是否为列表中的最后一位
        boolean isLastItemInList = position == getItemCount() - 1;

        // 判断行数的奇偶性
        if (row % 2 == 0) {
            fx_rightImg.setVisibility(View.VISIBLE);
            if (isFirstItemInRow) {
                fx_upLayout.setVisibility(View.GONE);
            }
            if (isLastItemInRowPrecise) {
                fx_upLayout.setVisibility(View.VISIBLE);
                fx_rightImg.setVisibility(View.GONE);
            }
        } else {
            fx_leftImg.setVisibility(View.GONE);
            fx_rightImg.setVisibility(View.VISIBLE);
            fx_upLayout.setVisibility(View.GONE);
            if (isFirstItemInRow) {
                fx_upLayout.setVisibility(View.VISIBLE);
            }
            if (isLastItemInRowPrecise) {
                fx_upLayout.setVisibility(View.GONE);
                fx_leftImg.setVisibility(View.GONE);
            }
        }
        // 根据是否为最后一位的逻辑来设置UI
        if (isLastItemInList) {
            fx_upLayout.setVisibility(View.GONE);
            fx_rightImg.setVisibility(View.GONE);
        }
        helper.setText(R.id.cd_tv, item.getTrain());
    }


}

2. item_layout.xml

XML 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="@dimen/dimen_120"
    android:layout_height="@dimen/dimen_80"
    android:layout_marginLeft="@dimen/dimen_15"
    android:orientation="vertical"
    android:padding="@dimen/dimen_5">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_40"
        android:orientation="horizontal">

        <LinearLayout
            android:id="@+id/bg_layout"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center">

            <TextView
                android:id="@+id/cd_tv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="G2519"
                android:textColor="@color/c_3681ff" />

        </LinearLayout>

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center">

            <ImageView
                android:id="@+id/fx_right_img"
                android:layout_width="@dimen/dimen_15"
                android:layout_height="@dimen/dimen_15"
                android:background="@drawable/icon_fx_right"
                android:visibility="gone" />

            <ImageView
                android:id="@+id/fx_left_img"
                android:layout_width="@dimen/dimen_15"
                android:layout_height="@dimen/dimen_15"
                android:background="@drawable/icon_fx_left"
                android:visibility="gone" />


        </LinearLayout>


    </LinearLayout>

    <LinearLayout
        android:id="@+id/fx_up_layout"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_40"
        android:gravity="center_vertical"
        android:visibility="gone">

        <ImageView
            android:layout_width="@dimen/dimen_15"
            android:layout_height="@dimen/dimen_15"
            android:layout_marginLeft="@dimen/dimen_25"
            android:background="@drawable/icon_fx_up" />
    </LinearLayout>


</LinearLayout>

3.应用

java 复制代码
 fromAssets = ReadAsUtil.getFromAssets(this, "UnList.json");
 unBean = new Gson().fromJson(fromAssets, UnBean.class);
 unList = unBean.getResult();
 gridLayoutManager = new GridLayoutManager(this, 4);
 cdLv.setLayoutManager(gridLayoutManager);
 unAdapter = new UnAdapter(R.layout.item_layout, unList);
 cdLv.setAdapter(unAdapter);
 unAdapter.notifyDataSetChanged();

总结

如果对你有所帮助的话,不妨 点赞收藏

如果你有什么疑问的话,不妨 评论私信

青山不改,绿水长流 ,有缘江湖再见 ~

相关推荐
冬奇Lab7 小时前
AudioRecord音频录制流程深度解析
android·音视频开发·源码阅读
alexhilton9 小时前
Jetpack Compose中的富文本输入
android·kotlin·android jetpack
兄弟加油,别颓废了。10 小时前
ctf.show_web4
android
哔哔龙12 小时前
Android OpenCV 实战:图片轮廓提取与重叠轮廓合并处理
android·算法
tangweiguo0305198712 小时前
Android SSE 流式接收:从手写到框架的进阶之路
android
大尚来也13 小时前
PHP 反序列化漏洞深度解析:从原理利用到 allowed_classes 防御实战
android·开发语言·php
sp42a13 小时前
通过 RootEncoder 进行安卓直播 RTSP 推流
android·推流·rtsp
SY.ZHOU14 小时前
移动端架构体系(一):组件化
android·ios·架构·系统架构
恋猫de小郭15 小时前
Android 17 新适配要求,各大权限进一步收紧,适配难度提升
android·前端·flutter
流星白龙15 小时前
【MySQL】9.MySQL内置函数
android·数据库·mysql