RecyclerView在Grid不居中点击Item部分区域有效的解决方法

本文指出RecyclerView复用Adapter时,在LinearLayoutManager布局下点击item中TextView有效,GridLayoutManager布局下只有部分区域有效。原因是两种布局下TextView占比不同,解决办法是将接受点击事件的TextView宽度设为match_parent并设置点击事件。

本文中RecyclerView的Adapter是复用的,当RecyclerView处于LinearLayoutManager布局时,点击item中的TextView有效,而RecyclerView处于GridLayoutManager时点击Item发现只有部分区域(显示文字的TextView)有效,原因是LinearLayoutManager占据了Item绝大部分区域,而GridLayoutManager布局时,显示文字的TextView占了Item区域很小一部分,所以点击无效。此时应该把用于接受点击事件的显示图标的TextView宽度设置为match_parent,然后设置其点击事件,而不是LinearLayoutManager时文字TextView设置的点击事件,这样就能响应点击事件了,关键代码如下:

@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position, @NonNull List<Object> payloads) {
    super.onBindViewHolder(holder, position, payloads);
    RecyclerViewItemsData data = m_items.get(position);
    holder.m_itemTitle.setText(data.m_title);
    holder.m_itemImage.setText(data.m_image);

    if (R.layout.recycleview_grid_item == m_layout) {
        holder.m_itemImage.setOnClickListener(getOnClickListener(position));
    }

    if (R.layout.recycleview_linear_item == m_layout) {
        holder.m_itemTitle.setOnClickListener(getOnClickListener(position));
    }

    //如果布局里存在右箭头(二级菜单),则设置为font awesome字体,以显示为符号
    if (m_items.get(position).m_bShowArrow) {
        TextView arrowIcon = (TextView) m_itemView.findViewById(R.id.tv_arrow);
        if (null != arrowIcon) {
            arrowIcon.setTypeface(m_font);
        }
    } else {
        TextView arrowIcon = (TextView) m_itemView.findViewById(R.id.tv_arrow);
        if (null != arrowIcon) {
            arrowIcon.setVisibility(View.INVISIBLE);
            Log.d(TAG, "-- Lee -- " + m_items.get(position).m_title +
                    " arrow is show : " + m_items.get(position).m_bShowArrow);
        }
    }

    if (null != holder.m_tvInfo) {
        holder.m_tvInfo.setText(data.m_info);
    }

    ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
    if (null != layoutParams) {
        layoutParams.height = RelativeLayout.LayoutParams.WRAP_CONTENT;
        holder.itemView.setLayoutParams(layoutParams);
    }
}
### 实现RecyclerView列表项的正确聚焦 为了确保`RecyclerView`中的项目能够获得正确的焦点并保持良好的用户体验,可以采取多种方法来优化焦点管理。 #### 方法一:检查RecyclerView是否有焦点 通过判断`RecyclerView`是否已经获得了焦点,可以帮助理解当前界面的状态: ```java boolean hasFocus = mRecyclerView != null && mRecyclerView.hasFocus(); ``` 这种方法适用于初步确认`RecyclerView`及其子项目的焦点状态[^1]。 #### 方法二:在适配器内处理居中逻辑 对于更复杂的场景,比如希望选中的条目始终处于屏幕中央,则可以在适配器内部实现这一功能。当某个特定条件满足时(例如点击事件触发),执行如下操作: - 计算目标视图相对于父容器的位置; - 调整整个列表位置使该视图位于中心区域; 具体来说就是监听每一个item获取到输入焦点后的变化情况,并据此调整其显示位置: ```java @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus){ int[] location = new int[2]; v.getLocationOnScreen(location); // 获取RecyclerView相对屏幕顶部的距离 int recyclerViewTop = mRecyclerView.getTop(); // 计算需要移动的距离 int offset = location[1] - heightOfItem / 2 - recyclerViewTop; // 平滑滚动至指定距离 mRecyclerView.smoothScrollBy(0, offset); } } ``` 此段代码实现了基于触控反馈自动将所选项置于中间的效果[^2]。 #### 方法三:自定义LayoutManager设置网格布局列数 如果应用的是Grid类型的展示形式,还可以利用`StaggeredGridLayoutManager`或`GridLayoutManager`来自定义每一行有多少个元素排列在一起: ```java int spanCount = 3; mRecyclerView.setLayoutManager(new GridLayoutManager(context, spanCount)); ``` 这里的参数`spanCount`决定了每行列的数量,在某些情况下也会影响焦点切换的行为模式[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值