像素
Android支持的像素单位有:px(像素)、in(英寸)、mm(毫米)、pt(磅,1/72英寸)、dp(与设备无关的显示单位)、dip(就是dp)、sp(用于设置字体大小)。其中,常用的有px、dp和sp三种。
具体来说,px是手机屏幕上可显示的最小单位,与物理设备的显示屏有关。一般来说,同样尺寸的屏幕(比如5寸的手机)看起来越清晰,像素的密度越高,以px计量的分辨率也越大。
dp与物理设备无关,只与屏幕的尺寸有关。一般来说,同样尺寸的屏幕以dp计量的分辨率是一样的,无论这个手机是哪个厂家生产的,dp大小都一样。
sp的原理跟dp差不多,专门用于设置字体大小。手机在系统设置里可以调整字体的大小(小、普通、大、超大)。设置普通字体时,同数值dp和sp的文字看起来一样大;如果设置为大字体,用dp设置的文字没有变化,用sp设置的文字就变大了。
在XML布局文件中,为了让不同设备屏幕拥有统一的显示效果,除了sp用于设置文字大小外,其余要用尺寸大小的地方都用dp。在代码中情况又有所不同,Android用于设置大小的函数都以px为单位。无论是LayoutParams里的width和height,还是setMargins和setPadding,参数单位都是px,要想在代码中使用dp设置布局大小或间距,得先把dp值转换成px值。
颜色
在Android中,颜色值由透明度alpha和RGB(红、绿、蓝)三原色定义,有八位十六进制数与六位十六进制数两种编码,例如八位编码FFEEDDCC,FF表示透明度,EE表示红色的浓度,DD表示绿色的浓度,CC表示蓝色的浓度。透明度为FF表示完全不透明,为00表示完全透明。RGB三色的数值越大颜色越浓也就越亮,数值越小颜色越暗。亮到极致就是白色,暗到极致就是黑色,这样记就不会搞混了。
六位十六进制编码有两种情况,在XML文件中默认不透明(透明度为FF),在代码中默认透明(透明度为00)。
Android系统有12种已经定义好的颜色,具体的类型定义在Color类中
在布局文件中设置颜色需要在色值前面加“#”,如android:textColor=“#000000”。在代码中设置颜色可以直接填八位的十六进制数值(如setTextColor(0xff00ff00);),也可以通过Color.rgb(int red, int green, int blue)和Color.argb(int alpha, int red, int green, int blue)这两种方法指定颜色。在代码中一般不要用六位编码,因为六位编码在代码中默认透明,所以代码用六位编码跟不用没什么区别。
使用colors.xml中定义的颜色。res/values目录下有个colors.xml文件,是颜色常量的定义文件。如果要在布局文件中使用XML颜色常量,可引用“@color/常量名”;如果要在代码中使用XML颜色常量,可通过这行代码获取:getResources().getColor(R.color.常量名)。
从一个接入设备上获得屏幕分辨率信息
简单布局
视图View的基本属性
View是Android的基本视图,所有控件和布局都是由View类直接或间接派生而来的。
下面是视图在XML布局文件中常用的属性定义说明。
-
id:指定该视图的编号。
-
layout_width:指定该视图的宽度。可以是具体的dp数值;可以是match_parent,表示与上级视图一样宽;也可以是wrap_content,表示与内部内容一样宽(内部内容若超过上级视图的宽度,则该视图保持与上级视图一样宽,超出宽度的内容得进行滚动才能显示出来)。
-
layout_height:指定该视图的高度。取值说明同layout_width。
-
layout_weight:表示视图长度占据总空间的权重。
-
layout_margin:指定该视图与周围视图之间的空白距离(包括上、下、左、右)。另有layout_marginTop、layout_marginBottom、layout_marginLeft、layout_marginRight分别表示单独指定视图与上边、下边、左边、右边视图的距离。
-
minWidth:指定该视图的最小宽度。
-
minHeight:指定该视图的最小高度。
-
background:指定该视图的背景。背景可以是颜色,也可以是图片。
-
layout_gravity:指定该视图与上级视图的对齐方式。对齐方式的取值说明见表2-2,若同时适用多种对齐方式,则可使用竖线“|”把多种对齐方式拼接起来。
表2-2 对齐方式的取值说明
-
padding:指定该视图边缘与内部内容之间的空白距离。另有paddingTop、paddingBottom、paddingLeft、paddingRight分别表示指定视图边缘与内容上边、下边、左边、右边的距离。
-
visibility:指定该视图的可视类型。可视类型的取值说明见表2-3。
前面提到margin和padding两个概念,margin是指当前视图与周围视图的距离,padding是指当前视图与内部内容的距离。
视图组ViewGroup是一类特殊视图,所有的布局类视图都是从它派生而来的。Android中的视图分为两类,一类是布局,另一类是控件。布局与控件的区别在于:布局本质上是个容器,里面还可以放其他视图(包括子布局和子控件);控件是一个单一的实体,已经是最后一级,下面不能再挂其他视图。
ViewGroup有3个方法,这3个方法也是所有布局类视图共同拥有的。
- addView:往布局中添加一个视图。
- removeView:从布局中删除指定视图。
- emoveAllViews:删除该布局下的所有视图。
线性布局LinearLayout
LinearLayout是最常用的布局,名字叫线性布局。顾名思义,LinearLayout下面的子视图就像用一根线串了起来,所以LinearLayout内部视图的排列是有顺序的,要么从上到下依次垂直排列,要么从左到右依次水平排列。LinearLayout除了继承View/ViewGroup类的所有属性和方法外,还有其特有的XML属性,说明如下。
- orientation:指定线性布局的方向。horizontal表示水平布局,vertical表示垂直布局。如果不指定该属性,就默认是horizontal。这真是出乎意料,因为大家感觉手机App理应从上往下垂直布局,所以这里要特别注意垂直布局一定要设置orientation,不然默认的水平布局不符合多数业务场景。
- gravity:指定布局内部视图与本线性布局的对齐方式。取值说明同layout_gravity。
- layout_weight:指定当前视图的宽或高占上级线性布局的权重。这里要注意,layout_weight属性并非在当前LinearLayout节点中设置,而是在下级视图的节点中设置。另外,如果layout_weight指定的是当前视图在宽度上占的权重,layout_width就要同时设置为0dp;如果layout_weight指定的是当前视图在高度上占的权重,layout_height就要同时设置为0dp。
下面是LinearLayout在代码中增加的两个方法。
- setOrientation:设置线性布局的方向。LinearLayout.HORIZONTAL表示水平布局,LinearLayout.VERTICAL表示垂直布局。
- setGravity:设置布局内部视图与本线性布局的对齐方式。具体的取值说明见表2-2。
接下来重点解释layout_gravity和gravity的区别。前面说过,layout_gravity指定该视图在父视图内的对齐方式,而gravity指定本布局内部子控件或子布局的对齐方式。(layout_gravity是用来约束自己,gravity是用来约束其他。)
滚动视图ScrollView
手机屏幕的显示空间有限,常常需要上下滑动或左右滑动才能拉出其余页面内容,可惜Android的布局节点都不支持自行滚动,这时就要借助ScrollView滚动视图实现了。与线性布局类似,滚动视图也分为垂直方向和水平方向两类,其中垂直滚动的视图名是ScrollView,水平滚动的视图名是HorizontalScrollView。这两个滚动视图的使用并不复杂,主要注意以下3点:
(1)垂直方向滚动时,layout_width要设置为match_parent,layout_height要设置为wrap_content。
(2)水平方向滚动时,layout_width要设置为wrap_content,layout_height要设置为match_parent。
(3)滚动视图节点下面必须且只能挂着一个子布局节点,否则会在运行时报错Caused by: java.lang.IllegalStateException: ScrollView can host only one direct child。
简单控件
文本视图TextView
TextView是最基础的文本显示控件,常用的基本属性和设置方法见表2-4。
按钮Button
Button派生自TextView,二者在UI上的区别主要是Button控件有个按钮外观,提示用户点击这里。系统默认的按钮外观通常都不好看,需要更换靓一点、活泼一点的图片,这时在布局文件中修改Button节点的background属性就可以了。如果把background属性设置为@null,就会去除Button控件的背景样式,此时的Button看起来跟TextView没什么区别。
图像视图ImageView
- ImageView是图像显示控件,与图形显示有关的属性说明如下。
- scaleType:指定图形的拉伸类型,默认是fitCenter。拉伸类型的取值说明见表2-8。
- src:指定图形来源,src图形按照scaleType拉伸。注意背景图不按scaleType指定的方式拉伸,背景默认以fitXY方式拉伸。
ImageView在代码中调用的方法说明如下。
- setScaleType:设置图形的拉伸类型。具体的取值说明见表2-8。
- setImageDrawable:设置图形的Drawable对象。
- setImageResource:设置图形的资源ID。
- setImageBitmap:设置图形的位图对象。
图像按钮ImageButton
ImageButton其实派生自ImageView,而不是派生自Button,ImageView拥有的属性和方法,ImageButton统统拥有,只是ImageButton有个默认的按钮外观。
ImageButton和Button都起到控制按钮的作用,不同的是Button是文本按钮,ImageButton是图像按钮,这两个按钮的主要区别在于:
(1)Button既可显示文本也可显示图形(通过设置背景图),而ImageButton只能显示图形不能显示文本。
(2)ImageButton上的图像可按比例拉伸,而Button上的大图会拉伸变形(因为背景图无法按比例拉伸)。
(3)Button只能在背景显示一张图形,而ImageButton可分别在前景和背景显示两张图形,实现图片叠加的效果。
从上面可以看出,Button与ImageButton各有千秋,通常情况下使用Button就够用了。但在某些场合,比如输入法打不出来的字符和以特殊字体显示的字符串,就适合先切图再用ImageButton显示。
图形基础
Android把所有显示出来的图形都抽象为Drawable(可绘制的)。这里的图形不止是图片,还包括色块、画板、背景等。
- drawable文件放在res目录的各个drawable目录下。\res\drawable一般存放的是描述性的XML文件,图片文件一般放在具体分辨率的drawable目录下。例如:
- drawable-ldpi里面存放低分辨率的图片(如240×320),现在基本没有这样的智能手机了。
- drawable-mdpi里面存放中等分辨率的图片(如320×480),这样的智能手机已经很少了。
- drawable-hdpi里面存放高分辨率的图片(如480×800),一般对应4英寸~4.5英寸的手机(但不绝对,同尺寸的手机有可能分辨率不同,手机分辨率就高不就低,因为分辨率低了屏幕会有模糊的感觉)。
- drawable-xhdpi里面存放加高分辨率的图片(如720×1280),一般对应5英寸~5.5英寸的手机。
- drawable-xxhdpi里面存放超高分辨率的图片(如1080×1920),一般对应6英寸~6.5英寸的手机。
- drawable-xxxhdpi里面存放超超高分辨率的图片(如1440×2560),一般对应7英寸以上的平板电脑。
如果各目录存在同名图片,Android就会根据手机的分辨率分别适配对应文件夹里的图片。在开发App时,为了兼容不同的手机屏幕,根据需求在各目录存放不同分辨率的图片才能达到最合适的显示效果。
在XML布局文件中引用drawable文件可使用“@drawable/xxx”这种形式,如background属性、ImageView和ImageButton的src属性、TextView和Button的drawableTop系列属性都可以引用drawable文件。
在代码中引用drawable文件可分为两种情况:
(1)使用setBackgroundResource和setImageResource方法,可直接在参数中指定drawable文件的资源ID,例如“R.drawable.xxx”。
(2)使用setBackgroundDrawable、setImageDrawable和setCompoundDrawables等方法,参数是Drawable对象,这时得先从资源文件中生成Drawable对象
状态列表图形
一般drawable是静态图形,如Button按钮的背景在正常情况下是凸起的,在按下时是凹陷的,从按下到弹起的过程,用户便能知道点击了这个按钮。根据不同的触摸情况变更图形显示,这种情况会用到Drawable的一个子类StateListDrawable,该子类在XML文件中定义不同状态时呈现图形列表。要想在项目中创建状态图形的XML文件,则需右击drawable目录,然后在右键菜单中依次选择New→Drawable resource file,即可自动生成一个空的XML文件。
下面是一个状态列表图形的drawable文件:
该XML定义文件中的关键点是state_pressed,值为true表示按下时显示button_pressed图像,其余情况显示button_normal图像。
StateListDrawable不仅用于Button控件,而且可以用于其他拥有不同状态的控件,取决于开发者对StateListDrawable状态类型的定义。状态类型的取值说明见表2-9。
形状图形
前面讲到可在XML文件中描述状态列表图形的定义,还有一种常用的XML图形文件,是描述形状定义的图形—— shape图形。用好shape可以让App页面不再呆板,还可以节省美工不少工作量。
形状图形的定义文件以shape元素为根节点。根节点下定义了6个节点:corners(圆角)、gradient(渐变)、padding(间隔)、size(尺寸)、solid(填充)、stroke(描边),各节点的属性值主要是长宽、半径、角度以及颜色。下面是形状图形各个节点和属性的简要说明。
1. shape
shape是XML文件的根节点,用来描述该形状图形是哪种几何图形。下面是shape节点的常用属性说明。
- shape:字符串类型,图形的形状。形状类型的取值说明见表2-10。
2. corners
- corners是shape的下级节点,用来描述4个圆角的规格定义。若无corners节点,则表示没有圆角。下面是corners节点的常用属性说明。
- bottomLeftRadius:像素类型,左下圆角的半径。
- bottomRightRadius:像素类型,右下圆角的半径。
- topLeftRadius:像素类型,左上圆角的半径。
- topRightRadius:像素类型,右上圆角的半径。
- radius:像素类型,圆角半径(若有上面4个圆角半径的定义,则不需要radius定义)。
3. size
size是shape的下级节点,用来描述形状图形的尺寸大小(宽度和高度)。若无size节点,则表示宽高自适应。下面是size节点的常用属性说明。
- height:像素类型,图形高度。
- width:像素类型,图形宽度。
4. solid
solid是shape的下级节点,用来描述形状图形内部的填充色彩。若无solid节点,则表示无填充颜色。下面是solid节点的常用属性说明。
- color:颜色类型,内部填充的颜色。
5. stroke
stroke是shape的下级节点,用来描述形状图形四周边线的规格定义。若无stroke节点,则表示不存在描边。下面是stroke节点的常用属性说明。
- color:颜色类型,描边的颜色。
- dashGap:像素类型,每段虚线之间的间隔。
- dashWidth:像素类型,每段虚线的宽度。
- width:像素类型,描边的厚度。若dashGap和dashWidth有一个值为0,则描边为实线。
在实际开发中,常用的有3个节点:corners(圆角)、solid(填充)和stroke(描边)。shape根节点的属性一般不用设置(默认矩形就好了)。
九宫格图片(.9图片)
前面在介绍ImageView时专门举了例子说明不同拉伸类型下的图片显示效果。当图片被拉大时,画面容易模糊,如果把图片作为背景图,模糊的情况会更严重。如图2-24所示,一张按钮图片被拉得很宽,此时左右两边的边缘线既变宽又变模糊了。
为了解决这个问题,Android专门设计了点九图片。点九图片的扩展名是png,文件名后常带有“.9”字样。因为把一张图片划分成了3×3的九宫格区域,所以得名点九图片,也叫九宫格图片。如果背景是一个shape图形,其stroke节点的width属性已经设置了具体的像素值(如1dp),那么无论该shape图形被拉伸到多大,描边宽度始终都是1dp。点九图片的实现原理与shape类似,即拉伸图形时,只对内部进行拉伸,不对边缘做拉伸操作。
background会根据ImageView组件给定的长宽进行拉伸,故多采用.9图片作为背景图片。而src就存放的是原图的大小,不会进行拉伸。src是图片内容(前景),bg是背景,可以同时使用。
小知识:日志Log/提示Toast
在正式编码之前,读者有必要了解一下Android中的运行信息调试手段。例如,开发C程序时,程序员常用printf函数输出程序日志;开发Java程序时,程序员常用System.out.println函数输出程序日志。同样,App开发也有相应的函数输出提示信息。提示信息可分为两类,一类是给开发者看的,另一类是给用户看的。
Log
给开发者看的提示信息要调用Log类的相应方法,日志打印结果可在Android Studio界面下方的logcat小窗口查看。Log类各种方法的区别在于日志的等级,具体说明如下。
- Log.e:表示错误信息,比如可能导致程序崩溃的异常。
- Log.w:表示警告信息。
- Log.i:表示一般消息。
- Log.d:表示调试信息,可把程序运行时的变量值打印出来,方便跟踪调试。
- Log.v:表示冗余信息。
Toast
给用户看的提示信息要调用Toast类的相应方法,提示文字会在屏幕下方以一个小窗口临时展现。对于计算器来说,有好几种情况需要提示用户,如“被除数不能为0”“开根号的数值不能小于0”等。Toast的简单用法只需一行代码就可以了,示例代码如下:
Toast弹窗的展示效果如图2-34所示,此时App发现了被除数为零的情况。
另外,计算器每个按钮的展示风格基本相同,为了减少冗余代码,可将相同的样式定义写在values目录下的styles.xml文件中,然后在布局文件节点下增加style="@style/btn_cal"这样的属性定义。