廢話不多說,本文將會層層深入給大家講解如何動態的生成一個完整的界面。
本文內容:
- Java代碼中動態生成View
- Java代碼中動態設置View的位置,以及其他的屬性
- LayoutParams詳解
一、Java代碼中動態的生成View
我們以創建一個Button為例子。
1、首先我們在onCreate方法中創建一個Button實例:
Button button=new Button(this);
- 1
2、創建了Button實例下面我們就要指定它在哪個界面中顯示:
首先第一步找到我們要顯示的界面:
首先把setContentView()刪掉(后文會講)。
有兩種方法:
- 使用LayoutInflate
- 使用findViewById
1)LayoutInflate使用來找到一個布局文件:
ViewGroup viewGroup = (ViewGroup) LayoutInflater.from(this).inflate(R.layout.activity_main, null);
- 1
返回的是布局文件的最外層的View容器,
貼一下布局文件中的XML代碼
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.miko.zd.dynamicview.MainActivity" android:id="@+id/relative"> </RelativeLayout>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
這里LayoutInflate返回的就是最外層的RelativeLayout。RelativeLayout繼承於ViewGroup因此完全沒有問題。
2)通過FindViewByID返回最外層的View
第二種方法以第一種一致都是返回最外層的RelativeLayout:
View viewGroup2 = findViewById(R.id.relative);
- 1
3、下一步就是要把我們的Button添加到RelativeLayout中了
使用ViewGroup的addView方法:
viewGroup.addView(button);
- 1
運行代碼,你會發現界面中什么都沒有,為什么呢?
前文中說過刪除setContentView()這個方法,setContenView可以理解為,為Activity綁定一個顯示的的布局,我們只是找到了ViewGroup,並且添加了Button,但是沒有綁定Activity,因此這里添加一句setContentView(viewGroup);你可能會說,我一開始不刪除這一句,不可以么?
findViewById可以,setContentView()一旦調用,layout就會立刻顯示UI,而后的findViewById,找到RelativeLayout實際上已經加載出來了,添加Button,可以理解為顯示出UI后動態的添加View;而inflate只會把Layout形成一個以view類實現成的對象,有需要時再用setContentView(view)顯示出來。
運行結果:
可以看到,相當原始的界面,下一步我們就要設置Button的位置以及相關屬性了
二、Java代碼中動態設置View的位置,以及其他的屬性
1、首先我們為我們的Button設置一個背景,以及文字:
button.setBackgroundColor(Color.RED); button.setText("Hello World");
- 1
- 2
2、我們下一步想給Button設置長寬:
你可能會想button會有setHeight,setWidth方法,確實有,而且你可以實現設置長寬,但是如果你要設置Match_parent,Wrap_content,怎么實現呢?這時候我們就要使用LayoutParam方法了。
首先創建一個Layoutparams實例:
RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(100,100);
- 1
不同的布局對應着不同的LayoutParams,我們這里是RelativeLayout所以當然是R.layoutParam這里的兩個參數是Button的寬以及高,注意這里的100代表着100px,使用dp可以參照我之前的博客
dp轉px
那么上文中的MATCH 以及WRAP怎么實現呢?
RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- 1
運行結果:
為什么沒有效果呢,因為定義了LayoutParam但是沒有指定哪一個View因此還需要添加一句
button.setLayoutParams(params);
- 1
沒有任何問題。
3、設置位置信息
我們想要使Button居中顯示,怎么實現呢?
還是使用LayoutParams,使用他的addRules方法:
params.addRule(RelativeLayout.CENTER_IN_PARENT);
- 1
addRules有兩個方法:
- addRule(int verb)
- addRule(int verb, int anchor)
verb我們很好理解,就是各種規定位置的參數,anchor代表什么呢?
我們看源碼注釋:
The id of another view to use as an anchor,
* or a boolean value (represented as {@link RelativeLayout#TRUE}
* for true or 0 for false). For verbs that don’t refer to another sibling
* (for example, ALIGN_WITH_PARENT_BOTTOM) just use -1.
實際上verb參數可以分為兩類,一種是不要任何相對view的,比如ALIGN_WITH_PARENT_BOTTOM這種的參數,另一種需要相對view的參數,例如above,right_of等等,需要一個view來表示位置的參數,這個時候就需要用到anchor,anchor代表的是相對view的id。
下面我們再創建一個Button:
ViewGroup viewGroup2 = (ViewGroup) viewGroup.findViewById(R.id.relative); Button button = new Button(this); RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); params.addRule(RelativeLayout.CENTER_IN_PARENT); button.setLayoutParams(params); button.setBackgroundColor(Color.RED); button.setText("Hello World"); button.setId(100); Button button1=new Button(this); RelativeLayout.LayoutParams params1=new RelativeLayout.LayoutParams(200,200); params1.addRule(RelativeLayout.BELOW,100); button1.setLayoutParams(params1); button1.setBackgroundColor(Color.RED); button1.setText("Hello World"); viewGroup2.addView(button); viewGroup2.addView(button1); setContentView(viewGroup);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
注意我們要先給第一個button一個id,因為是動態創建的所以使用setId方法,設id為100, params1.addRule(RelativeLayout.BELOW,100);核心代碼,意思是將button1設置在id為100的view的下方。
運行結果:
四、后記
上文我為大家詳細解析了View的動態創建,以及動態的添加屬性,有幾點需要注意的:
1、上文中的布局都是用的RelativeLayout,實際上你會發現只有RelativeLayout.layoutParam具有addRules方法,這其實是與XML中相對應的,你在LinearLayout中無法使用Right_of等等相對布局的屬性,這些都是相通的。 實際上我認為在動態生成界面的幾個布局中RelativeLayout是最簡單也是最准確的。
2、為什么要使用動態生成界面?我想在編程中使用XML是無可厚非的,但是App的大趨勢是動態化來減少版本更替,這就涉及到一個不要寫死的問題,國內已經有很多嘗試,即通過服務器動態生成界面。