更新时间 | 修改意见 |
---|---|
2016-08-02 | 陈敏 |
第1节 布局与控件的常用概念
界面设计中的控件,就是我们常常看到的按钮
滑动条
文字显示区
等等,它们就像房间里的家具,是界面设计的最小单位。
![](https://i-blog.csdnimg.cn/blog_migrate/7608f85e59b6dfc51496d48681f3ef94.png)
布局是一个可以容纳别的布局(或者控件)的容器。它就像是一个大的房间,房间里面可以放各种家具(控件),也可以再隔离成更多的房间(放入别的布局)。
![](https://i-blog.csdnimg.cn/blog_migrate/b11eb6ae1a1e694f20746b179b0e89d7.png)
不过,两者有很多共同的地方,例如定义它们的大小、边距等等。
1.1 尺寸单位
在使用布局或控件时,有时需要指定它们的尺寸。安卓系统提供了三种单位:
px
:以像素为单位进行设置,屏幕上每一个点,就是一个像素,例如一部安卓手机,屏幕像素是1920 x 1080
,就是说屏幕高度有1920
个像素点,宽度有1080
个像素点,但是在安卓系统中,最好不要使用这个单位来设置尺寸,而是用dp
;sp
:用于字体大小的设置,它可以让字体大小根据用户在设置
中的设置,进行缩放;dp
:密度无关像素,这是在布局和控件中应该使用的单位;
1.1.1 dp的引入
如果用px为单位设定设备区域的大小,通常会有很大的问题。
假设有两个物理尺寸都为5寸大小的屏幕,它们的屏幕分辨率不同,一个是1080*1920,而另一个却是450*800.
如果指定一个按钮的大小为200px长,200px宽,那么它们的显示效果就如下图。很明显,两者的差别也太大了,界面就严重变形了。所以,想让一个区域的大小在不同屏幕的上显示的都差不多,就需要考虑像素密度。为了显示同样的长度,在密度大的屏幕上,使用到的像素就要多一些,在密度小的屏幕上,使用到的像素就要少一些。
![](https://i-blog.csdnimg.cn/blog_migrate/dae75883cd7ae75042bb2dfea4f96504.png)
所以为了解决这个问题,安卓引入了dip的概念-device independed pixel-简称dp。
1.1.2 dpi的定义
在近一步介绍dp
之前,要先讲讲dpi
。dpi
叫做屏幕像素密度,就是每英寸有多少个像素点。我们用简单的数学原理
440dpi
,另一个是
184dpi
。
![](https://i-blog.csdnimg.cn/blog_migrate/ecd7b6e083db8a675bec54381ce5a821.png)
注意,dpi
与dip(dp)
写法很像,千万不要混淆了,前者和密度有关,后者与像素有关。
1.1.3 dpi的划分
安卓使用dpi
为160的数值作为一个基准--baseline
,
- 如果一个设备的
dpi
刚好等于这个基准,那么它就是mdpi设备; - 如果一个设备的
dpi
是这个基准的1.5倍,那么它就是hdpi设备; - 如果一个设备的
dpi
是这个基准的2倍,那么它就是xhdpi设备; - 如果一个设备的
dpi
是这个基准的3倍,那么它就是xxhdpi设备;
这就是划分不同屏幕密度的依据。
像素密度类型 | 像素密度大小 | 与Baseline比值 |
---|---|---|
mdpi | 160 | 1 |
hdpi | 240 | 1.5 |
xhdpi | 320 | 2 |
xxhpi | 480 | 3 |
按照这样的约定划分,
- 刚才1080*1920的屏幕应该属于xxhdpi类型;
- 450*800的屏幕应该属于mdpi类型;
现在的安卓手机几乎都在往高清屏幕发展,所以xhdpi和xxhdpi是最为常见的设备类型。
屏幕的dpi
计算出来不一定就是基准(160)的整数倍,而且安卓系统也不一定会使用我们计算出来的那个值作为设备的dpi。
设备通常会在系统中指定一个接近那个值的dpi值,例如,你的Nexus5,虽然计算出来是440,但系统实际上给它指定的是480,刚好是基准的3倍。
在系统的目录的/system/build.prop
文件中,可以看到,
//这里指定了一个dpi值
ro.sf.lcd_density=480
1.1.4 dp与px的关系
安卓引入了dp(dip)
的概念之后,实际显示的像素就可以通过下面这个公式计算出来
相同dp
的情况下,密度大的设备,实际像素就占的大,密度小点设备,实际像素就占用小了。因此使用dp这个单位后,按钮在两种不同的屏幕上的实际显示大小,几乎就是一样的了。
例如刚才两种屏幕。如果我指定按钮的大小为200dp*200dp,那么它们在各自的屏幕上占用的实际像素分别是230px*230px与550px*550px,真实设备上看上去的确差不多。
![](https://i-blog.csdnimg.cn/blog_migrate/179067b7fb2f11f2033281992948c76a.png)
1.2 大小设置
在设置布局或者控件大小的时候,会使用它们的android:layout_width
和android:layout_height
属性,
<View
android:layout_width="match_parent"
android:layout_width="wrap_content"/>
它们的值可以设定成,
- 特定的数值:例如
5dp
。当然也可以使用除了dp
以外其他的尺寸单位,但是考虑到屏幕的像素密度不同,我们都使用dp
为单位; match_parent
:以父布局的宽度(或长度)为界,尽可能占据全部空间;wrap_content
:以子布局或控件内容的宽度(或长度)为界,尽可能少占据空间;
1.3 边距
margin
:控件或布局相对外面组件的边距叫做margin
,例如一个LinearLayout
与它相邻的另一个FrameLayout
之间的间隔。在布局或控件中,使用以下属性来定义,android:layout_margin="5dp" android:layout_marginLeft="5dp" android:layout_marginTop="5dp" android:layout_marginRight="5dp" android:layout_marginBottom="5dp"
padding
:控件或布局为内部区域保留的边距叫做padding
,例如一个LinearLayout
与它内部的一个FrameLayout
之间的间隔,或者TextView
的边框与它内部文字之间的间隔。在布局或控件中,使用以下属性来定义,android:padding="5dp" android:paddingLeft="5dp" android:paddingTop="5dp" android:paddingRight="5dp" android:paddingBottom="5dp"
![](https://i-blog.csdnimg.cn/blog_migrate/9974853cd460630959bb59f29ccd8259.png)
1.4 可见性
布局和控件都还有个常用的android:visiblility
属性,
<View
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:visibility="visible"/>
它有3个可选的参数,
visible
:这个控件或者布局是可见的;invisible
:这个控件或者布局是不可见的,但是它的位置还在那里,只是界面上看不到它,别的控件或布局还是需要考虑它的位置;gone
:这个控件或者布局不仅不可见,而且它的位置已经不在那里了,在显示的时候,别的控件或布局都不用考虑它的位置了;
默认情况下,如果不指定这个属性,系统通常会为它们使用visible
参数。
1.5 位置
无论控件还是布局都可以设置它本身相对于父布局的偏好位置,例如是居中还是靠左。例如一个放到LinearLayout
中的Button
,它希望自己位于父布局内部靠上的位置,就可以添加android:layout_gravity
属性,设置值为top
,
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_gravity="top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello world!"/>
</LinearLayout>
其它可以设置的值还有bottom
left
right
center
center_horizontal
center_vertical
。
实际效果也要看父布局的类型,比如在上面的例子中,子控件的位置属性只是向LinearLayout
提出请求,但LinearLayout
还是要从自己的实际情况出发--它不一定能满足所有子控件或者布局的要求。
比如这里使用bottom
值,就是没有意义的。因为LinearLayout
本来就是要求子布局(或控件)从上到下进行排列。所以即使设定了bottom
值,Button
还是会在上方。
控件或者布局,也可以设置自己的内容相对于内部的位置。例如上面的例子中,要将Button
放到LinearLayout
底部靠右的位置,可以为其android:gravity
属性设置bottom|right
。这里的|
表示并且
,
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom|right">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello world!"/>
</LinearLayout>
这里可以让LinearLayout
从下方开始排列子控件的原因是:这是LinearLayout
自己的属性,而不是听子控件的安排。android:gravity
属性告诉了LinearLayout
,在排列时优先放下边、右边。
/*******************************************************************/
* 版权声明
* 本教程只在CSDN和安豆网发布,其他网站出现本教程均属侵权。
*另外,我们还推出了Arduino智能硬件相关的教程,您可以在我们的网店跟我学Arduino编程中购买相关硬件。同时也感谢大家对我们这些码农的支持。
*最后再次感谢各位读者对安豆
的支持,谢谢:)
/*******************************************************************/