Android获取Button正确尺寸:返回错误值且回调无法更新UI
我来帮你搞定这两个问题!先理清楚背后的原因,再一步步给出解决方案:
一、为啥直接获取Button尺寸总是返回420px?
这是因为你获取尺寸的时机太早了!Button还没走完测量和布局流程,此时拿到的只是系统默认的初始尺寸(或者wrap_content还没根据文本计算出真实宽度)。比如在Activity的onCreate、onStart里直接调用getWidth(),肯定拿不到正确值——因为View此时还没被渲染到屏幕上。
二、怎么获取Button的真实尺寸?
给你两个靠谱的方案:
方案1:用View.post()延迟获取
post()里的Runnable会被放到View的消息队列中,等View完成布局后再执行,此时拿到的就是真实尺寸:
yourButton.post(new Runnable() { @Override public void run() { int realWidth = yourButton.getWidth(); int realHeight = yourButton.getHeight(); // 这里可以放心使用真实尺寸 Log.d("ButtonSize", "真实宽度:" + realWidth + "px"); } });
如果是动态修改Button文本后要获取尺寸,记得先触发重新布局:
yourButton.setText("这是一段很长很长的测试文本"); yourButton.requestLayout(); // 告诉系统重新测量布局 yourButton.post(() -> { int correctWidth = yourButton.getWidth(); // 这里就是文本更新后的真实宽度 });
方案2:用OnGlobalLayoutListener监听
这个监听会在整个View树布局完成后触发,适合需要监听多次布局变化的场景:
ViewTreeObserver observer = yourButton.getViewTreeObserver(); observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { // 记得移除监听,避免重复触发 yourButton.getViewTreeObserver().removeOnGlobalLayoutListener(this); int realWidth = yourButton.getWidth(); // 处理尺寸逻辑 } });
三、为啥addOnLayoutChangeListener里无法更新UI?
不是不能更新,而是直接更新可能触发布局循环!当你在onLayoutChange里修改UI(比如调整其他View的尺寸),会再次触发View的布局流程,导致onLayoutChange被反复调用,甚至引发ANR。
解决办法很简单,把UI更新操作放到post()里,或者只执行一次:
yourButton.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { // 先移除监听,只处理一次布局变化 yourButton.removeOnLayoutChangeListener(this); final int realWidth = right - left; // 宽度=右边界-左边界,和getWidth()结果一致 // 用post把UI更新放到下一次主线程循环,避免布局循环 yourButton.post(() -> { // 比如更新某个TextView的内容 sizeInfoTv.setText("Button真实宽度:" + realWidth + "px"); // 或者调整其他View的尺寸 anotherView.getLayoutParams().width = realWidth; anotherView.requestLayout(); }); } });
总结
核心思路就是:等View完成测量布局后再获取尺寸,更新UI时要避免触发重复布局。上面的方案都能解决你的问题,根据自己的场景选择就行~
内容的提问来源于stack exchange,提问作者Ananta
相关产品推荐
相关产品推荐

