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();

总结

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

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

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

相关推荐
黄林晴2 小时前
如何判断手机是否是纯血鸿蒙系统
android
火柴就是我2 小时前
flutter 之真手势冲突处理
android·flutter
法的空间3 小时前
Flutter JsonToDart 支持 JsonSchema
android·flutter·ios
循环不息优化不止3 小时前
深入解析安卓 Handle 机制
android
恋猫de小郭3 小时前
Android 将强制应用使用主题图标,你怎么看?
android·前端·flutter
jctech3 小时前
这才是2025年的插件化!ComboLite 2.0:为Compose开发者带来极致“爽”感
android·开源
用户2018792831673 小时前
为何Handler的postDelayed不适合精准定时任务?
android
叽哥3 小时前
Kotlin学习第 8 课:Kotlin 进阶特性:简化代码与提升效率
android·java·kotlin
Cui晨3 小时前
Android RecyclerView展示List<View> Adapter的数据源使用View
android
氦客3 小时前
Android Doze低电耗休眠模式 与 WorkManager
android·suspend·休眠模式·workmanager·doze·低功耗模式·state_doze