文本
文本
屏幕显示像素单位
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设置的文字就变大了。例如,当系统设置普通字体时,18dp与18sp的文字一样大;当系统设置大字体时,18dp的文字大小不变,18sp的文字却增大了。
即是dp与系统设置的字体大小没有关系,而sp会随系统设置的字体大小变大或变小。
dp与px的转换
dp和px之间的联系取决于具体设备上的像素密度,像素密度就是DisplayMetrics里的density参数。当density=1.0时,表示一个dp值对应一个px值;当density=1.5时,表示两个dp值对应3个px值;当density=2.0时,表示一个dp值对应两个px值。
转换代码如下:
// 根据手机的分辨率从dp的单位转换成px像素
public static int dp2px(Context context,float dpValue){
// 获取当前手机的像素密度
final float scale = context.getResources().getDisplayMetrics().density;
return (int)(dpValue*scale+0.5f);// 四舍五入取整
}
//根据手机的分辨率从px像素单位转换成dp单位
public static int px2dp(Context context,float pxValue){
// 获取当前手机的像素密度
final float scale = context.getResources().getDisplayMetrics().density;
return (int)(pxValue/scale+0.5f);// 四舍五入取整
}
值得注意的是:在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)
屏幕分辨率
在App编码中时常要取手机的屏幕分辨率(如当前屏幕的宽和高),然后动态调整界面上的布局。在代码中获取分辨率就是想办法获得DisplayMetrics对象,然后从该对象中获得宽度、高度、像素密度等信息。
下面是DisplayMetrics类的常用属性说明:
- widthPixels:以px为单位计量的宽度值。
- heightPixels:以px为单位计量的高度值。
- density:像素密度,即一个dp单位包含多少个px单位。
取当前屏幕的宽度、高度、像素密度的代码示例:
public static int getScreenWidth(Context context){
// 从系统服务中获取窗口管理器
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics displayMetrics = new DisplayMetrics();
// 从默认显示器中获取显示参数保存到dm对象中
wm.getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics.widthPixels;
}
public static int getScreenHeight(Context context){
// 从系统服务中获取窗口管理器
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics displayMetrics = new DisplayMetrics();
// 从默认显示器中获取显示参数保存到dm对象中
wm.getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics.heightPixels;
}
public static float getScreenDensity(Context context){
// 从系统服务中获取窗口管理器
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics displayMetrics = new DisplayMetrics();
// 从默认显示器中获取显示参数保存到dm对象中
wm.getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics.density;
}
视图View的基本属性
view
View是Android的基本视图,所有控件和布局都是由View类直接或间接派生而来的。故而View类的基本属性和方法是各控件和布局通用的。
这是XML中的属性值定义:
id:指定该视图的编号。
layout_width:指定该视图的宽度。可以是具体的dp数值;可以是match_parent,表示与上级视图一样宽;也可以是wrap_content,表示与内部内容一样宽(内部内容若超过上级视图的宽度,则该视图保持与上级视图一样宽,超出宽度的内容得进行滚动才能显示出来)。
layout_height:指定该视图的高度。取值说明同layout_width。
layout_margin:指定该视图与周围视图之间的空白距离(包括上、下、左、右)。另有layout_marginTop、layout_marginBottom、layout_marginLeft、layout_marginRight分别表示单独指定视图与上边、下边、左边、右边视图的距离。
minWidth:指定该视图的最小宽度。
minHeight:指定该视图的最小高度。
background:指定该视图的背景。背景可以是颜色,也可以是图片。
layout_gravity:指定该视图与上级视图的对齐方式。对齐方式的取值说明可以参考下面的表格,若同时适用多种对齐方式,则可使用竖线“|”把多种对齐方式拼接起来。
padding:指定该视图边缘与内部内容之间的空白距离。另有paddingTop、paddingBottom、paddingLeft、paddingRight分别表示指定视图边缘与内容上边、下边、左边、右边的距离。
visibility:指定该视图的可视类型。
当然也可以通过代码设定:
setLayoutParams:设置该视图的布局参数。参数对象的构造函数可以设置视图的宽度和高度。其中,LayoutParams.MATCH_PARENT表示与上级视图一样宽,也可以是LayoutParams.WRAP_CONTENT,表示与内部内容一样宽;参数对象的setMargins方法可以设置该视图与周围视图之间的空白距离。
setMinimu mWidth:设置该视图的最小宽度。
setMinimumHeight:设置该视图的最小高度。
setBackgroundColor:设置该视图的背景颜色。
setBackgroundDrawable:设置该视图的背景图片。
setBackgroundResource:设置该视图的背景资源id。
setPadding:设置该视图边缘与内部内容之间的空白距离。
setVisibility:设置该视图的可视类型。
XML中的对齐方式 | Gravity类中的对齐方式 | 说明 |
---|---|---|
left | LEFT | 靠左对齐 |
right | RIGHT | 靠右对齐 |
top | TOP | 向上对齐 |
bottom | BOTTOM | 向下对齐 |
center | CENTER | 居中对齐 |
center_horizontal | CENTER_HORIZONTAL | 水平方向居中 |
center_vertical | CENTER_VERTICAL | 垂直方向居中 |
--- | --- | ---- |
XML中可视的类型 | Gravity类中的可视类型 | 说明 |
visible | VISIBLE | 可见,默认值 |
invisible | INVISIBLE | 不可见,虽然看不见但还是会占据位置 |
gone | GONE | 消失,看不见也不会占据位置 |
- margin是指当前视图与周围视图的距离,padding是指当前视图与内部内容的距离
ViewGroup
视图组ViewGroup是一类特殊视图,所有的布局类视图都是从它派生而来的。Android中的视图分为两类,一类是布局,另一类是控件。布局与控件的区别在于:布局本质上是个容器,里面还可以放其他视图(包括子布局和子控件);控件是一个单一的实体,已经是最后一级,下面不能再挂其他视图。
ViewGroup有3个方法,这3个方法也是所有布局类视图共同拥有的:
addView:往布局中添加一个视图。
removeView:从布局中删除指定视图。
removeAllViews:删除该布局下的所有视图。
TextView
TextView是最基础的文本显示控件
XML中的属性 | TextView类的设置方法 | 说明 |
---|---|---|
text | setText | 设置文本内容 |
textColor | setTextColor | 设置文本颜色 |
textSize | setTextSize | 设置文本大小 |
textAppearance | setTextAppearance | 设置文本风格,风格定义在res/styles.xml |
gravity | setGravity | 设置文本的对齐方式 |
lins | setLines | 指定文本行数 |
maxLines | setMaxLines | 指定文本的最大行数 |
跑马灯&文字滚动效果
实现这个效果需要定义一些其他的属性值,如下:
XML中的属性 | TextView类的设置方法 | 说明 |
---|---|---|
singleline | setSingleLine | 指定文本是否单行显示 |
ellipsize | setEllipsize | 指定文本超出范围后的省略方式 |
focusable | setFocusable | 指定是否获得焦点,跑马灯效果需要设置为true |
focusableintouchmode | setFocusableInTouchMode | 指定在触摸时是否获得焦点,跑马灯效果需要设置为true |
无 | setMovementMethod | 设置文本移动的方式,可以设置为ScrollingMovementMethod,如果不设置将无法拉动文本 |
scrollbars | 无 | 指定滚动条的方向,取值vertical,如果不指定将不显示滚动条 |
- | - | - |
XML中的省略方式 | TruncateAt类中省略方式 | 说明 |
start | START | 省略号在前面 |
middle | MIDDLE | 省略号在中间 |
end | END | 省略号在末尾 |
marquee | MARQUEE | 跑马灯显示 |
- tip: 视频弹幕、直播弹幕效果实现,将背景设置为透明,字体颜色设置为白色或其他颜色,开启跑马灯效果,让文字从左到右滚动,半屏或全屏可以通过改变View的高度,或者最大显示的行数控制.
EditText
EditText是文本编辑框,用户可在此输入文本等信息。EditText的常用属性说明如下。
inputType:指定输入的文本类型,代码中对应的方法是setInputType。输入类型的取值说明可以见下表,若同时使用多种文本类型,则可使用竖线“|”把多种文本类型拼接起来。
maxLength:指定文本允许输入的最大长度。该属性无法通过代码设置。
hint:指定提示文本的内容,代码中对应的方法是setHint。
textColorHint:指定提示文本的颜色,代码中对应的方法是setHintTextColor。
输入类型 | 说明 |
---|---|
text | 文本 |
textPassword | 文本密码,显示时用 * 符号代替 |
number | 整型数 |
numberSigned | 带符号的数字,允许在开头带负号 |
numberDecimal | 带小数点的数字 |
numberPassword | 数字密码,显示时用 * 符号代替 |
datetime | 时间日期格式,除了数字以外,还允许输入横线、斜杠、空格、冒号 |
date | 日期格式,除了数字外,还允许输入横线 - 和斜杠 / |
time | 时间格式,除了数字外,还允许输入冒号 : |
除了上述文本与提示文本的基本操作外,实际开发中还常常关注4个方面:更换编辑框的光标、更换编辑框的边框、自动隐藏输入法、输入回车符自动跳转。
更换编辑框的光标
EditText与光标处理有关的属性主要有两个,分别是:cursorVisible,指定光标是否可见。代码中对应的方法是setCursorVisible。textCursorDrawable,指定光标的图像。该属性无法通过代码设置。如果要隐藏光标,就要把cursorVisible设置为false。如果要变更光标的样式,就要修改textCursorDrawable设置新图像。如图3-13所示,光标被换成自定义的红色竖线光标。
更换编辑框的边框
EditText的边框通过background属性控制,如果要隐藏边框,就要把background设置为@null;如果要修改边框的样式,就要将background设置为其他边框图形。
自动隐藏输入法
如果页面上有EditText控件,开发者又没做其他处理,那么用户打开该页面时往往会自动弹出输入法。这是因为编辑框会默认获得焦点,即默认模拟用户的点击操作,于是输入法的软键盘就弹出了。要想避免这种情况,就得阻止编辑框默认获得焦点。比较常见的做法是给该页面的根节点设置focusable和focusableInTouchMode属性,通过将这两个属性设置为true可强制让根节点获得焦点,从而避免输入法自动弹出的尴尬。由于软键盘通常会遮盖“登录”“确认”“下一步”等按钮,造成用户输入完毕得再点一次返回键才能关闭软键盘。大家都希望省事点,比如手机号输入满11位软键盘自动关闭,这样就会极大改善用户体验。
一个好用的App就是在这一点一滴中体现出来的。
想让编辑框文本达到指定长度时自动关闭输入法,开发者需要获得两个参数,第一个是该编辑框允许输入的最大长度,第二个是当前已经输入的文本长度。当已输入的文本长度等于最大长度时,即可触发关闭软键盘。自动隐藏输入法可分解为3个功能点,分别是获取编辑框的最大长度、监控当前已输入的文本长度和关闭软键盘。
(1)获取编辑框的最大长度前面提到maxLength属性可设置最大长度,但是EditText并没有直接提供获取最大长度的方法,不过开发者可以通过反射方式间接获得最大长度,具体代码参见本书附带源码middle模块里面ViewUtil.java的getMaxLength方法。
(2)监控当前已输入的文本长度这个监控操作用到一个文本监听器接口TextWatcher,该接口提供了3个监控方法,具体说明如下。
beforeTextChanged:在文本改变之前触发。
onTextChanged:在文本改变过程中触发。
afterTextChanged:在文本改变之后触发。这里用到的是afterTextChanged方法,需要自己写个监听器实现TextWatcher接口,另外再给EditText对象调用addTextChangedListener方法注册该监听器。
(3)关闭软键盘输入法通过系统服务INPUT_METHOD_SERVICE管理,所以隐藏输入法也要通过该服务实现。下面是关闭软键盘的两种方式及其代码:
public static void hideAllInputMethod(Activity activity) {
// 从系统服务中获取输入法管理器
InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
if (inputMethodManager.isActive()) {
// 软键盘如果打开则关闭
inputMethodManager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
}
}
public static void hideOneInputMethod(Activity activity, View view){
// 从系统服务中获取输入法管理器
InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
// 关闭屏幕上的输入法软键盘
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(),0);
}
示例:
private class HideTextWatcher implements TextWatcher {
private EditText mView; // 声明一个编辑框对象
private int mMaxLength; // 声明一个最大长度变量
public HideTextWatcher(EditText v, int maxLength) {
super();
mView = v;
mMaxLength = maxLength;
}
// 在编辑框的输入文本变化前触发
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
// 在编辑框的输入文本变化时触发
public void onTextChanged(CharSequence s, int start, int before, int count) {}
// 在编辑框的输入文本变化后触发
public void afterTextChanged(Editable s) {
String str = s.toString(); // 获得已输入的文本字符串
// 输入文本达到11位(如手机号码),或者达到6位(如登录密码)时关闭输入法
if ((str.length() == 11 && mMaxLength == 11)
|| (str.length() == 6 && mMaxLength == 6)) {
ViewUtil.hideOneInputMethod(EditHideActivity.this, mView); // 隐藏输入法软键盘
}
}
}
输入回车符自动跳转
在录入用户信息时(比如输入姓名、密码等),往EditText控件输入回车键,常常不是换行而是让光标直接跳到下一个编辑框。 该功能也用到了文本监听器接口TextWatcher,主要监听用户是否输入回车符,如果监控到已输入回车符,就自动将焦点移到下一个控件,从而实现回车符自动跳转的要求。
下面是一个回车符监听器的代码例子,注意注释部分的文字说明:
public final class JumpTextWatcher implements TextWatcher {
private final EditText thisView;
private final View nextView;
public JumpTextWatcher(EditText thisView, View nextView) {
this.thisView = thisView;
this.nextView = nextView;
}
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void afterTextChanged(Editable editable) {
String s = editable.toString();
// 判断是否是回车符或者换行符
if(s.contains("\r")||s.contains("\n")){
//去掉回车符和换行符
thisView.setText(s.replace("\r","").replace("\n",""));
if(nextView!=null){
nextView.requestFocus();
if(nextView instanceof EditText){
Editable editable1 = ((EditText) nextView).getText();
Selection.setSelection(editable1,editable1.length());
//((EditText) nextView).setSelection(editable1.length());
}
}
}
}
}
自动完成编辑框AutoCompleteTextView
自动完成编辑框一般用于搜索文本框,如在电商App的搜索框输入商品文字时,下方会自动弹出提示词列表,方便用户快速选择具体商品。
AutoCompleteTextView的实现原理是:EditText结合监听器TextWatcher与下拉列表Spinner,一旦监控到EditText的文本发生变化,就自动弹出适配好的文字下拉列表,选中具体的下拉项向EditText填入相应文字。
xml属性值 | 代码设置 | 说明 |
---|---|---|
completionHint | setCompletionHint | 设置下拉列表底部的提示文字 |
completionThreshold | setThreshold | 设置至少输入多少个字符才会显示 |
dropDownHorizontalOffset | setDropDownHorizontalOffset | 设置下拉列表与文本框之间的水平偏移 |
dropDownVerticalOffset | setDropDownVerticalOffset | 设置下拉列表与文本框之间的垂直偏移 |
dropDownHeight | setDropDownHeight | 设置下拉列表的高度 |
dropDownWidth | setDropDownWidth | 设置下拉列表的宽度 |
无 | setAdapter | 设置数据适配器 |
String [] hintArray = {"第一个","第二个"};
AutoCompleteTextView completeTextView = new AutoCompleteTextView(this);
completeTextView.setAdapter(new ArrayAdapter<String>(this,R.layout.布局文件,hintArray));
Button
Button派生自TextView,二者在UI上的区别主要是Button控件有个按钮外观,提示用户点击这里。 系统默认的按钮外观通常都不好看,需要更换靓一点、活泼一点的图片,这时在布局文件中修改Button节点的background属性就可以了。
如果把background属性设置为@null,就会去除Button控件的背景样式,此时的Button看起来跟TextView没什么区别。
因为点击和长按监听器都来源于View类,所以这两个方法及其监听器并非Button特有的,而是所有布局和控件都能使用的,一般用于为按钮控件注册点击和长按事件。Android中的简单按钮主要是Button和ImageButton。这两个按钮对点击和长按监听器的使用方法并不复杂,主要步骤如下:
步骤01
自己定义一个扩展自监听器的类,如点击监听器扩展自View.OnClickListener,长按监听器扩展自View.OnLongClickListener。为了方便起见,也可以直接给页面的Activity类加上监听器接口。
步骤02
在自定义监听器类中重写点击或者长按方法,加入事件处理的代码。点击方法的名称是onClick,长按方法的名称是onLongClick。
步骤03
哪个视图要响应点击或长按,就给哪个视图注册对应的监听器对象。点击事件的注册方法是setOnClickListener,长按事件的注册方法是setOnLongClickListener。
示例:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
button.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
return false;
}
});