Kotlin入门(19)Android的基础布局
线性布局
线性布局linearlayout是最常用的布局,顾名思义,它下面的子视图像是用一根线串了起来,所以其内部视图的排列是有顺序的,要么从上到下垂直排列,要么从左到右水平排列。排列顺序只能指定一维方向的视图次序,可是手机屏幕是个二维的平面,这意味着还剩另一维方向需要指定视图的对齐方式。故而线性布局主要有以下两种属性设置方法:
1. setorientation: 设置内部视图的排列方向。linearlayout.horizontal表示水平布局,linearlayout.vertical表示垂直布局。
2. setgravity: 设置内部视图的对齐方式。gravity.left表示靠左对齐、gravity.right表示靠右对齐、gravity.top表示靠上对齐、gravity.bottom表示靠下对齐、gravity.center表示居中对齐。
空白距离margin和间隔距离padding是另外两个常见的视图概念,margin指的当前视图与周围视图的距离,而padding指的是当前视图与内部视图的距离。这么说可能有些抽象,接下来还是做个实验,看看它们的显示效果到底有什么不同。下面是个实验用的布局文件内容,通过背景色观察每个视图的区域范围:
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<!-- 外层布局的背景色是蓝色 -->
<linearlayout
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#00aaff" >
<!-- 中间布局的背景色是黄色 -->
<linearlayout
android:id="@+id/ll_margin"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffff99" >
<!-- 内层视图的背景色是红色 -->
<view
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ff0000" />
</linearlayout>
</linearlayout>
</linearlayout>
与上述布局文件对应的页面kotlin代码如下,根据不同的按钮分别设置不同方向上的margin和padding数值:
//该页面用于演示margin和padding的区别
class linearlayoutactivity : appcompatactivity() {
override fun oncreate(savedinstancestate: bundle?) {
super.oncreate(savedinstancestate)
setcontentview(r.layout.activity_linear_layout)
//设置ll_margin内部视图的排列方式为水平排列
ll_margin.orientation = linearlayout.horizontal
//设置ll_margin内部视图的对齐方式为居中对齐
ll_margin.gravity = gravity.center
btn_margin_vertical.setonclicklistener {
//kotlin对变量进行类型转换的关键字是as
val params = ll_margin.layoutparams as linearlayout.layoutparams
//setmargins方法为设置该视图与外部视图的空白距离
//此处设置左边和右边的margin空白距离为50dp
params.setmargins(0, dip(50), 0, dip(50))
ll_margin.layoutparams = params
}
btn_margin_horizontal.setonclicklistener {
val params = ll_margin.layoutparams as linearlayout.layoutparams
//此处设置顶部和底部的margin空白距离为50dp
params.setmargins(dip(50), 0, dip(50), 0)
ll_margin.layoutparams = params
}
//setpadding方法为设置该视图与内部视图的间隔距离
btn_padding_vertical.setonclicklistener {
//此处设置左边和右边的padding间隔距离为50dp
ll_margin.setpadding(0, dip(50), 0, dip(50))
}
btn_padding_horizontal.setonclicklistener {
//此处设置顶部和底部的padding间隔距离为50dp
ll_margin.setpadding(dip(50), 0, dip(50), 0)
}
}
}
依据页面代码例子,kotlin代码与java代码的写法有以下三点区别:
1. kotlin允许对属性orientation直接赋值,从而取代了setorientation方法;类似的还有属性gravity取代了setgravity方法;
2. kotlin使用关键字as进行变量的类型转换;
3. kolin支持调用dip方法将dip数值转换为px数值,倘若由java编码则需开发者自己实现一个像素转换的工具类;
因为dip方法来自于kotlin扩展的anko库,所以需要在activity代码头部加上下面一行导入语句:
import org.jetbrains.anko.dip
既然用到了anko库,自然要修改模块的build.gradle,在dependencies节点中补充下述的anko-common包编译配置:
compile "org.jetbrains.anko:anko-common:$anko_version"
anko库除了提供dip方法,还提供了sp、px2dip、px2sp、dimen等像素单位的转换方法,具体的方法说明见下表。
dip 将dip单位的数值转换为以px为单位的数值
sp 将sp单位的数值转换为以px为单位的数值
px2dip 将px单位的数值转换为以dip为单位的数值
px2sp 将px单位的数值转换为以sp为单位的数值
dimen 将dip单位的数值转换为以sp为单位的数值
相对布局
由于线性布局的视图排列方式比较固定,既不能重叠显示也不能灵活布局,因此复杂一些的界面往往用到相对布局relativelayout。相对布局内部的视图位置不依赖于排列规则,而依赖于指定的参照物,这个参照物可以是与该视图平级的视图,也可以是该视图的上级视图(上级视图即相对布局自身)。有了参照物之后,还得指定当前视图位于参照物的哪个方向,才能确定该视图的具体位置。
在代码中指定参照物及其所处方位,调用的是布局参数对象的addrule方法,方法格式形如“addrule(方位类型, 参照物的资源id)”。下面是个给相对布局添加下级视图的kotlin代码例子:
//根据参照物与方位类型添加下级视图
private fun addnewview(align: int, referid: int) {
var v = view(this)
v.setbackgroundcolor(color.green)
val rl_params = relativelayout.layoutparams(100, 100)
rl_params.addrule(align, referid)
v.layoutparams = rl_params
v.setonlongclicklistener { vv -> rl_content.removeview(vv); true}
rl_content.addview(v)
}
代码里的方位类型有多种取值,比如relativelayout.left_of表示位于指定视图的左边,relativelayout.align_right表示与指定视图右侧对齐,relativelayout.center_in_parent表示位于上级视图*等等。举个例子,让某视图位于指定视图上方,且与上级视图的左侧对齐,则调用addrule方法的kotlin代码如下所示:
rl_params.addrule(relativelayout.above, 指定视图的资源id)
rl_params.addrule(relativelayout.align_parent_left, 上级视图的资源id)
由此可见,常规的addrule调用代码有点冗长,因此kotlin利用anko库将相对位置进行了简化,具体办法是引入扩展函数实现相对位置的设定,譬如above方法代表位于指定视图上方,alignparentleft方法代表与上级视图的左侧对齐。于是原来的kotlin代码简化如下:
rl_params.above(指定视图的资源id)
rl_params.alignparentleft()
因为这几个新方法来自于anko库,所以要在代码头部加上下面一行导入语句:
import org.jetbrains.anko.*
另外要修改模块的build.gradle,在dependencies节点中补充下述的anko-common包编译配置:
compile "org.jetbrains.anko:anko-common:$anko_version"
除了above和alignparentleft之外,anko也提供了所有的相对位置设定方法,具体的对应关系说明见下表。
anko库的相对位置 relativelayout类的相对位置
leftof left_of
sametop align_top
above above
sameleft align_left
rightof right_of
samebottom align_bottom
below below
sameright align_right
centerinparent center_in_parent
alignparentleft align_parent_left
centervertically center_vertical
alignparenttop align_parent_top
centerhorizontally center_horizontal
alignparentright align_parent_right
alignparentbottom align_parent_bottom
推荐阅读