如何获取RecyclerView中按钮Item的实际宽度?
RecyclerView按钮宽度获取与设置问题解答
我开发了一个包含横向按钮列表的RecyclerView,期望实现如下逻辑:当所有按钮的总宽度小于屏幕宽度时,将每个按钮的宽度设置为屏幕宽度÷按钮数量。
我在Adapter类中编写了测试代码尝试获取和设置按钮宽度,代码如下:
override fun onBindViewHolder(holder: TabViewHolder, position: Int) { Log.d("TEST-APP","Button Width: " + holder.button.width.toString()) holder.button.width = 1080 Log.d("VED-APP","New Button Width: " + holder.button.width.toString()) holder.button.text = items[position].first holder.button.setOnClickListener { (context as MainActivity).updateCurrentImageLayout(items[position].second) } }
但出现异常情况:代码确实将按钮宽度修改为1080,但设置宽度前后的两次Log输出结果均为0。
请问该如何正确获取RecyclerView中按钮Item的实际宽度?
以下是RecyclerView单个Item的布局文件代码:
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="match_parent"> <Button android:id="@+id/tabButton" android:layout_width="match_parent" android:minWidth="120dp" android:layout_height="match_parent" android:text="Unset-Button-Text"/> </android.support.constraint.ConstraintLayout>
问题原因分析
你遇到的Log输出为0的情况,核心原因是**onBindViewHolder执行时机早于View的测量布局流程**。在这个方法里,我们只是完成了数据和View的绑定,但此时View还没有被添加到界面上完成测量和布局,直接调用width拿到的是View初始的默认值0,哪怕你手动设置了width,这个值也要等到布局完成后才会生效,所以立刻打印还是0。
解决方案
针对你的需求(按钮均分屏幕宽度),我给你两种方案,优先推荐第一种更简洁的布局实现方式:
方案1:通过布局属性自动均分宽度(最优解)
不需要手动计算宽高,直接通过布局和LayoutManager的配置就能实现需求:
- 修改Item布局:把根
ConstraintLayout的layout_width改为0dp,并添加layout_weight="1",让每个Item自动均分RecyclerView的宽度:<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1"> <Button android:id="@+id/tabButton" android:layout_width="match_parent" android:minWidth="120dp" android:layout_height="match_parent" android:text="Unset-Button-Text"/> </android.support.constraint.ConstraintLayout> - 配置RecyclerView的LayoutManager:使用横向的
LinearLayoutManager,确保RecyclerView宽度为match_parent:val layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false) yourRecyclerView.layoutManager = layoutManager yourRecyclerView.adapter = yourAdapter
这样设置后,当所有按钮总宽度小于屏幕宽度时,每个按钮会自动均分屏幕宽度;如果总宽度超过屏幕宽度,RecyclerView会自动横向滚动,完全符合你的需求。
方案2:正确获取View的实际宽高(如果需要手动处理逻辑)
如果你确实需要获取View的实际宽高来做自定义逻辑,可以通过以下两种方式:
- 使用
View.post():post中的代码会在View完成测量布局后执行,此时能拿到真实的宽高:override fun onBindViewHolder(holder: TabViewHolder, position: Int) { holder.button.post { val actualWidth = holder.button.width Log.d("TEST-APP", "Actual Button Width: $actualWidth") // 在这里执行你的宽度设置逻辑 } // 其他绑定逻辑 holder.button.text = items[position].first holder.button.setOnClickListener { (context as MainActivity).updateCurrentImageLayout(items[position].second) } } - 添加
OnGlobalLayoutListener:监听View的布局完成事件,记得要移除监听避免内存泄漏:override fun onBindViewHolder(holder: TabViewHolder, position: Int) { val viewTreeObserver = holder.button.viewTreeObserver viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { // 根据API版本移除监听 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { holder.button.viewTreeObserver.removeOnGlobalLayoutListener(this) } else { holder.button.viewTreeObserver.removeGlobalOnLayoutListener(this) } val actualWidth = holder.button.width Log.d("TEST-APP", "Actual Button Width: $actualWidth") } }) // 其他绑定逻辑 }
内容的提问来源于stack exchange,提问作者Foobar
相关产品推荐
相关产品推荐

