android将布局与具体操作分为xml文件和java文件,xml文件主要负责布局,但是xml文件完成的所有任务java文件都是可以完成的,并且解析xml文件也是需要资源的,只不过google推荐这样使用,一是为了界面和逻辑分离,二是xml的逻辑控制很方便。所以牺牲一点资源来解析xml文件是可取的。
我将其分为静态布局和动态布局(也可以称为交互),静态布局直接加载,方便查看和修改。动态布局需要代码控制,用户体验好。
开始一个项目之前,要想好静态布局和动态布局的分布,一句话,能在xml文件中做的事,一定不要放在java里做。
1.静态布局
1.1 View和ViewGroup
静态布局都是由View和ViewGroup继承而来。
- View是所有的UI组件都要继承并实现的,一个View要在屏幕上占据一块矩形区域。
- ViewGroup是一个容器,可以将View添加进ViewGroup中,ViewGroup可以对其内的View进行布局,ViewGroup可以添加其他的ViewGroup。
所有的控件都是从View继承而来,ViewGroup是View的一个重要子类,绝大多数布局都是从ViewGroup继承而来。
1.2 xml基本属性
1.2.1 xml文件声明
<?xml version="1.0" encoding="utf-8"?>
这是xml的声明和编码格式,删掉也是可以,但是一般都会保留,并且编码有时候也是需要注意的。
1.2.2 xml文件命名空间
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns是xml namespace 的简写,是引用命名空间。
这类似于c++ using namespace std,这个必须在最外层的Layout进行声明。因为只有在这个命名空间内,android:layout_width 才会有意义。因为在这个命名空间内,android:layout_width是被定义过的,只需要拿来引用即可。
当然,xml命名空间是可以自定义的。至于为什么要有命名空间,是为了区别不同部分相同元素。详细可以查查xml的命名空间。此处因重心在android,点到为止。
1.2.3 layout属性
android:layout_width=""
android:layout_height=""
一横一竖,确定 了layout的大小。
一共有2种填法:
- 属性填法
- fill_parent 和match_parent是填充满整个父空间。
- wrap_content而是自适应大小,随着内容的多少进行扩大。
- 数值填法
- dp、dpi:是动态适应所有分辨率的单位,会随着屏幕大小的改变而改变。
- px:是设计师常用的像素,不会随着屏幕大小的改变而改变。
这样,xml文件基本就可以运行了。
xml文件基本要素:命名空间,layout属性
1.3 六大布局
1.3.1 LinearLayout
line是线的意思,linear是线性的意思,这个布局就是线性布局。只能横着排,或者只能竖着排。
关键属性是orientation,这个是方向的意思。
这个有两个选项 vertical,horizontal。是不是觉得太长记不住呢,有一个简便的记忆方法,利用IDE的自动提示功能,只要记住第一个字母就可以了对吧,可以把h记作横(heng)这样就不会错了。
1.3.2 RelativeLayout
relative是相对的意思,这个布局是相对布局。
相对布局就是依据父元素和某元素进行相对布局。
有三种类型的属性:
- 属性值是true或false
- android:layout_centerHrizontal 水平居中
- android:layout_centerVertical 垂直居中
- android:layout_centerInparent 相对于父元素完全居中。
- android:layout_alignParentBottom 位于父元素的下边缘
- android:layout_alignParentTop 位于父元素的上边缘
- android:layout_alignParentLeft 位于父元素的左边缘
- android:layout_alignParentRight 位于父元素的右边缘
- 属性值是"@id/*“
- android:layout_below 在某元素的下方
- android:layout_above 在某元素的上方
- andorid:layout_toRightOf 在某元素的右方
- android:layout_toLeftOf 在某元素的左方
- android:layout_alignBottom 和某元素下方对齐
- android:layout_alignTop 和某元素上方对齐
- android:layout_alignRight 和某元素右方对齐
- android:layout_alignLeft 和某元素左方对齐
- 属性值是数值
- android:layout_marginLeft 离某元素左边缘的距离
- android:layout_marginRight 离某元素右边缘的距离
- android:layout_marginTop 离某元素上边缘的距离
- android:layout_marginBottom 离某元素下边缘的距离
上面这两种是最常用的两种布局,基本能完成一些基本的布局了。
1.3.3 自定义布局
自定义是对ViewGroup进行继承,一般要实现以下方法:
- 重写onMeasure()方法对子View进行测量。在onMeasure中计算childView的测量值以及模式,以及设置自己的宽和高。
- 重写onLayout()方法确定子View的位置,对所有childView进行定位(设置childView的绘制区域)。
自定义ViewGroup是很有必要的,因为当官方给出的空间无法满足自己的需求时,就需要自己取定义一种布局了。
1.3.4 FrameLayout
框架布局,第一个控件放在最底层的左上角,然后后面的控件在左上角一层一层的覆盖上去。类似于Ps图层的样子。
1.3.5 TableLayout
表格布局,顾名思义,就是一个表格。
它遵循着以下结构:
<TableLayout>
<TableRow>
<!-在这里填充第一行的元素->
</TableRow>
<TableRow>
<!-在这里填充第二行的元素->
</TableRow>
</TableLayout>
还有几个重要属性:
- 写在TableLayout中的属性
- android:stretchColumns 设置第几列为伸展(0表示第一列)
- android:shrinkColumns 设置第几列为收缩
- android:collapseColumns 设置第几列为隐藏
- 写在TableRow里的控件里的属性
- android:layout_column 设置控件在第几列
- android:layout_span 设置控件能跨多少列
下面是一个例子:
<TableLayout ……
android:stretchColumns="0"
android:shrinkColumns="1"
android:collapseColumns="2">
<TableRow>
<TextView android:text="我是伸展的第一列"/>
<TextView android:text="我是收缩的第二列"/>
<TextView android:text="我被隐藏了"/>
</TableRow>
<TableRow>
<TextView android:text="我可以伸展的很长很长很长长"/>
<TextView android:text="我可以收缩,我可以变的很深很深很深"/>
<TextView android:text="我被隐藏了T_T"/>
</TableRow>
<TableRow >
<TextView
android:text="我要在第2列"
android:layout_column="1"/>
</TableRow>
<TableRow ……>
<TextView
android:text="我要 跨 两 列"
android:layout_column="0"
android:layout_span="2">
</TableRow>
</TableLayout>
1.3.6 AbsoluteLayout
绝对布局,已经被淘汰了的布局。
所有控件都要设置x,y坐标,使用绝对的布局。
android:layout_x //控件x坐标
android:layout_y //控件y坐标
1.4 控件
1.4.1 android自带控件
来一张大图,控件继承类。
1.4.2 自定义控件
自定义控件有三种方法:
- 对现有控件进行扩展
继承控件后重写onDraw()方法,在回调父类方法前实现自己的逻辑。
@Override
protected void onDraw(Canvas canvas){
//在回调之前实现自己逻辑。
super.onDraw(canvas);
//在回调之后实现自己逻辑。
}
- 通过组合来实现新的控件
- 重写View来实现全新的控件
2 动态布局
2.1 用类修改xml
这是一种最简单的动态布局了,可以使用findViewById找到想要进行接管的控件,然后再修改其中的属性,然后达到动态的目的。
2.2 动态生成
首先创建一个布局管理器,然后使用setContentView()将布局管理器绘制出来,之后再用addView()方法加入控件元素。
LinearLayout linearLayout=new LinearLayout(this);
setContentView(linearLayout);
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
TextView txt=new TextView(this);
tvSecond.setText("这是变身前");
Button btn=new Button(this);
btNext2.setText("变身");
linearLayout.addView(txt);
linearLayout.addView(btn);
btn.setOnClickListener(new OnClickListener(){
public void onClick(View view){
//这次只放置一个TextView不需要布局管理器
TextView tv3=new TextView(Show.this);
tv3.setText("我是变身后");
//直接让页面显示一个TextView
setContentView(tv3);
}
}
);