當(dāng)一個(gè)活動(dòng)接收到焦點(diǎn)時(shí),它將被要求繪制它的布局。Android框架將處理這個(gè)繪畫(huà)的過(guò)程,但是活動(dòng)必須提供它的布局層次的根節(jié)點(diǎn)。
繪畫(huà)從布局的根節(jié)點(diǎn)開(kāi)始。它被要求來(lái)測(cè)量和繪制布局樹(shù)。繪畫(huà)通過(guò)遍歷布局樹(shù)并渲染每個(gè)和失效區(qū)域相交的視圖來(lái)處理。相應(yīng)的,每個(gè)視圖組負(fù)責(zé)請(qǐng)求繪制它的子視圖(通過(guò)draw() 方法)而每個(gè)視圖負(fù)責(zé)畫(huà)它自己。因?yàn)檫@個(gè)樹(shù)是順序遍歷的,這意味著先畫(huà)父節(jié)點(diǎn)(也就是在屏幕后面),然后按照樹(shù)中出現(xiàn)的順序畫(huà)其同層次節(jié)點(diǎn)。
框架將不會(huì)畫(huà)不在失效區(qū)域的視圖,而且還將會(huì)幫你畫(huà)視圖背景。
你可以強(qiáng)制一個(gè)視圖被重畫(huà),通過(guò)調(diào)用invalidate()。
繪畫(huà)布局共有兩步:一個(gè)度量過(guò)程和一個(gè)布局過(guò)程。 度量過(guò)程在measure(int, int)里實(shí)現(xiàn)且是一個(gè)自頂向下的視圖樹(shù)遍歷。每個(gè)視圖在遞歸時(shí)往下推送尺寸規(guī)格。在度量過(guò)程的最后,每個(gè)視圖都已經(jīng)保存了自己的度量。第二個(gè)過(guò)程發(fā)生在 layout(int, int, int, int) 中并且也是自頂向下。在這個(gè)過(guò)程中,每個(gè)父節(jié)點(diǎn)負(fù)責(zé)定位它的所有子節(jié)點(diǎn),通過(guò)使用在度量過(guò)程中計(jì)算得到的尺寸。
當(dāng)一個(gè)視圖的 measure()方法返回時(shí),它的getMeasuredWidth()和getMeasuredHeight() 值必須被設(shè)置,以及所有這個(gè)視圖子節(jié)點(diǎn)的值。一個(gè)視圖的度量的寬度和高度值必須符合父視圖引入的限制。這確保在度量過(guò)程之后,所有父節(jié)點(diǎn)接受所有它們的子 節(jié)點(diǎn)的度量值。一個(gè)父視圖可能會(huì)在其子視圖上多次調(diào)用measure()方法。比如,父視圖可能會(huì)通過(guò)未指定的尺寸調(diào)用measure來(lái)發(fā)現(xiàn)它們的大小, 然后使用實(shí)際數(shù)值再次調(diào)用measure(),如果所有子視圖未做限制的尺寸總合過(guò)大或過(guò)小(也即是,如果子視圖之間不能對(duì)各自占據(jù)的空間達(dá)成共識(shí)的話, 父視圖將會(huì)干預(yù)并設(shè)置第二個(gè)過(guò)程的規(guī)則)。
要開(kāi)始一個(gè)布局,可調(diào)用requestLayout()。這個(gè)方法通常在視圖認(rèn)為它自己不再適合它當(dāng)前的邊界的情況下被調(diào)用。
度量過(guò)程使用兩個(gè)類來(lái)交流尺寸。View.MeasureSpec類被視圖用來(lái)告訴它們的父視圖它們想如何被度量和定位。基礎(chǔ)的LayoutParams類僅僅描述了視圖想有多大(高和寬)。對(duì)于每個(gè)維度,它可以指定下面之一:
- · 一個(gè)準(zhǔn)確的數(shù)值
- · FILL_PARENT, 這意味著視圖想和父視圖一樣大(減掉填充padding)。
- · WRAP_CONTENT, 這意味著視圖只想有剛好包裝其內(nèi)容那么大(加上填充)
對(duì)于不同的ViewGroup子類,有相應(yīng)的LayoutParams子類。比如,相對(duì)布局RelativeLayout有它自己的LayoutParams子類,這包含了能夠讓子視圖橫向和豎向居中顯示的能力。
度量規(guī)格(MeasureSpecs)被用來(lái)沿著樹(shù)從父到子的下傳度量需求。一個(gè)MeasureSpecs可以是下面三種模式之一:
- · UNSPECIFIED: 這被父視圖用來(lái)決定其子視圖期望的尺寸。比如,一個(gè)線性布局可能在它的子視圖上調(diào)用measure() on its child,通過(guò)設(shè)置其高度為UNSPECIFIED 以及一個(gè)寬度為EXACTLY 240,來(lái)找出這個(gè)子視圖在給定240像素寬度的情況下需要顯示多高。
- · EXACTLY: 這被父視圖用來(lái)給子視圖強(qiáng)加一個(gè)準(zhǔn)確的尺寸。子視圖必須使用這個(gè)大小,并確保其所有的后代將適合這個(gè)尺寸。
- · AT_MOST: 這被父視圖用來(lái)給子視圖強(qiáng)加一個(gè)最大尺寸。子視圖必須確保它自己以及所有的后代都適合這個(gè)尺寸。
一。也 許很多童鞋對(duì)getWidth()和getMeasuredWidth()的用法有很多的不解,這兩者之間有什麼樣的不同呢,網(wǎng)上也有各種不同的版本,但 大多數(shù)都大同小異,從這個(gè)地方Ctrl+C,到另一個(gè)地方Ctrl+V,沒(méi)有把問(wèn)題說(shuō)透,也有一部分文章誤導(dǎo)了大家對(duì)這兩個(gè)方法的認(rèn)識(shí),我也是深受其害。 這裡先糾正下面的一個(gè)版本的說(shuō)法,Baidu上一搜一大堆的,可惜這種說(shuō)法是錯(cuò)的,所以希望大家就不要再盲目的轉(zhuǎn)載到你的空間裡:
getWidth得到是某個(gè)view的實(shí)際尺寸.
getMeasuredWidth是得到某view想要在parent view里面占的大小.
想必你也見(jiàn)過(guò)這樣的解釋,聽(tīng)起來(lái)這樣的解釋也似雲(yún)裡霧裡,沒(méi)有把問(wèn)題點(diǎn)透。
二。好了,錯(cuò)誤的版本就不過(guò)多說(shuō)了,下面對(duì)這兩個(gè)方法做一下正解,首先大家應(yīng)先知道以下幾點(diǎn):
1. 在一個(gè)類初始化時(shí),即在構(gòu)造函數(shù)當(dāng)中我們是得不到View的實(shí)際大小的。感興趣的朋友可以試一下,getWidth()和getMeasuredWidth()得到的結(jié)果都是0.但是我們可以從onDraw()方法裡面得到控件的大小。
2. 這兩個(gè)方法所得到的結(jié)果的單位是像素即pixel.
對(duì)兩個(gè)方法做介紹:
getWidth():得到的是view在父Layout中佈局好後的寬度值,如果沒(méi)有父佈局,那麼默認(rèn)的父佈局是整個(gè)屏幕。也許不好理解。通過(guò)一個(gè)例子來(lái)說(shuō)明一下。
例1 :
public class Test extends Activity {
private LinearLayout mBackgroundLayout;
private TextViewTest mTextViewTest;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBackgroundLayout = new MyLayout(this);
mBackgroundLayout.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT));
mTextViewTest = new TextViewTest(this);
mBackgroundLayout.addView(mTextViewTest);
setContentView(mBackgroundLayout);
}
public class MyLayout extends LinearLayout{
public MyLayout(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
super.onLayout(changed, l, t, r, b);
Log.i("Tag", "--------------");
View mView=getChildAt(0);
mView.measure(0, 0);
}
}
public class TextViewTest extends TextView {
public TextViewTest(Context context) {
super(context);
// TODO Auto-generated constructor stub
setText("test test ");
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
// measure(0, 0);
Log.i("Tag", "width: " + getWidth() + ",height: " + getHeight());
Log.i("Tag", "MeasuredWidth: " + getMeasuredWidth()
+ ",MeasuredHeight: " + getMeasuredHeight());
}
}
}
這裡是在LinearLayout裡添加一個(gè)TextView控件,如果此時(shí)要得到對(duì)TextView獲取getWidth(),那麼是在TextView添加到Layout後再去獲取值,並不單單的是對(duì)TextView本身寬度的獲取。
getMeasuredWidth():先看一下API裡面怎麼說(shuō)的
The width of this view as measured in the most recent call to measure(). This should be used during measurement and layout calculations only.
得到的是在最近一次調(diào)用measure()方法測(cè)量後得到的view的寬度,它僅僅用在測(cè)量和layout的計(jì)算中。
所以此方法得到的是view的內(nèi)容佔(zhàn)據(jù)的實(shí)際寬度。
你如果想從一個(gè)最簡(jiǎn)單的例子中的到它們的不同,下面將對(duì)上面的例子做一下修改:
public class Test extends Activity {
private TextViewTest mTextViewTest;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mTextViewTest = new TextViewTest(this);
setContentView(mTextViewTest);
}
public class TextViewTest extends TextView {
public TextViewTest(Context context) {
super(context);
// TODO Auto-generated constructor stub
setText("test test ");
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
measure(0, 0);
Log.i("Tag", "width: " + getWidth() + ",height: " + getHeight());
Log.i("Tag", "MeasuredWidth: " + getMeasuredWidth()
+ ",MeasuredHeight: " + getMeasuredHeight());
}
}
}
總結(jié)(正解):
getWidth(): View在設(shè)定好佈局後整個(gè)View的寬度。
getMeasuredWidth(): 對(duì)View上的內(nèi)容進(jìn)行測(cè)量後得到的View內(nèi)容佔(zhàn)據(jù)的寬度,前提是你必須在父佈局的onLayout()方法或者此View的onDraw()方法裡調(diào) 用measure(0,0);(measure 參數(shù)的值你可以自己定義),否則你得到的結(jié)果和getWidth()得到的結(jié)果一樣。
也許我組織的不是很好,大家有什麼不清楚的地方再給我留言。關(guān)於這兩個(gè)方法的區(qū)別就是看你有沒(méi)有用measure()方法,當(dāng)然measure()的位置也是很重要的。
三.請(qǐng)尊重原創(chuàng),轉(zhuǎn)載請(qǐng)?jiān)]明這是http://hi.baidu.com/ljlkings/home的空間。
--------------------------------------------------------------------2011/03 /01更新------------------------------------------------------------
1. 在xml裡面用的Layout_weight是什麼意思?
A: 該屬性代表的權(quán)值,權(quán)值越小,級(jí)別越高,即在佈局中佔(zhàn)的分量就越重,舉例。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Button1"
/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="Button2"
/>
</LinearLayout>
因?yàn)樵O(shè)置了button1的權(quán)重最小,所以它佔(zhàn)用的佈局就越大,這樣設(shè)置的意思是:將橫向的佈局分為三份,button1佔(zhàn)兩份,button2佔(zhàn)一份,很簡(jiǎn)單的,有什麼不懂的可以留言,謝謝!,
下面看效果圖:
*******2011-3-26 修改
這里要首先感謝sunwayforever的指導(dǎo),避免了我這篇文章錯(cuò)誤之處的進(jìn)一步擴(kuò)散,在這里先引用一句話吧:由于作者水平有限,文章中難免有疏漏和錯(cuò)誤之處,懇請(qǐng)大家批評(píng)指正。謝謝!(注:上面綠色底紋的言論錯(cuò)誤,希望大家往下看)
這 里對(duì)layout_weight 說(shuō)一下自己新的見(jiàn)解,首先,前面有一句話“因?yàn)樵O(shè)置了button1的權(quán)重最小,所以它占用的布局就越大”這句話在你的layout_width設(shè)置為 fill_parent的時(shí)候是沒(méi)錯(cuò)的,可是如果設(shè)置為wrap_content的時(shí)候,這句話就解釋不清了,下面是sunwayforever對(duì)此屬性的認(rèn)識(shí):
linearLayout中包含有weight的child時(shí),linearLayout會(huì)measure兩次:
設(shè)屏幕寬度為X
第一次:button1的measuredWidth為X,button2也為X (因?yàn)橛昧藈eight,所以linearLayout每次measure child時(shí)不考慮前一個(gè)已經(jīng)占用的大小),total_width為2X
第二次:計(jì)算delta=x-total_width=-x,然后會(huì)將button1的寬度設(shè)為
x+delta*1/3=0.66x, button2的寬度為 x+delta*2/3=0.33x
那我現(xiàn)在對(duì)這句話重新概括一下:“因?yàn)樵O(shè)置了button1的權(quán)重最小,所以它占用的布局優(yōu)先級(jí)就越高”,也許在Android里面布局并沒(méi)有優(yōu)先級(jí)之說(shuō),我這里只是為了說(shuō)明問(wèn)題,自己定義的,所以朋友們不要拍磚。
那首先分析一下當(dāng)layout_width屬性設(shè)置為fill_parent的時(shí)候,即充滿父佈局,當(dāng)然意思是這個(gè)控件要根據(jù)weight的設(shè)置盡可能的 大,因此,依上例而論,button1的weight設(shè)為1,button2的weight設(shè)置為2.即button的優(yōu)先級(jí)最高,因此,要填充父佈局就 要button1先來(lái)填充,盡可能的大,那這個(gè)盡可能又是多少呢,這就要綜合layout裡其他控件的weight值了,然後做一下運(yùn)算,button1 佔(zhàn)據(jù)2/3,button2佔(zhàn)據(jù)1/3.你也可以把button2設(shè)置為一個(gè)非常大的數(shù),比如2000,此時(shí)在Graphical Layout模式下可以看到button1填充滿了整個(gè)寬度,而看不到button2的影子,事實(shí)上button2還是存在的,你把鼠標(biāo)指向 button1的後面就可以看到一個(gè)長(zhǎng)長(zhǎng)的豎條,那個(gè)就是button2,已經(jīng)非常非常小了。因此,在layout_width設(shè)置為fill_parent的時(shí)候,weight所代表的是你的控件要優(yōu)先盡可能的大。
接著是當(dāng)layout_weight設(shè)置為wrap_content的時(shí)候,即適應(yīng)內(nèi)容的寬度,意思是這個(gè)控件要盡可能的小,只要能把內(nèi)容顯示出來(lái)就可以 了,同樣的,如果把button1和button2的layout_weight設(shè)置為wrap_content後,button1的weight為 1,button2的weight為2.那麼button1要優(yōu)先盡可能的小,而button2也要盡可能的小,只是優(yōu)先級(jí)不一樣,因?yàn)樵O(shè)置了 weight,所以這兩個(gè)控件總的寬度要填滿父佈局的寬度,所以就又要計(jì)算每個(gè)控件所佔(zhàn)據(jù)的大小,此時(shí),button1的優(yōu)先級(jí)較高,共有兩份,一份 1/3,一份2/3,button1要盡可能的小,那button1當(dāng)然要選1/3,因此,我們看到的效果反而是button2佔(zhàn)據(jù)的較大。這裡要說(shuō)的是 如果把權(quán)值同樣做如下設(shè)置:button1為1,button2為2000,那button1是不是就要佔(zhàn)據(jù)1/2000的空間呢?這麼理解就錯(cuò)了,剛才 說(shuō)了,要盡可能的小,但這個(gè)小是有 一個(gè)限度的,那就是wrap_content,就是還要是內(nèi)容完完整整的顯示出來(lái),同樣的,盡可能的大也是有一個(gè)限度的,那就是父佈局的寬度。因此,在 layout_width設(shè)置為wrap_content的時(shí)候,weight所代表的是你的控件要優(yōu)先盡可能的大。
所以,要對(duì)weight做了解,要深深的理解下面兩句話:
在layout_width設(shè)置為fill_parent的時(shí)候,layout_weight所代表的是你的控件要優(yōu)先盡可能的大,但這個(gè)大是有限度的,即fill_parent.
在layout_width設(shè)置為wrap_content的時(shí)候,layout_weight所代表的是你的控件要優(yōu)先盡可能的小,但這個(gè)小是有限度的,即wrap_content.
layout_height 同 layout_width.
下面貼幾張圖:
1. layout_width="fill_parent", button1的weight=1,button2的weight=2;
2.layout_width="fill_parent", button1的weight=1,button2的weight=2000;
3.layout_width="wrap_content", button1的weight=1,button2的weight=2;
4.layout_width="wrap_content", button1的weight=1,button2的weight=2000;
轉(zhuǎn)自:http://www.cnblogs.com/-OYK/archive/2011/10/30/2229620.html
posted on 2013-01-01 18:31
JavaBird 閱讀(1852)
評(píng)論(1) 編輯 收藏 所屬分類:
ANDROID