第3章 Android常用布局 目前使用Android Studio开发设计UI(User Interface,用户接口)时还无法提供类似Visual Studio所见即所得的图形界面设计方式,但依靠线性布局(LinearLayout)、表格布局(TableLayout)、相对布局(RelativeLayout)、帧布局(FrameLayout)、绝对布局(AbsoluteLayout)、网格布局(GridLayout)和约束布局(ConstraintLayout)等已经能开发出各式各样 UI界面。本章节通过案例来学习各种布局的特点和相关属性设置。 在Android的UI开发中需要了解长度单位的几种表示方式。 视频讲解 3.1Android长度单位 Android布局设计的长度单位没有完全统一。常见的单位有px、dp、sp、pt、mm和in共6种。在布局文件的长度相关属性值中输入数字后, 图31智能提示中的长度单位 弹出智能提示中的长度单位,如图31所示。智能弹出提示框中会显示6种长度单位供开发人员选择。 以下是与长度相关的技术术语。 (1) px: 即像素(pixels),1px代表屏幕上一个物理的像素点。 (2) dp: 独立像素密度(Density Independent Pixels),早期叫dip),与像素无关。 (3) sp: 主要用于设置字体尺寸,会随着系统的字体大小而改变,即同样大小的dp和sp字体,在Android设置中改变字体大小后,以sp为单位的字体会随系统字体大小改变而改变,以dp为单位的字体大小不会改变。正常字体1dp=1sp,大字体和超大字体1sp>1dp。以下是布局文件代码。 【main.xml】 01 02 06 07 12 13 18 以上代码按系统默认字体大小的效果如图32所示。 系统字体改成大字体后的效果如图33所示。 (4) in: 英寸,1in=2.54cm,一般用于屏幕对角线尺寸单位。 (5) pt: 磅,1in/72的长度,1pt=1in*2.54cm/72in≈0.035cm。 (6) 分辨率: 如果屏幕的分辨率是 1080*1920,是指水平方向上的像素数是1080px,垂直方向上像素数是1920px,屏幕分辨率如图34所示,根据勾股定律对角线则为2203px。 图32系统默认字体大小的效果 图33系统字体改成大字体后的效果 图34屏幕分辨率 (7) 屏幕像素密度: 图34的对角线的像素数为2203px,如果是5英寸屏(指对角线尺寸),屏幕像素密度为2203÷5=440; 如果是6寸屏,屏幕像素密度为2203÷6=367。如此一来就会有很多不同的屏幕像素密度,同样的图片在屏幕中显示所占比例也就不同。为此Android引入像素密度与逻辑密度的概念。 (8) 像素密度与逻辑密度: 像素密度(dot per inch,dpi)就是每英寸的像素点数,不同的像素密度对应不同的Android dpi名称。如像素密度是160,意思是每英寸像素数160px,对应的dpi名称为mdpi。Android Studio在构建项目时会自动建立一个名为HelloAndroid\app\src\main\res\mipmapmdpi的目录,目录中默认提供的图片分辨率为48×48。Android Studio同时也会建立其他Android dpi名称的目录,让不同分辨率、不同尺寸的Android设备自行调用不同目录中的图片文件,以保证不同参数的屏幕尽可能显示相似界面。像素密度是40的倍数。像素密度与逻辑密度如表31所示。 表31像素密度与逻辑密度 Android dpi名称分辨率默认图片尺寸像素密度比例逻辑密度 xxxhdpi3840*2160192*192640164 xxhdpi1920*1080144*144480123 xhdpi1280*72096*9632082 hdpi480*80072*7224061.5 mdpi480*32048*4816041 ldpi320*24036*3612030.75 逻辑密度是以160dpi为基准,其他像素密度与160dpi的比值,或者是像素密度对应的比例值除以4,也是dp转px的系数。 dp与px的换算关系为: px=dp*dpi/160,如160dpi的mdpi,1dp*160dpi/160=1px,对于基准160dpi而言,逻辑密度density=1(160dpi/160dpi或者比例4/4)。又如240dpi的hdpi,1dp*240dpi/160=1.5px,对于基准160dpi而言,逻辑密度density=1.5(240dpi/160dpi或者比例为6/4)。换言之,要将mdpi的图片在hdpi上也能同比例显示,只需将mdpi下的图片放大1.5倍即可。在实际的设计中还可以使用Java代码获取屏幕分辨率然后换算比例进行屏幕动态布局,以此保证在不同分辨率的屏幕下都能按同样比例显示。以下是获取屏幕相关尺寸参数代码。 【FirstActivity.java】 01public class FirstActivity extends Activity 02{ 03 04@Override 05public void onCreate(Bundle savedInstanceState) 06{ 07super.onCreate(savedInstanceState); 08setContentView(R.layout.main); 09 10String str = ""; 11DisplayMetrics dm = new DisplayMetrics(); 12dm = this.getApplicationContext().getResources().getDisplayMetrics(); 13str += "屏幕分辨率为:" + dm.widthPixels + " * " + dm.heightPixels + "\n"; 14str += "水平方向分辨率:" + dm.widthPixels + "px\n"; 15str += "垂直方向分辨率:" + dm.heightPixels + "px\n"; 16str += "逻辑密度:" + dm.density + "\n"; 17str += "xdpi:" + dm.xdpi + "像素/英寸\n"; 18str += "ydpi:" + dm.ydpi + "像素/英寸\n"; 19Log.i("xj", str); 20} 21} 程序运行结果如下: I:屏幕分辨率为:1080 * 1776 水平方向分辨率:1080px 垂直方向分辨率:1776px 逻辑密度:3.0 xdpi:480.0像素/英寸 ydpi:480.0像素/英寸 将上面运行结果xdpi的480除以基准像素密度160,得到的结果3就是逻辑密度。 视频讲解 3.2线 性 布 局 线性布局是Android早期开发版本的默认布局,使用LinearLayout标签,通过设置android:orientation属性值为horizontal(水平)或vertical(垂直)来将其内的控件按照水平方向或垂直方向依次排列。排列的控件不用指定位置的相关属性(简单即是美的体现),控件显示位置与在线性布局中出现的先后顺序相关。线性布局可以互相嵌套形成更复杂的结构。布局文件代码如下: 【main.xml】 01 02 07 08 12 13 20 21 28 29 36 37 38 42 43 50 51 58 59 66 67 74 75 76 77 线性布局的运行结果如图35所示。 从布局代码和组件树(见图36)所示的结构可以看出,整个布局的结构为,最外层是一个垂直线性布局,内嵌一个水平线性布局(含3个TextView)和一个垂直线性布局(含4个TextView)。TextView控件的android:layout_width属性常用值有match_parent(早期版本为fill_parent,将TextView控件宽度设置为父容器宽度)、wrap_content(按TextView的显示文本内容长度来设置宽度,如果文本内容显示宽度超过父容器宽度则将宽度设为父容器宽度,多余的文本在下一行中显示)和具体数值宽度(如第30行的200dp)。android:layout_height属性用于设置高度,与设置宽度概念类似。 图35线性布局的运行结果 图36组件树 显示界面标题栏下的第一行分别显示红、绿、蓝3种颜色的TextView,前两个TextView按文字长度显示,第三个TextView定义的宽度为200dp,大于文字长度,所以TextView控件中文字离控件右边缘有一段距离。 后面几行显示了不同文字长度的TextView在android:layout_width宽度属性分别设置为match_parent和wrap_content时的显示差异。读者可修改代码观察运行结果中TextView的宽度和折行变化。 在图36的组件树右侧单击图标按钮可以修改控件是否可见。图标提示控件代码有警示信息。本案例中将TextView中的文字直接以字符串形式赋予了android:text,而Android Studio建议采用“@string/字符串变量名”的方式定义TextView的值。在Code视图中警示方式会变为将相应属性背景色变为黄色,如图37所示。在Design视图中单击橙色三角形,在弹出信息栏中单击Fix按钮(如果是Code视图,则将光标置于字符串中,按lt+Enter快捷键,在上下文菜单中选择Extract string resource菜单),在弹出的界面中输入字符串变量名,系统自动在strings.xml中注册相应的字符串变量名和对应的字符串值。如果弹出的三角形是红色,代表控件的属性设置中有错误。开发人员可以用鼠标拖动组件树中的控件位置来改变控件显示顺序,Code视图中的代码也会自动调整顺序。右击控件树中的线性布局,在弹出的快捷菜单中可选择转换为其他布局方式。 Code视图如图37所示,android:background属性用来设置背景色。android:textColor属性用来设置文字颜色,颜色值使用6位十六进制数表示,每2位为一组,分别表示红、绿、蓝,合成的颜色效果在左侧行号后显示为颜色方块或在Design视图中查看效果。 用鼠标双击Code视图行号后的颜色方块弹出调色盘,如图38所示,可实现可视化的颜色调配选择。如果在图38中选择Resources选项卡,可选择系统自定义的颜色,如第16行的“@android:color/holo_red_dark”,代表使用Android自定义的颜色。Design视图中显示的效果与实际运行结果可能会有差异,以实际运行结果为准。 图37Code视图 图38调色盘 3.3边 线 和 角 所有的布局方式(含LinearLayout)设定的边界都是没有线条标识的,如果想给相关布局画出边线可以采用以下方式: 【main.xml】 01 02 08 09 15 在线性布局标签属性中添加第5行的代码,设置线性布局背景使用drawable目录下的shape_conner.xml文件(此时shape_conner.xml文件被当成一个图片文件使用)。 【shape_conner.xml】 01 02 03 04 05 06 11 12 15 第4行定义了背景色。 第6~10行定义了屏幕4个角的转角半径,如果半径设为0则为直角。 第13行定义了线条的宽度。 第14行定义了线条的颜色。 给布局添加边线和角的运行结果如图39所示。 图39给布局添加边线和角的运行结果 当前屏幕为圆角的手机越来越多,而大多数模拟器的4个角是直角,如果设计时就处理边角显示适配,则可以考虑采用此方法。 3.4layout_weight Android布局中设置控件的宽度一般使用android:layout_width属性,有时会采用属性android:layout_weight与android:layout_width配合使用。android:layout_weight的作用是设定同一父容器内控件的长度或宽度的占比。先通过一个布局代码来看实际运行结果,再分析与显示结果不同的原因。 视频讲解 【main.xml】 01 02 06 07 11 12