代码控制UI,View
在前面的幾講中,我們都是使用xml layout 來(lái)去控制UI組件,其實(shí)我們也可以完全拋開(kāi)XML,用純代碼來(lái)控制我們的界面UI。
回顧我們學(xué)過(guò)的,遇到過(guò)的UI組件,有容器類的Layout:LinearLayout,RelativeLayout等, 也有視圖類UI:TextView, EditText, Button, ImageView等。對(duì)應(yīng)到代碼中,我們會(huì)發(fā)現(xiàn),他們都是View子類,具體關(guān)系如下:
Tips:在Eclipse中,可以用Ctrl+T鍵來(lái)查看某個(gè)類的類層次關(guān)系:
?
ViewGroup 與View 的關(guān)系,是一個(gè)典型的“組合”設(shè)計(jì)模式。
我們來(lái)用代碼,實(shí)現(xiàn)一個(gè)簡(jiǎn)單的UI布局:
只有一個(gè)EditText和一個(gè)Button, 看看代碼是怎么寫(xiě)的:
public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);LinearLayout container = new LinearLayout(this);container.setOrientation(LinearLayout.HORIZONTAL);this.setContentView(container);EditText content = new EditText(this);content.setHint("寫(xiě)點(diǎn)什么吧...");Button submit = new Button(this);submit.setText("發(fā)送");container.addView(content);container.addView(submit);} }我們來(lái)分析一下代碼,
不管LinearLayout, EditText 還是Button, 他們的構(gòu)造函數(shù)都是this. 其實(shí)查看源碼后我們發(fā)現(xiàn),所有的View及其子類的構(gòu)造都至少包含三個(gè)構(gòu)造方法:
public View(Context context)public View(Context context, AttributeSet attrs)public View(Context context, AttributeSet attrs, int defStyle)?
后兩個(gè)是為XML layout 定義的,用代碼創(chuàng)建View時(shí),一般都是用第一個(gè)構(gòu)造函數(shù),這里用this, 是因?yàn)锳ctivity其實(shí)就是Context的子類。
this.setContentView()這個(gè)方法,以前我們都是傳一個(gè)R.layout進(jìn)去,其實(shí)它有多個(gè)重載,也可以直接傳入根視圖View。
這里的線性布局container 就是根視圖(容器視圖),要往容器視圖里面添加View,使用addView方式,addView 方法有幾個(gè)重載版本:
public void addView(View child)
public void addView(View child, int index)
public void addView(View child, int index, LayoutParams params)
public void addView(View child, int width, int height)
public void addView(View child, LayoutParams params)
LayoutParams 我們之后會(huì)講到。
總結(jié)一下,用代碼添加UI組件的步驟是:
- New 組件對(duì)應(yīng)的類;
- 把它添加到父容器中。
運(yùn)行結(jié)果就如上圖的一樣。你也許會(huì)想到,不是說(shuō)width, height是必須的嗎?怎么沒(méi)有設(shè)置也可以啊?是因?yàn)?#xff0c;addView默認(rèn)使用wrap_content.
但是光是這樣不夠,我們還想添加邊距,權(quán)重等。
為View指定LayoutParams
添加寬,高,邊距,權(quán)重這些屬性,對(duì)應(yīng)的類是LayoutParams,它一般都是作為一個(gè)內(nèi)部類出現(xiàn)在某個(gè)ViewGroup的子類中。對(duì)于線性布局,我們使用LinearLayout.LayoutParams,
weight, leftMargin, rightMargin…..這些屬性都在它的公有變量里面。
LinearLayout.LayoutParams contentLayoutParams = new LinearLayout.LayoutParams(0,LinearLayout.LayoutParams.WRAP_CONTENT);contentLayoutParams.weight = 1;contentLayoutParams.leftMargin = 10;container.addView(content, contentLayoutParams);LinearLayout.LayoutParams buttonLayoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);buttonLayoutParams.leftMargin = 10;container.addView(submit, buttonLayoutParams);在addView之前,我們?cè)O(shè)置好LayoutParams 的值,調(diào)用addView(View child, LayoutParams params)這個(gè)重載方法。
?
相對(duì)布局的RelativeLayout.LayoutParams
我們來(lái)看看, 在代碼中,調(diào)用那些方法來(lái)定位布局
因?yàn)樵谙鄬?duì)布局中, 定位的方法有很多種類,所以API提供了一個(gè)統(tǒng)一的方法:
addRule(int verb, int anchor)
addRule(int verb)
verb是動(dòng)詞的意思,就是用來(lái)表達(dá)above, below, toRightOf, toLeftOf, alignParentLeft…..等等。
這些動(dòng)詞的int 值在RelativeLayout下有常量定義。例如:
RelativeLayout.ABOVE
RelativeLayout.BELOW
RelativeLayout.ALIGN_LEFT
RelativeLayout.LEFT_OF
RelativeLayout.RIGHT_OF
anchor的值,可以是RelativeLayout.TRUE,0表示false, 或者其它View 的Id, 根據(jù)具體的verb, 填入相應(yīng)的值:
@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);this.setContentView(this.addRelativeLayout());}private RelativeLayout addRelativeLayout() {RelativeLayout container = new RelativeLayout(this);Button btn1 = new Button(this);btn1.setId(11);btn1.setText("上"); Button btn2 = new Button(this);btn2.setId(12);btn2.setText("下"); Button btn3 = new Button(this);btn3.setId(13);btn3.setText("左"); Button btn4 = new Button(this);btn4.setId(14);btn4.setText("右"); Button btn5 = new Button(this);btn5.setId(15);btn5.setText("中");RelativeLayout.LayoutParams lp1 = new RelativeLayout.LayoutParams(100,RelativeLayout.LayoutParams.WRAP_CONTENT);RelativeLayout.LayoutParams lp2 = new RelativeLayout.LayoutParams(lp1);RelativeLayout.LayoutParams lp3 = new RelativeLayout.LayoutParams(lp1);RelativeLayout.LayoutParams lp4 = new RelativeLayout.LayoutParams(lp1);RelativeLayout.LayoutParams lp5 = new RelativeLayout.LayoutParams(lp1);lp5.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);lp1.addRule(RelativeLayout.ABOVE, btn5.getId());lp1.addRule(RelativeLayout.ALIGN_LEFT, btn5.getId());lp2.addRule(RelativeLayout.BELOW, btn5.getId());lp2.addRule(RelativeLayout.ALIGN_LEFT, btn5.getId());lp3.addRule(RelativeLayout.LEFT_OF, btn5.getId());lp3.addRule(RelativeLayout.ALIGN_BASELINE, btn5.getId());lp4.addRule(RelativeLayout.RIGHT_OF, btn5.getId());lp4.addRule(RelativeLayout.ALIGN_TOP, btn5.getId());container.addView(btn5, lp5);container.addView(btn1, lp1);container.addView(btn2, lp2);container.addView(btn3, lp3);container.addView(btn4, lp4);return container;}注意:LayoutParams的構(gòu)造函數(shù)也可以是另外一個(gè)已經(jīng)存在的LayoutParams對(duì)象,他的width, height值被克隆到當(dāng)前對(duì)象中去。
?
FrameLayout, TableLayout的LayoutParams, 讀者可自行研究一下。
總結(jié)
以上是生活随笔為你收集整理的代码控制UI,View的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Android app按三层架构+MVC
- 下一篇: View工作原理(一)事件传递原理详解