基本概念:
1、 相对布局的基本概念
一个控件的位置它决定于它和其他控件的关系,好处:比较灵活;缺点:掌握比较复杂。
2、 相对布局常用属性介绍
这里将这些属性分成4个组,便于理解和记忆。
a)、以下4个属性设置控件与之间的关系和位置
但是上面4个属性并没有设置各个控件之间是否对齐。
示例1:将控件A放置在控件B的上面,则使用android:layout_above属性,控件布局的效果可以有以下这么两种情况。
1、控件A与控件B对齐,并且控件A是在控件B的上面。
2、控件A没有与控件B对齐,但是控件A又确实是在控件B的上面。
b)、以下5个属性,设置的是控件与控件之间对齐的方式(是顶部、底部还是左、右对齐)。
示例2:在示例1的基础上,设置控件A放置在控件B的上面,使用android:layout_above属性,并且控件A的左边边缘与控件B的左边边缘对齐,使用android:layout_alignLeft属性。
c)、以下4个属性设置控件与父控件之间对齐的方式(是顶部、底部还是左、右对齐)。
d)、以下4个属性设置控件的方向。
可以通过组合这些属性来实现各种各样的布局。
除了这些属性之外,还有一个属性是更加灵活使用的,
android:layout_grivity——指定控件的基本位置(基于父亲),比如说居中,居右等位置(只有一些控件有)
当然在这里我们发现一个问题,就是我们控制各个控件的位置,但是各个空间似乎联系不紧密,是的,这里我们需要使用到这里几个属性:
// 指定移动像素
android:layout_marginTop上偏移的值;
android:layout_marginBottom下偏移的值;
android:layout_marginLeft 左偏移的值;
android:layout_marginRight 右偏移的值;
当然还有其他一些设置:
android:id--- 为控件指定相应的ID
android:text--- 指定控件当中显示的文字,需要注意的是,这里尽量使用strings.xml文件当中的字符串
android:grivity--- 指定控件的基本位置,比如说居中,居右等位置这里指的是控件中的文本位置并不是控件本身。
android:textSize--- 指定控件当中字体的大小
android:background--- 指定该控件所使用的背景色,RGB命名法
android:width--- 指定控件的宽度
android:height--- 指定控件的高度
android:padding*--- 指定控件的内边距,也就是说控件当中的内容
android:sigleLine--- 如果设置为真的话,则控件的内容在同一行中进行显示
看完这些之后,初步认识了relativelayout,那么下面来几个例子带我们走进去认识他吧。
解惑区
padding和margin的用法:
这里我们使用盒子模型来分析一下,如图,每一个控件,我们把它当作一个盒子,那么盒子存在着一个盒子的厚度(内间距),”android:padding”,”android:paddingLeft”…android没有自作聪明的帮你初始化一个padding。所以默认都是0,我们不需要重新设置他。一般他会怎么使用呢?其实我们可以看到,在使用textview结合grivity的时候他用的比较多,其他时候用的比较少。
而margin的使用就比较普遍了,他主要用于调整控件的移动距离,使用它可以更细致的定位到你想要存放的位置,当然注意一点,margin是相对的。如果空间里面没有设置相对于哪个兄弟控件的话,那么就会默认选择跟父亲控件作为参照进行移动,如果有设置兄弟控件,那么就会相对于兄弟控件的位置进行移动。理解起来比较容易接受,我们还是用程序验证一下我们的想法吧。
贴上效果图:
Xml布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/act_bg"
>
<Button
android:id="@+id/back_btn"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="@drawable/back"/>
<LinearLayout
android:id="@+id/role_ly_1"
android:layout_width="250dp"
android:layout_height="100dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="50dp"
android:background="@drawable/help_btn"
android:orientation="vertical">
<TextView
android:id="@+id/role_title1"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="15dp"
android:gravity="center_horizontal"
android:text="@string/help_title"
android:paddingTop="5dp"
android:textColor="#ffdc00"
android:textSize="10sp" />
<TextView
android:id="@+id/role_content1"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginLeft="25dp"
android:layout_marginRight="15dp"
android:text="@string/help_content"
android:textColor="#ffdc00"
android:textSize="10sp"/>
</LinearLayout>
<!-- 右边的模块 -->
<LinearLayout
android:id="@+id/role_ly_2"
android:layout_width="250dp"
android:layout_height="100dp"
android:layout_alignTop="@id/role_ly_1"
android:layout_toRightOf="@id/role_ly_1"
android:layout_marginLeft="10dp" android:background="@drawable/help_btn"
android:orientation="vertical">
<TextView
android:id="@+id/role_title2"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="15dp"
android:gravity="center_horizontal"
android:text="@string/help_title"
android:paddingTop="5dp"
android:textColor="#ffdc00"
android:textSize="10sp"/>
<TextView
android:id="@+id/role_content2"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginLeft="25dp"
android:layout_marginRight="15dp"
android:text="@string/help_content"
android:textColor="#ffdc00"
android:textSize="10sp"/>
</LinearLayout>
</RelativeLayout>
这里我们着重对比,有加上android:layout_toRightOf 和没有加上去的区别:
如图,两个线性布局重叠了。这里我们可以看到,相对布局的相对是非常明确。所以也看到了他的弊端,牵一处而动全身。于是我们更乐意把控件相对于父亲进行布局。上面的第二个linearlayout我们可以这么改:
android:layout_marginRight="10dp"
android:layout_alignParentRight="true"
注意到这里我们的textview使用的布局属性是:
android:layout_gravity="center_horizontal"
android:layout_marginTop="15dp"
android:paddingTop="5dp"
看到布局是这样的:
整个textview距离顶部15dp,而文字在textview中又距离顶部有5dp的间隔,整体使用水平居中,这样让我们的文本更容易定位到我们想要的地方,当然在这里,我们发现一个问题。就是文本的所在位置最好是在背景彩带上,于是我们需要让他缩小点,于是在定义了android:layout_width="match_parent"后我们加上左右两边距离父亲一定的间隔之后就可以让他调整过来而且textview可以自动隐藏,这样就不用担心文本会超出了。
添加的属性是:
android:paddingLeft="32dp"
android:paddingRight="22dp"
android:paddingTop="5dp"
于是如图看起来就好看很多了
当然这里还多说一点就是下面的那个textview,我们关心他的位置,因为他是靠左对齐的,那么我们在保留他android:layout_width="match_parent"后给他添加这两个属性之后,他可以自动适应并缩小,于是看起来就更符合我们的需要了。
android:layout_marginLeft="25dp"
android:layout_marginRight="15dp"
聪明的运用他可以让我们的布局变得更人性化。
这里还提一点就是关于绘制顺序:
这里我们引入第三个linearlayout,属性设置如下:
<!-- 第三个布局 -->
<LinearLayout
android:id="@+id/role_ly_3"
android:layout_width="250dp"
android:layout_height="100dp"
android:layout_centerHorizontal="true"
android:layout_gravity="center_horizontal"
android:layout_marginTop="50dp"
android:background="@drawable/help_btn"
android:orientation="vertical">
<TextView
android:id="@+id/TextView03"
android:layout_width="match_parent"
android:layout_height="18dp"
android:layout_marginTop="15dp"
android:gravity="center_horizontal"
android:paddingLeft="32dp"
android:paddingRight="22dp"
android:paddingTop="5dp"
android:text="@string/help_title"
android:textColor="#ffdc00"
android:textSize="10sp"/>
<TextView
android:id="@+id/role_content3"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginLeft="25dp"
android:layout_marginRight="15dp"
android:layout_marginTop="5dp"
android:text="@string/help_content"
android:textColor="#ffdc00"
android:textSize="10sp"/>
</LinearLayout>
如图所示:
这给我们的启示是,android根据xml的节点自顶而下的绘制图层的。至于有没有z轴一说还需要考究,至少没有一个属性可以证明,所以这里我们小小的鄙视一下不是非常人性化之后需要做多点实现才能让我们的布局更好看。
其实到了这里,我们对相对布局的了解更深一步了,可往往我们的需求是那么的不简单,假设我们现在每个组合控件的内容是多个 ,那么我们该如何处理这个布局呢?
那么我们想到的就是因为每个控件的内容基本是一致,如果我们把第一个做出来,其他的我们让他们自动生成,是否可以符合我们的假设呢?
查看Google android的api我们不难发现,除了用xml布局可以实现,我们还可以使用Java code去控制,这样让我们在处理上更随意。
新建一个activity,我们开始来实现我们的二次改版。
代码如下:
packagecom.example.relativelayout;
importandroid.app.Activity;
importandroid.content.Intent;
importandroid.graphics.Color;
importandroid.os.Bundle;
importandroid.view.Gravity;
importandroid.view.View;
importandroid.view.View.OnClickListener;
importandroid.view.ViewGroup.LayoutParams;
importandroid.widget.LinearLayout;
importandroid.widget.RelativeLayout;
importandroid.widget.ScrollView;
importandroid.widget.TextView;
publicclassMyRelativeLayout extends Activity {
privateScrollView sv;
@Override
protectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.r_layout);
// 获取布局文件中的scrollview
sv= (ScrollView) findViewById(R.id.sv_jcode);
// 获取填充数据
finalString[] ll_title = getResources().getStringArray(R.array.ll_title);
finalString[] ll_content = getResources().getStringArray(R.array.ll_content);
intcount = ll_title.length;
RelativeLayout rl = newRelativeLayout(this);
LinearLayout[] lls = newLinearLayout[count];
RelativeLayout.LayoutParams[] rl_lp = newRelativeLayout.LayoutParams[count];
for(inti = 0; i < count; i++) {
lls[i] = newLinearLayout(this);
lls[i].setId(i + 1); // 测试过id=0的时候,addRule调用的时候无法指派
lls[i].setBackgroundResource(R.drawable.help_btn);
lls[i].setOrientation(1);
lls[i].setPadding(38, 20, 32, 10);
TextView t1 = newTextView(this);
t1.setText(ll_title[i]);
t1.setHeight(30);
t1.setGravity(Gravity.CENTER_HORIZONTAL);
t1.setPadding(10, 5, 0, 0);
t1.setTextSize(10);
TextView t2 = newTextView(this);
t2.setText(ll_content[i]);
t2.setWidth(340);
t2.setHeight(80);
//t2.setBackgroundColor(Color.BLUE);
t2.setTextSize(10);
t2.setTextColor(Color.BLACK);
t2.setPadding(10, 5, 0, 0);
// 把sub布局里面的文本添加到sub布局上
lls[i].addView(t1);
lls[i].addView(t2);
// 设置外部布局的布局参数
rl_lp[i] = newRelativeLayout.LayoutParams(360, 144);
if(i % 2 == 0) {
if(i == 0) {
rl_lp[i].leftMargin= 15;
}
if(i / 2 > 0) {
rl_lp[i].addRule(RelativeLayout.ALIGN_LEFT,i - 1);
rl_lp[i].addRule(RelativeLayout.BELOW,i - 1);
}
} else{
rl_lp[i].addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
rl_lp[i].rightMargin = 25;
if((i - 1) / 2 > 0) {
rl_lp[i].addRule(RelativeLayout.BELOW,i - 1);
}
}
// 把所有的sublayout添加到外部的layout内
rl.addView(lls[i], rl_lp[i]);
// 监听subLayout的点击事件
lls[i].setOnClickListener(newOnClickListener() {
@Override
publicvoidonClick(View v) {
Intent i = newIntent(MyRelativeLayout.this,MyRelativeLayoutDetail.class);
i.putExtra("r_layout_title", ll_title[v.getId() - 1]); // 由于id从1开始,数组下标从零开始要j
i.putExtra("r_layout_content", ll_content[v.getId() - 1]);
MyRelativeLayout.this.startActivity(i);
//MyRelativeLayout.this.finish();
}
});
}
sv.addView(rl);
sv.setVerticalScrollBarEnabled(false);
}
}
布局文件:
<?xml version="1.0"encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/act_bg">
<Button
android:id="@+id/back_btn"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="@drawable/back"/>
<ScrollView
android:id="@+id/sv_jcode"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="50dp"
android:orientation="vertical">
</ScrollView>
</RelativeLayout>
效果图:
strings.xml文件内容就忽略不加上去了。
从代码中我们主要看到有一个RealtiveLayout和RealtiveLayout.LayoutParams,查看源代码我们可以发现,LayoutParams是RealtiveLayout的一个内部类,里面主要定义的动作就是动作规则,“上下左右居中…”和初始化控件的大小,使用addRule(verb, anchor)。而RealtiveLayout里面又定义了各个改变控件的属性,于是我们根据需求就可以定制我们的布局文件了,具体可参照xml布局,值得我们注意的就是这里定位用到的数字都是px为计量单位的,不再是dp。
具体参考文档:
1. http://blog.csdn.net/aomandeshangxiao/article/details/6978681 px dp sp pt异同
2. http://byandby.iteye.com/blog/830420 相对布局基础
第一次在csdn写这种博客,太呛了,一直贴图太辛苦了。附上小demo,有空测试一下吧。