前言:以前曾写过一篇关于动态生成控件的文章《动态添加控件及将某XML动态加入到Activity显示》,比较浅显,对于RelativeLayout的相关布局设置方法及相对布局与线性布局的混合使用的相关内容都没有进行深入讨论。今天再次涉及到这些内容,就不再单独讨论相对布局的相关设置内容了,直接从相对布局与线性布局的混合应用开始。
相关文章:《动态添加控件及将某XML动态加入到Activity显示》
总效果:
这里动态生成十个相同的列表,这是最终效果,但凡事都是从易而难的,下面我们就从XML生成一项内容开始讲解。
一、利用XML生成一项列表
这里先利用XML生成一项列表开始,先看一项列表的效果图及对应代码:
对应的XML代码为:
- <LinearLayoutxmlns: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代码生成界面
先贴出完整的代码,然后再逐步讲解。
完整代码:
- packagecom.example.trydynamiclayout;
- /**
- *writebyharvic
- *2014-4-25
- *http://blog.csdn.net/harvic880925
- */
- importandroid.os.Bundle;
- importandroid.app.Activity;
- importandroid.graphics.Color;
- importandroid.widget.ImageView;
- importandroid.widget.LinearLayout;
- importandroid.widget.RelativeLayout;
- importandroid.widget.TextView;
- publicclassMainActivityextendsActivity{
- privatestaticintid=100;
- @Override
- protectedvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- finalLinearLayoutlin=(LinearLayout)findViewById(R.id.list_Lin);
- LinearLayout.LayoutParamsLP_FW=newLinearLayout.LayoutParams(
- LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);
- RelativeLayoutnewSingleRL=newRelativeLayout(this);
- for(inti=0;i<10;)
- {
- newSingleRL=generateSingleLayout(id,"第"+(++i)+"个动态列表");
- lin.addView(newSingleRL,LP_FW);//全部用父结点的布局参数
- }
- //finalLinearLayoutroot=(LinearLayout)findViewById(R.id.layout_root);//获取总根结点
- //setContentView(root);//这里必须是总根结点
- }
- /**
- *新建一个列表item
- *@paramimageID新建imageView的ID值
- *@paramstrTextView要显示的文字
- *@return新建的单项布局变量
- */
- privateRelativeLayoutgenerateSingleLayout(intimageID,Stringstr)
- {
- RelativeLayoutlayout_root_relative=newRelativeLayout(this);
- LinearLayoutlayout_sub_Lin=newLinearLayout(this);
- layout_sub_Lin.setBackgroundColor(Color.argb(0xff,0x00,0xff,0x00));
- layout_sub_Lin.setOrientation(LinearLayout.VERTICAL);
- layout_sub_Lin.setPadding(5,5,5);
- TextViewtv=newTextView(this);
- LinearLayout.LayoutParamsLP_WW=newLinearLayout.LayoutParams(
- LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);
- tv.setText(str);
- tv.setTextColor(Color.argb(0xff,0x00));
- tv.setTextSize(20);
- tv.setLayoutParams(LP_WW);
- layout_sub_Lin.addView(tv);
- RelativeLayout.LayoutParamsRL_MW=newRelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
- RelativeLayout.LayoutParams.WRAP_CONTENT);//尤其注意这个位置,用的是父容器的布局参数
- RL_MW.setMargins(5,10,5);
- RL_MW.addRule(RelativeLayout.LEFT_OF,imageID);
- layout_root_relative.addView(layout_sub_Lin,RL_MW);
- ImageViewimageView=newImageView(this);
- RelativeLayout.LayoutParamsRL_WW=newRelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
- RelativeLayout.LayoutParams.WRAP_CONTENT);
- imageView.setPadding(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);
- returnlayout_root_relative;
- }
- }
讲解:
一、先看generateSingleLayout(int imageID,String str)
1、看这段代码:
- RelativeLayoutlayout_root_relative=newRelativeLayout(this);
- LinearLayoutlayout_sub_Lin=newLinearLayout(this);
- layout_sub_Lin.setBackgroundColor(Color.argb(0xff,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自己是布局控件也要按其父容器的布局方法写!!!!
在XML中,对于此LinearLayout的相对布局,用到了android:layout_toLeftOf="@+id/image",而在代码中是动态生成的控件,如何利用此规则呢。
首先给动态生成的ImageView设置一个ID值,此ID值在些Acitivity中必须是唯一的,不可冲突的,如果冲突,关于用到此ID值的任何代码都将是无效的!这也就是后面代码中会看到的imageView.setId(imageID);
然后利用addRule()添加规则。
2、剩余代码就没什么好讲的了,就是生成一个imageView设置ID值及其它参数,然后添加到RelativeLayout中,并将layout_root_relative返回。
二、onCreate()函数
这段代码如下:
- finalLinearLayoutlin=(LinearLayout)findViewById(R.id.list_Lin);
- LinearLayout.LayoutParamsLP_FW=newLinearLayout.LayoutParams(
- LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);
- RelativeLayoutnewSingleRL=newRelativeLayout(this);
- for(inti=0;i<10;)
- {
- newSingleRL=generateSingleLayout(id,"第"+(++i)+"个动态列表");
- lin.addView(newSingleRL,LP_FW);//全部用父结点的布局参数
- }
- finalLinearLayoutroot=(LinearLayout)findViewById(R.id.layout_root);//获取总根结点
- setContentView(root);//这里必须是总根结点
1、先看For循环及其上部的代码:
- finalLinearLayoutlin=(LinearLayout)findViewById(R.id.list_Lin);
找到当前新生成的ITEM项的插入位置。
- LinearLayout.LayoutParamsLP_FW=newLinearLayout.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);显示视图
这段代码如下:
- finalLinearLayoutroot=(LinearLayout)findViewById(R.id.layout_root);//获取总根结点
- setContentView(root);//这里必须是总根结点
这里最注意的一点,setContentView()所设置的视图结点是整个XML的根结点!!!!设置为其它结点会发生异常!!!很容易理解。
更正:
- finalLinearLayoutroot=(LinearLayout)findViewById(R.id.layout_root);//获取总根结点
- setContentView(root);//这里必须是总根结点
原因在于,在其上面的代码中,我们通过
- finalLinearLayoutlin=(LinearLayout)findViewById(R.id.list_Lin);
在博客中,我将这两句无关代码注释了起来,而源码中没有更改过来,请大家注意一下,由于当时刚接触这部分,对大家造成的误导,深表歉意……
源码下载地址:http://download.csdn.net/detail/harvic880925/7250631,不要分,仅供分享!
三、完全使用JAVA代码生成UI界面
这部分其实在上面的改动不大,只是完全使用代码构建整个界面,由于这种方法构建UI可维护性很差,所以不推荐使用。
- protectedvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- //setContentView(R.layout.activity_main);
- finalLinearLayoutlin=newLinearLayout(this);
- lin.setOrientation(LinearLayout.VERTICAL);
- LinearLayout.LayoutParamsLP_FW=newLinearLayout.LayoutParams(
- LinearLayout.LayoutParams.FILL_PARENT,LP_FW);//全部用父结点的布局参数
- }
- setContentView(lin);//这里必须是总根结点
- }
该部分源码地址:http://download.csdn.net/detail/harvic880925/7692059