源码下载:http://download.csdn.net/detail/forwardyzk/7271971
转载请注明原文地址:http://blog.csdn.net/forwardyzk/article/details/24730733
一般情况下,我们都是在文件中设置好长和宽,使用match_parent,warp_content,fill_parent和设置固定的长和宽,倘若有这样的一种情况,使用代码设置控件的长和宽,那么这样就会根据动态获取控件的大小,按比例的设置其他控件的常何况,这样也可以达到屏幕适配的效果。
这只是一种情况,还有其他的情况用到动态的获取或者设置控件的长和宽。
获取控件的长和宽
我们一般情况下,会在onCreate()中用到这种办法获取控件的长和宽。
int w=findViewById(R.id.ll).getWidth(); 我们发现这样获得的宽度是0,原因是:在onCreate()方法获得的控件对象还没有开始测量,所以获得的宽度是0,当执行了onMeasure()方法,才可以获得真正的宽,然后执行onDraw()方法,展示出来。
main.xml
<LinearLayout
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="@+id/tv_01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ff0000"
android:text="this is 01" />
<TextView
android:id="@+id/tv_02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ff00ff"
android:text="this is 02" />
</LinearLayout>
那么怎样在onCreate()方法中获得长和宽呢。有以下三种方法:
方法1:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ll = (LinearLayout)findViewById(R.id.ll);
tv_01 = (TextView)findViewById(R.id.tv_01);
tv_02 = (TextView)findViewById(R.id.tv_02);
int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
ll.measure(w, h);
int width = ll.getMeasuredWidth();
int height = ll.getMeasuredHeight();
Log.i(TAG, "方法1:"+String.valueOf(width)+":"+height);
}
介绍:
在main.xml中,LinearLayout是填充的父窗体,但是使用此方法获取的宽度却不是屏幕的宽度。而是两个TextView实际长度的和。Log.i(TAG, "屏幕的宽度:"+getWindowManager().getDefaultDisplay().getWidth());
方法2:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ll = (LinearLayout)findViewById(R.id.ll);
tv_01 = (TextView)findViewById(R.id.tv_01);
tv_02 = (TextView)findViewById(R.id.tv_02);
ViewTreeObserver vto = ll.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
int height = ll.getMeasuredHeight();
int width = ll.getMeasuredWidth();
Log.i(TAG, "方法2:"+String.valueOf(width)+":"+height);
//w = width;
//setWidth_01(ll.getMeasuredWidth());
return true;
}
});
Log.i(TAG, "屏幕的宽度:"+getWindowManager().getDefaultDisplay().getWidth());
}
介绍:
使用此方法获得的宽度是设置的长度
如果你设置的是填充父窗体,那么获得的宽度是屏幕的宽度
如果你设置的是一个具体的宽度(200),那么获得的宽度是设置的那个值(200)
方法3:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ll = (LinearLayout)findViewById(R.id.ll);
tv_01 = (TextView)findViewById(R.id.tv_01);
tv_02 = (TextView)findViewById(R.id.tv_02);
ViewTreeObserver vto2 = ll.getViewTreeObserver();
vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
ll.getViewTreeObserver().removeGlobalOnLayoutListener(this);
Log.i(TAG, "方法3:"+String.valueOf(ll.getWidth())+":"+ll.getHeight());
}
});
Log.i(TAG, "屏幕的宽度:"+getWindowManager().getDefaultDisplay().getWidth());
}
介绍:
此方法和方法二获得的值是一样的。
动态的设置控件的长和宽
方法1:
/**
* 第一种方法:动态的设置View的宽和高
*/
public void setWidth_01(int w) {
LinearLayout.LayoutParams llp = new LayoutParams(w, 50);
tv_01.setLayoutParams(llp);
}
方法2:
/**
* 第二种方法:动态的设置View的宽和高
*/
public void setWidth_02(int w) {
// 第二种设置控件的宽度
LinearLayout.LayoutParams llp = null;
llp = (LayoutParams)tv_02.getLayoutParams();
llp.width = w;
tv_02.setLayoutParams(llp);
}
这两种方法动态的设置控件的长和宽效果是一样的。
注意点:
1.如果是使用第一种方法获得的宽度,然后动态的设置长和宽,此时的长和宽是控件中实际内容所占的常何况
2.如果使用第二种方法获得长和宽
直接设置的话,那么会出现死循环,虽然效果出来了,可以通过查看打印的log就明白是死循环。
public void getWidth_02() {
ViewTreeObserver vto = ll.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
int height = ll.getMeasuredHeight();
int width = ll.getMeasuredWidth();
Log.i(TAG, "方法2:"+String.valueOf(width)+":"+height);
setWidth_01(ll.getMeasuredWidth());
return true;
}
});
}
如果是把获得的长和宽设置为成员变量,那么在设置的话,获取的长和宽是0
public void getWidth_02() {
ViewTreeObserver vto = ll.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
int height = ll.getMeasuredHeight();
int width = ll.getMeasuredWidth();
Log.i(TAG, "方法2:"+String.valueOf(width)+":"+height);
w=width;
return true;
}
});
setWidth_01(w);
}
3.如果是第三种方法获取长和宽,是没有异常状况的。
public void getWidth_03() {
ViewTreeObserver vto2 = ll.getViewTreeObserver();
vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
ll.getViewTreeObserver().removeGlobalOnLayoutListener(this);
Log.i(TAG, "方法3:"+String.valueOf(ll.getWidth())+":"+ll.getHeight());
setWidth_01(ll.getWidth());
}
});
}
也可以把长和宽提取为成员变量,然后给其他控件设置长和宽也可以。
综上所述:
如果只是获得长和宽,那么获取长和宽的方法1和方法2都可以,根据需要选取。
如果即获取还要设置,那么推荐使用方法3