動態添加綜合佈局---動態添加控件及將某XML動態加入到Activity顯示(續)

總效果:

這裏動態生成十個相同的列表,這是最終效果,但凡事都是從易而難的,下面我們就從XML生成一項內容開始講解。

一、利用XML生成一項列表

這裏先利用XML生成一項列表開始,先看一項列表的效果圖及對應代碼:

對應的XML代碼爲:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/layout_root"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >
 
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#19000000"
        android:gravity="center_horizontal"
        android:paddingBottom="20dip"
        android:paddingTop="20dip"
        android:text="嘗試動態生成列表"
        android:textColor="#ff0000"
        android:textSize="24sp" />
 
    <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical" >
 
        <LinearLayout
            android:id="@+id/list_Lin"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >
 
            <!-- 動態生成部分開始 -->
             <RelativeLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content" >
 
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_margin="5dip"
                    android:layout_marginRight="10dip"
                    android:layout_toLeftOf="@+id/image"
                    android:background="#ff00ff00"
                    android:orientation="horizontal"
                    android:padding="5dip" >
 
                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="我的第一次經歷"
                        android:textColor="#ff000000"
                        android:textSize="20dip" />
                </LinearLayout>
 
                <ImageView
                    android:id="@+id/image"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentRight="true"
                    android:clickable="true"
                    android:padding="5dip"
                    android:src="@drawable/plus" />
            </RelativeLayout>
            <!-- 動態生成部分結束 -->
 
        </LinearLayout>
    </ScrollView>
 
</LinearLayout>

動態生成註釋裏的部分就是我們將要用代碼生成的部分,這裏寫出來是爲了在寫代碼時參考,現在把註釋裏的部分刪掉,開始在代碼中生成。

二、使用XML和JAVA代碼生成界面

 先貼出完整的代碼,然後再逐步講解。

 完整代碼:

package com.example.trydynamiclayout;
/**
 * write by harvic
 * 2014-4-25
 * http://blog.csdn.net/harvic880925
 */
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Color;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
 
public class MainActivity extends Activity {
	
	private static int id = 100;
 
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		final LinearLayout lin = (LinearLayout) findViewById(R.id.list_Lin); 
		LinearLayout.LayoutParams LP_FW = new LinearLayout.LayoutParams(
				LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
		RelativeLayout newSingleRL=new RelativeLayout(this);
		
		for(int i=0;i<10;)
		{
			newSingleRL=generateSingleLayout(id,"第"+(++i)+"個動態列表");
			lin.addView(newSingleRL,LP_FW);//全部用父結點的佈局參數
		}
		
		
//		final LinearLayout root = (LinearLayout) findViewById(R.id.layout_root); //獲取總根結點
//		setContentView(root); //這裏必須是總根結點		
	}
	/**
	 * 新建一個列表item
	 * @param imageID 新建imageView的ID值
	 * @param str  TextView要顯示的文字
	 * @return 新建的單項佈局變量
	 */
	private RelativeLayout generateSingleLayout(int imageID,String str)
	{
		RelativeLayout layout_root_relative=new RelativeLayout(this);
		
		LinearLayout layout_sub_Lin=new LinearLayout(this);
		layout_sub_Lin.setBackgroundColor(Color.argb(0xff, 0x00, 0xff, 0x00));
		layout_sub_Lin.setOrientation(LinearLayout.VERTICAL);
		layout_sub_Lin.setPadding(5, 5, 5, 5);
		
		TextView tv = new TextView(this);
		LinearLayout.LayoutParams LP_WW = new LinearLayout.LayoutParams(
		LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
		tv.setText(str);
		tv.setTextColor(Color.argb(0xff, 0x00, 0x00, 0x00));
		tv.setTextSize(20);
		tv.setLayoutParams(LP_WW);
		layout_sub_Lin.addView(tv);
		
		RelativeLayout.LayoutParams RL_MW = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
				RelativeLayout.LayoutParams.WRAP_CONTENT);//尤其注意這個位置,用的是父容器的佈局參數
		RL_MW.setMargins(5, 5, 10, 5);
		RL_MW.addRule(RelativeLayout.LEFT_OF,imageID);
		layout_root_relative.addView(layout_sub_Lin,RL_MW);
		
		
		 ImageView imageView = new ImageView(this);    
		 RelativeLayout.LayoutParams RL_WW = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
					RelativeLayout.LayoutParams.WRAP_CONTENT);
		 imageView.setPadding(5, 5, 5, 5);
		 RL_WW.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
	     imageView.setLayoutParams(RL_WW);  
	     imageView.setClickable(true);
	     imageView.setId(imageID);
	     imageView.setImageResource(R.drawable.plus);
	     layout_root_relative.addView(imageView);
	     
	     return layout_root_relative;
		
	}
 
}

講解:

 一、先看generateSingleLayout(int imageID,String str)

 1、看這段代碼: 

RelativeLayout layout_root_relative=new RelativeLayout(this);
 
LinearLayout layout_sub_Lin=new LinearLayout(this);
layout_sub_Lin.setBackgroundColor(Color.argb(0xff, 0x00, 0xff, 0x00));
layout_sub_Lin.setOrientation(LinearLayout.VERTICAL);
layout_sub_Lin.setPadding(5, 5, 5, 5);
 
TextView tv = new TextView(this);
LinearLayout.LayoutParams LP_WW = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
tv.setText(str);
tv.setTextColor(Color.argb(0xff, 0x00, 0x00, 0x00));
tv.setTextSize(20);
tv.setLayoutParams(LP_WW);
layout_sub_Lin.addView(tv);
 
RelativeLayout.LayoutParams RL_MW = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
		RelativeLayout.LayoutParams.WRAP_CONTENT);//尤其注意這個位置,用的是父容器的佈局參數
RL_MW.setMargins(5, 5, 10, 5);
RL_MW.addRule(RelativeLayout.LEFT_OF,imageID);
layout_root_relative.addView(layout_sub_Lin,RL_MW);

 

根據上面的XML可以,我們要首先生成一個RelativeLayout,這就是layout_root_relative。

注意一: (控件的佈局參數選擇方式)

然後生成其第一個字佈局LinearLayout  layout_sub_Lin;然後再生成layout_sub_Lin裏唯一的一個控件,注意這裏設置LayoutParams的方式,使用的是LinearLayout 參數!!!!對於如何選擇當前控件的佈局layout_width、layout_height的參數的方法,主要是看其父佈局!!!!如果其父佈局是LinearLayout 設置其LayoutParams參數時就要使用LinearLayout.LayoutParams,正如這裏的TextView tv。而如果其父容器的相對佈局呢,一樣,換它父佈局的來,使用RelativeLayout.LayoutParams RL_MW,如這裏的LinearLayout layout_sub_Lin,所以即便layout_sub_Lin自己是佈局控件也要按其父容器的佈局方法寫!!!!  
 

注意二: layout_toLeftOf的代碼書寫方法 

在XML中,對於此LinearLayout的相對佈局,用到了android:layout_toLeftOf="@+id/image",而在代碼中是動態生成的控件,如何利用此規則呢。
首先給動態生成的ImageView設置一個ID值,此ID值在些Acitivity中必須是唯一的,不可衝突的,如果衝突,關於用到此ID值的任何代碼都將是無效的!這也就是後面代碼中會看到的imageView.setId(imageID);
然後利用addRule()添加規則。

 2、剩餘代碼就沒什麼好講的了,就是生成一個imageView設置ID值及其它參數,然後添加到RelativeLayout中,並將layout_root_relative返回。
 

 二、onCreate()函數

 這段代碼如下:

final LinearLayout lin = (LinearLayout) findViewById(R.id.list_Lin); 
LinearLayout.LayoutParams LP_FW = new LinearLayout.LayoutParams(
		LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
RelativeLayout newSingleRL=new RelativeLayout(this);
 
for(int i=0;i<10;)
{
	newSingleRL=generateSingleLayout(id,"第"+(++i)+"個動態列表");
	lin.addView(newSingleRL,LP_FW);//全部用父結點的佈局參數
}
 
 
final LinearLayout root = (LinearLayout) findViewById(R.id.layout_root); //獲取總根結點
setContentView(root); //這裏必須是總根結點	

1、先看For循環及其上部的代碼:

final LinearLayout lin = (LinearLayout) findViewById(R.id.list_Lin); 

找到當前新生成的ITEM項的插入位置。

LinearLayout.LayoutParams LP_FW = new LinearLayout.LayoutParams(
		LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); 
newSingleRL=generateSingleLayout(id,"第"+(++i)+"個動態列表");
lin.addView(newSingleRL,LP_FW);//全部用父結點的佈局參數

這裏是兩塊代碼,先看第二塊,先是新生成一項,注意這一項返回的結點是RelativeLayout layout_root_relative,然後將其插入到列表位置中去,注意要插入的佈局是LinearLayout lin,也就是layout_root_relative的父結點是LinearLayout,所以這也就是在addView時爲什麼它對應的佈局參數使用LinearLayout.LayoutParams的原因了!


 2、setContentView(root);顯示視圖 

 這段代碼如下:
 

final LinearLayout root = (LinearLayout) findViewById(R.id.layout_root); //獲取總根結點
setContentView(root); //這裏必須是總根結點		

這裏最注意的一點,setContentView()所設置的視圖結點是整個XML的根結點!!!!設置爲其它結點會發生異常!!!很容易理解。

 

更正:

在原來的onCreate代碼中,在代碼的最後,加上了

final LinearLayout root = (LinearLayout) findViewById(R.id.layout_root); //獲取總根結點
setContentView(root); //這裏必須是總根結點	

其實這樣做是完全沒有必要的,直接將這兩句刪除,效果是完全一樣的。

 

原因在於,在其上面的代碼中,我們通過

final LinearLayout lin = (LinearLayout) findViewById(R.id.list_Lin);

 

找到了要插入佈局的結點位置,直接在其下面插入佈局代碼,界面會自動更新,根本不需要重新setContentView()

 

在博客中,我將這兩句無關代碼註釋了起來,而源碼中沒有更改過來,請大家注意一下,由於當時剛接觸這部分,對大家造成的誤導,深表歉意……

 

三、完全使用JAVA代碼生成UI界面

這部分其實在上面的改動不大,只是完全使用代碼構建整個界面,由於這種方法構建UI可維護性很差,所以不推薦使用。

其它代碼不變,OnCreate()函數代碼如下:

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
//		setContentView(R.layout.activity_main);
		
		final LinearLayout lin = new LinearLayout(this);
		lin.setOrientation(LinearLayout.VERTICAL);
		LinearLayout.LayoutParams LP_FW = new LinearLayout.LayoutParams(
				LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
		RelativeLayout newSingleRL=new RelativeLayout(this);
		
		for(int i=0;i<10;)
		{
			newSingleRL=generateSingleLayout(id,"第"+(++i)+"個動態列表");
			lin.addView(newSingleRL,LP_FW);//全部用父結點的佈局參數
		}
		
		setContentView(lin); //這裏必須是總根結點		
	}

效果圖:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章