Android中控件实际呈现宽高与Java中动态设置的宽高不一致

博主原创文章,转载请说明出处,但是不说我也管不了你🏳️

前言

今天在写安卓的时候,需要用java代码去动态的改变一个按钮的宽高,但是意外地发现实际呈现出来的宽高只有高是被设置成功的,而按钮的宽度总是比想设置的宽一些,找了好一会儿才发现了问题所在,在这里记录一下这个问题。

正文

一、快速解决方案

删除xml文件中对应控件的weight属性(如果有的话)。若还不生效,删除对应控件中所有宽高相关的的属性设置。

二、详细问题分析

1、环境还原

JAVA
1
2
3
4
5
6
public static void setImgBtnLayoutParams(ImageButton imageButton,int widthPX,int heightPX){//设置imgBtn的布局
ViewGroup.LayoutParams layoutParams = imageButton.getLayoutParams();//获取imgBtn的默认布局
layoutParams.height = heightPX; //设置高,单位为像素
layoutParams.width = widthPX; //设置宽,单位为像素
imageButton.setLayoutParams(layoutParams); //更新imgBtn的布局
}

这是实现功能的关键代码,主要功能是改变按钮的宽高。这里imageButton是需要被改变宽、高的控件,widthPXheightPX分别为需要设置宽高。使用的是普通的方法,按道理说不会有什么问题,但是很不幸的是还是出了问题——按钮宽度总是比设置的宽度长一点。

2、问题分析

log一下按钮动态改变前、动态改变后的宽度,居然发现总是有改变后的宽度值=想要改变的宽度值+一个未知值71,好家伙,这是直接相加了。

JAVA
1
2
before: width of set is 90PX
after: width of reality is 161PX

那么这个未知值71是怎么来的?除了java代码里,那肯定是从XML文件中的属性里来的,如下为对应XML属性:

XML
1
2
3
4
5
6
7
8
9
<ImageButton
android:id="@+id/back_btn"
android:layout_width="0dp"
android:layout_height="20dp"
android:layout_weight="1"
android:padding="10dp"
android:background="@drawable/baseline_arrow_back_02"
android:contentDescription="@string/des_back_icon" >
</ImageButton>

可以看到,在XML中会直接影响width只有android:layout_width="0dp"android:layout_weight="1",而layout_width属性肯定是没问题的(因为java代码中设置的就是这个值),只有可能是lauout_weight属性(注:这里的weight实际将控件宽度设置为了相对于总宽度的1/12,且还有一个属性与该控件相同布局的按钮)。有了这个思路,再将java代码部分删除(不动态设置)后,再log一下按钮动态改变前、动态改变后的宽度:

JAVA
1
2
before: width of set is 90PX
after: width of reality is 86PX

现在试着将86与71联系起来。前面说了,weight实际将控件宽度设置为了相对于总宽度的1/12,那么总宽度为86*12=1032,随后因为有一个和该控件相同布局的按钮,则1032-90*2=852852/12=71,这不巧了吗。

所以,结论是:当weight属性存在时,若对应宽度或高度值(统称为长度)不为零,则weight值的计算会在总长度减去设置的长度后再按比例设置,且控件的最终长度为weight计算的值+设置的长度值

3、解决方法

取消weight属性即可。当然,由此类推,若没有weight属性仍然出现了相关问题,则一定是存在某个会直接影响长度的属性值,删除它即可。