Android基础篇(一)屏幕,文本,图形,控件

关于显示单位

白话解释:
所谓的屏幕大小 是指屏幕对角线长度,单位英寸,如:5英寸
屏幕的宽/高(px像素)
dpi Dots Per Inch(每英寸所打印的点数),也就是当设备的dpi为160的时候1px=1dp;
ppi 每英寸的像素数(也被称为图像的采样率)。

关于颜色

Android中颜色值的定义是由透明度alpha和RGB(红绿蓝)三原色来定义的,有八位(依次为透明度红黄蓝)十六进制数与六位十六进制数两种编码,透明度为FF时表示完全不透明,为00时表示完全透明。

Android系统有十二种已经定义好的颜色,分别是Color类下面的BLACK(黑色)、DKGRAY(深灰)、GRAY(灰色)、LTGRAY(浅灰)、WHITE(白色)、RED(红色)、GREEN(绿色)、BLUE(蓝色)、YELLOW(黄色)、CYAN(青色)、MAGENTA(玫瑰红)、TRANSPARENT(透明)。

在布局文件中设置颜色,需要在色值前面加“#”,如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中设置的颜色,可按如下方式获取 setTextColor(getResources().getColor(R.color.black));

关于屏幕

通过windowsManager 获取, DisplayMetrics 类中封装了系统帮你计算的app 分辨率尺寸,当作屏幕大小,还有很多其他方法,针对具体情况具体使用,如图 7.png
Android基础篇(一)屏幕,文本,图形,控件_第1张图片

public static void getSize(Context ctx) {  
    WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);  
    DisplayMetrics dm = new DisplayMetrics();  
    wm.getDefaultDisplay().getMetrics(dm);  
    宽 = dm.widthPixels;  
    高 = dm.heightPixels;  
    屏幕密度 = dm.density;  
}  

网上的屏幕尺寸对照表
Android基础篇(一)屏幕,文本,图形,控件_第2张图片

Android基础篇(一)屏幕,文本,图形,控件_第3张图片

Android基础篇(一)屏幕,文本,图形,控件_第4张图片

数据来自友盟2017

关于屏幕适配

曾经有一种适配方式是这样的
将屏幕的宽高按照一定比例等分其分辨率宽高,比如,可以通过系统类DisplayMetrics 获取到宽高像素长度,然后按照 320*480的宽高分等分,即宽分320份,高分480份
具体实现见博客http://blog.csdn.net/zhaokaiqiang1992/article/details/45419023# 文章太长可以通过Ctrl + F 搜索文字“Day Day Up ”
然后,利用dimens 文件夹使用计算后的每份px像素值一一对每一个项目中使用到的表示长度的单位进行转换,如下图:
Android基础篇(一)屏幕,文本,图形,控件_第5张图片
但是这种方式有天然缺点:
1.有些细节是粗略匹配的,即,有可能1像素的位置分配了1.2像素,虽然误差小,但是还是有,这不是谷歌推荐的方式;
2.需要创建N多dimens 以应对不同 分辨率及屏幕尺寸;

技巧终归是技巧,还是来看看谷歌官方的描述吧https://developer.android.google.cn/guide/practices/screens_support.html
屏幕尺寸:
Android 将所有实际屏幕尺寸分组为四种通用尺寸:小(屏幕至少为 426dp x 320dp)、 正常(屏幕至少为 470dp x 320dp)、大(屏幕至少为 640dp x 480dp)和超大(屏幕至少为 960dp x 720dp)。
屏幕密度:
Android 将所有屏幕密度分组为六种通用密度: ldpi(低)~120dpi、mdpi(中)~160dpi、hdpi(高)~240dpi、xhdpi(超高)~320dpi、xxhdpi(超超高)~480dpi和xxxhdpi(超超超高)~640dpi。
分辨率:(略,因为程序中不直接使用这个)
密度无关像素 (dp)
开发时候使用dp 让系统自己适配,在不同的屏幕密度文件夹中放入不同的图片,因为l的已经很少了,所以只需要考虑四个文件目录 mdpi,hdpi,xhdpi,xxhdpi,xxxhdpi

目前的适配做法:详情见官方文档:https://developer.android.google.cn/guide/practices/screens_support.html,以上所有用到的参数均已该文中提到为准
分辨率导致不能直接使用像素,屏幕大小导致使用dp的时候也要小心考虑屏幕大小的影响;
对布局尺寸使用 wrap_content、match_parent 或 dp 单位,用sp来设置文字大小
为不同屏幕密度,即mipmap-(N)dpi这个目录下分配不同资源交给系统来处理
多用一些线性布局的等比例,相对布局的相对位置,以及最新的约束布局;
多用扁平式的布局风格,简约好适配,不得已的时候尽量依赖相对位置;
屏幕适配时候的代表性适配方案,如图:
Android基础篇(一)屏幕,文本,图形,控件_第6张图片

关于日期

string ,date,Calendar 找源码API
tips:
1、GMT(格林尼治标准时间)1970 年,1 月 1 日 00:00:00 这一刻开始的毫秒数。
2、java.util.Date 从 JDK 1.1 开始,应该使用 Calendar 类实现日期和时间字段之间转换,使用 DateFormat 类来格式化和分析日期字符串。Date 中的把日期解释为年、月、日、小时、分钟和秒值的方法已废弃。
3、java.util.Calendar 提供诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日历字段及一些转换方法,或者相对于GMT的毫秒数
4、日期上的计算注意与中国日期的差,月日上会差一天

关于版本对照

Android基础篇(一)屏幕,文本,图形,控件_第7张图片

关于图形

Drawable android.graphics.drawable目录下
Android把所有显示出来的图形都抽象为Drawable(该单词意思就是“可绘制的”),这里的图形不只是图片,还包括色块、画板、背景等等。

Drawable资源目录
drawable文件放在res目录的各个drawable目录下,\res\drawable一般放的是描述性的xml文件,图片文件一般放在具体分辨率的drawable目录下。例如
drawable-ldpi里面主要放低分辨率的图片,如QVGA(240×320)
drawable-mdpi里面主要放中等分辨率的图片,如HVGA(320×480)
drawable-hdpi里面主要放高分辨率的图片,如WVGA(480×800),FWVGA(480×854)
drawable-xhdpi里面主要放加高分辨率的图片,如Nexus(720×1280)以上分辨率
drawable-xxhdpi里面主要放超高分辨率的图片,如Nexus(1080×1920)以上分辨率
Android会根据手机的分辨率来分别适配对应文件夹里的图片。如果图片只存在某一个文件中,其他分辨率的手机运行时会对其拉伸,出现模糊情况

selector选择器
由于drawable放的都是静态图片,在做一些按钮点击状态变更类似操作的时候会用到选择器,通过手写xml文件实现
下面是一个例子btn_selector.xml

  
<selector  
  xmlns:android="http://schemas.android.com/apk/res/android">  
    <item android:state_pressed="true" android:drawable="@drawable/common_selected" />  
    <item android:drawable="@drawable/common_normal" />  
selector>  

该xml中关键点是state_pressed,该值为true表示按下时显示common_selected图像,其余情况显示common_normal图像。
常用的状态位有:
state_pressed:为true时表示按下,一般用于按钮Button,图形设置于android:background
state_checked:为true时表示勾选,一般用于单选框RadioButton、复选框CheckBox,图形设置于android:drawableLeft
state_selected:为true时表示选中,一般用于单选框RadioButton、复选框CheckBox,图形设置于android:background
state_focused:为true时表示获取焦点,一般用于文本框EditText,图形设置于android:background
具体源码见 android.graphics.drawable.StateListDrawable

接下来是:shape
也是xml,以shape元素为根节点。根节点下定义了六个节点:corners(圆角)、gradien(渐变)、padding(间隔)、size(尺寸)、solid(填充)、stroke(描边),各节点的属性值主要是各种长宽、半径、角度,以及颜色。

 shape(根节点)
android:shape: 字符串类型,图形的形状。为rectangle表示矩形(默认),为oval表示椭圆(此时corners节点将失效),为line表示直线(此时必须设置stroke节点,不然会报错),为ring表示圆环。
下面的属性只有在android:shape=”ring”时可用:
android:innerRadius: 像素类型,内圆的半径。
android:innerRadiusRatio: 浮点型,以环的宽度比率来表示内圆的半径。例如,如果android:innerRadiusRatio=”3”,表示内圆半径等于环的宽度(即外圆直径)除以3。如已设置android:innerRadius则不需设置本属性
android:thickness: 像素类型,环的厚度
android:thicknessRatio: 浮点型,以环的宽度比率来表示环的厚度。例如,如果android:thicknessRatio=”2”,那么环的厚度就等于环的宽度除以2。如已设置android:thickness则不需设置本属性
android:useLevel: 布尔类型,如果当做是LevelListDrawable使用时值为true,否则为false(一般情况必须设置为false,不然ring无法显示)。

  corners(圆角)
android:bottomLeftRadius: 像素类型,左下圆角的半径
android:bottomRightRadius: 像素类型,右下圆角的半径
android:topLeftRadius: 像素类型,左上圆角的半径
android:topRightRadius: 像素类型,右上圆角的半径
android:radius: 像素类型,圆角半径(若有上面四个圆角半径的定义,则不需要radius定义)
  无corners节点表示没有圆角

  gradien(渐变)
android:angle: 整型,渐变的起始角度。0值时表示时钟的九点位置,其值增大表示往逆时针方向旋转。例如值为90表示时钟六点位置,值为180表示时钟三点位置,值为270表示时钟零点/十二点位置
android:centerX: 浮点型,圆心的X坐标。当android:type=”linear”时不可用
android:centerY: 浮点型,圆心的Y坐标。当android:type=”linear”时不可用
android:gradientRadius: 整型,渐变的半径。当android:type=”radial”时才需要设置该属性

android:centerColor: 颜色类型,渐变的中间颜色
android:startColor: 颜色类型,渐变的起始颜色
android:endColor: 颜色类型,渐变的终止颜色
android:type: 字符串类型,渐变类型。为linear表示线性渐变(默认值),为radial表示放射渐变(起始颜色就是圆心颜色),为sweep表示滚动渐变(即一个线段以某个端点为圆心做360度旋转)
android:useLevel: 布尔类型,设置为true无渐变,false有渐变色。如果要使用LevelListDrawable对象,就要设置为true
  无gradien节点表示没有渐变效果

  padding(间隔)
android:bottom: 像素类型,与下边的间隔
android:left: 像素类型,与左边的间隔
android:right: 像素类型,与右边的间隔
android:top: 像素类型,与上边的间隔
  无padding节点表示四周不设间隔

  size(尺寸)
android:height: 像素类型,图形高度
android:width: 像素类型,图形宽度
  无size节点表示长宽自适应

  solid(填充)
android:color: 颜色类型,内部填充的颜色
  无solid节点表示无填充颜色

  stroke(描边)
android:color: 颜色类型,描边的颜色
android:dashGap: 像素类型,每段虚线之间的间隔
android:dashWidth: 像素类型,每段虚线的宽度
android:width: 像素类型,描边的宽度(厚度)。当dashGap和dashWidth有一个值为0,则描边为实线
  无stroke节点表示描边不存在

实际运用中,常用的就是三个节点:corners(圆角)、solid(填充)、stroke(描边)。shape自身的属性一般不用设置(默认矩形就好了)。
这种东西就得常用,不然就得现用现查,真记不住,具体源码见 android.graphics.drawable.ShapeDrawable

.9图制作
左上代表拉伸,右下代表填充;想象一下空间画面;
1,左边框、上边框一定要有描点或描点段(垂直方向及水平方向 拉伸区域);
2,左边框、上边框的描点或描点段 可以有多个 ;
3,右边框、下边框可以不需要有描点或描点段(可以不设置内容填充区域)
4,右边框、下边框如果设置了描点或描点段,只能有一个。
当然,使用android studio 工具就会很方便,图片右键既有制作9图选项,右边还会有对照显示,然后选择保存路径即可。

图片处理相关工具
【颜色拾取器下载】
加工如缩放、旋转、裁剪、格式转换,gif动画取帧,使用ACDSee 或者PhotoShop。
Android本身不支持gif动画的显示,如果用ImageView加载一张gif图片,结果只能显示gif的第一帧图。当然我们可以重写ImageView使之支持显示gif动画,也可以使用帧动画FrameAnimation,使用帧动画需要从gif中提取每帧的图片。

关于控件
布局视图有五类,分别是
线性布局LinearLayout(常用)、水平或者垂直
相对布局RelativeLayout(常用)、控件之间互相依存的关系
框架布局FrameLayout(不常用)、层叠
绝对布局AbsoluteLayout(不用)、没用过
表格布局TableLayout(很少)。没用过
还有一类需要导入插件
com.android.support.constraint:constraint-layout:1.0.2
Android基础篇(一)屏幕,文本,图形,控件_第8张图片
但是也是google IO 2016 中发布的叫约束布局constrainLayout ,相对布局升级版,更优雅,【TODO 后面文章详细描述】

View/ViewGroup(源码很长,相信你也不想读,用就好了少年)
View是单个视图,所有的控件类都是从它派生出来;而ViewGroup是个视图组织,继承自View 。由于View和ViewGroup是基类,因此很少会直接使用,偶尔用到的场景,主要有如下几个:
1、页面上需要单独显示一条横线或者竖线。如果填充图片显然不够经济,最简单的做法,就是在xml布局中增加一个View控件,高度或宽度设置为1dp,背景颜色设置为线条颜色,这样便实现了单独显示线条的需求。
2、点击事件的处理函数onClick(View v),这里面我们要调用View的getId方法获取发生点击事件的控件id,从而进行该控件对应的点击处理。
3、在代码中设置某控件为可见或不可见或消失,此时需要使用View类的三个变量,分别是View.VISIBLE、View.INVISIBLE和View.GONE。
4、特殊的自定义View。此时需要重写ondraw 绘制,onmesure 计算大小传给父类比较等等,【TODO 后面文章详细描述】

TextView文本显示
gravity : 指定文本的对齐方式,一般取值“left|bottom”,表示靠左对齐且靠下对齐。
lines : 指定文本的行数。
maxLines : 指定文本的最大行数。
scrollbars : 指定滚动条的方向,一般取值vertical,如不指定将不显示滚动条。注意该属性只能在xml中设置。
在代码中实现时,可调用如下方法:
setGravity : 设置文本的对齐方式。
setLines : 设置文本的行数。
setMaxLines : 设置文本的最大行数。
setMovementMethod : 设置文本移动的方式,一般取值“new ScrollingMovementMethod()”,如不设置将无法拉动文本。注意该方法只能在代码中调用。
需要注意的是,scrollbars只能在xml中设置,而无法通过代码设置。反过来,setMovementMethod只能在代码中设置,而无法通过xml设置。
drawableTop : 指定文本上方的图形。
drawableBottom : 指定文本下方的图形。
drawableLeft : 指定文本左边的图形。
drawableRight : 指定文本右边的图形。
drawablePadding : 指定图形与文本的间距。
在代码中实现时,可调用如下方法:
setCompoundDrawables : 设置文本周围的图形。该方法有四个参数,分别表示左边、上方、右边、下方的图形。
setCompoundDrawablePadding : 设置图形与文本的间距。
对该控件(或视图)截图。需要先设置绘图缓存可用,然后取出该控件的绘图缓存完成截图操作。
该操作必须通过代码完成,相关方法如下:
setDrawingCacheEnabled : 设置绘图缓存的可用状态。true表示打开,false表示关闭。
isDrawingCacheEnabled : 判断该控件的绘图缓存是否可用。
setDrawingCacheQuality : 设置绘图缓存的质量。
getDrawingCache : 获取该控件的绘图缓存结果,返回值为Bitmap类型
setDrawingCacheBackgroundColor : 设置绘图缓存的背景颜色。可能大家很奇怪为何还要该方法,其实是因为绘图缓存默认背景色是黑色,如果不提前设置缓存的背景色的话,截图的结果就是黑乎乎一片,所以需要将背景色设置为默认颜色(通常是白色)。
其实截图操作适用于大多数控件和视图,因为这几个方法来自于View类,所以凡是继承自View的控件和视图都是可以截图的。

EditText 文本输入框
inputType : 指定输入的文本类型。常用的取值说明包括:text表示普通文本,textPassword表示文本密码,textEmailAddress表示邮件地址,number表示数字,numberPassword表示数字密码,phone表示电话和手机号码。
maxLength : 指定文本允许输入的最大长度。该属性无法通过代码设置。
hint : 指定提示文本。
textColorHint : 指定提示文本的颜色。
在代码中设置:
setInputType : 设置输入的文本类型。如果要隐藏密码注意要设置“InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_VARIATION_PASSWORD”,如果要显示密码则设置“InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD”。
setHint : 设置提示文本。
setHintTextColor : 设置提示文本的颜色。

在录入用户信息时(比如输入姓名、密码等等),EditText输入回车键,常常不要换行而是让光标直接跳到下一个编辑框。这个场景说起来简单,开发过程中就分解为三个功能:

1、监控用户当前输入了回车键。该功能有两种实现方式:
方式一:给编辑框注册一个OnKeyListener监听器(setOnKeyListener方法),当检测到回车键(keyCode == 66)时,触发光标跳转操作;
方式二:给编辑框注册一个TextWatcher监听器(addTextChangedListener方法),当检测到文本发生变化并找到回车换行符时,触发光标跳转操作;

2、保持当前控件不换行,依旧单行显示。该功能有两种实现方式:
方式一:在布局文件的EditText节点中加入singleLine属性,但该方式只在视觉上起作用,真正的字符串还是带有回车换行符;
android:singleLine=”true”
方式二:去掉编辑框文本中的回车符和换行符,示例代码如下:
String str = et_this.getText().replace(“\r”, “”).replace(“\n”, “”);
et_this.setText(str);

3、光标跳到下个编辑框,并自动挪到编辑框文本末尾。该功能有两种实现方式:
方式一:使用EditText的setSelection方法,示例代码如下:
et_next.requestFocus();
et_next.setSelection(et_next.getText().length());
方式二:使用Selection的setSelection方法,示例代码如下:
et_next.requestFocus();
Editable edit = et_next.getText();
Selection.setSelection(edit, edit.length());
注意控件之间切换光标要使用requestFocus方法,不能使用setFocusable方法(该方法只能切换焦点,不能切换光标)。

EditText还有一个需要特殊处理的地方,就是自动关闭软键盘。一般我们希望点击其它控件时,原输入框的软键盘就要自动消失,可惜Android不是这样处理。
于是我们得通过输入法工具类InputMethodManager来协助,该类的对象从系统服务Context.INPUT_METHOD_SERVICE中获取。下面是自动关闭软键盘的两种方法:
1、调用toggleSoftInput方法,该方法会关闭所有控件弹出的软键盘;

InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);    
    //软键盘如果已经打开则关闭之  
    if (imm.isActive() == true) {  
        imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);  
    }  

2、调用hideSoftInputFromWindow方法,该方法只关闭指定EditText控件弹出的软键盘;

InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);  
    imm.hideSoftInputFromWindow(et_server.getWindowToken(), 0);  

ImageView图形显示
scaleType : 指定图形的拉伸类型。常用的取值说明包括:fitXY表示拉伸图片正好填满视图(图片可能被拉伸变形),
fitStart表示拉伸图片使之位于视图上部,fitCenter表示拉伸图片使之位于视图中间,fitEnd表示拉伸图片使之位于视图下部,
center表示保持图片原尺寸使之位于视图中间,centerCrop表示拉伸图片并使视图位于图片中间,centerInside表示使图片位于视图中间(只压不拉)。
以上方式只有fitXY不按比例拉伸,其他都要按比例拉伸。另外注意centerInside,当图片尺寸大于视图时,centerInside等同于fitCenter;当图片尺寸小于视图时,centerInside等同于center。
src : 指定图形来源,src图形按照scaleType拉伸。
background : 指定图形背景。注意背景图不按比例拉伸,其实背景默认以fitXY方式拉伸。
在代码中设置:
setScaleType : 设置图形的拉伸类型。
setImageAlpha : 设置图形的透明度。
setImageBitmap : 设置图形的Bitmap对象。
setImageDrawable : 设置图形的Drawable对象。
setImageResource : 设置图形的资源ID。

Button文本按钮(继承自TextView)与ImageButton图像按钮(继承自ImageView)。两者之间的区别在于:
1、Button即可显示文本也可显示图形(通过设置背景图),而ImageButton只能显示图形不能显示文本;
2、Button可在文本周围区域显示小图,而ImageButton无法在某个区域显示小图;
3、ImageButton上的图像可按比例进行拉伸,而Button上的大图会拉伸变形(因为背景图无法按比例拉伸);
从上面可以看出,Button的适应面更广,所以实际开发中基本使用Button。

监听事件(略) View.OnClickListener View.OnLongClickListener 等等

CompoundButton抽象的复合按钮
因为是抽象的,所以并不能直接使用。实际开发中用的是它的两个派生类,分别是CheckBox和RadioButton,派生类继承了CompoundButton新增的属性和方法。
xml布局上新加的属性设置:
checked : 指定按钮的勾选状态,true表示勾选,false表示未勾选。
button : 指定左侧勾选图标的图形。如果不指定就使用系统的默认图标;如果要自定义图标就要设置该属性,当然也可以将该属性设置为@null,然后到drawableLeft中设置新图标。
代码中新加的方法:
setChecked : 设置按钮的勾选状态。
setButtonDrawable : 设置左侧勾选图标的图形。
setOnCheckedChangeListener : 设置勾选变化的监听器
isChecked : 判断按钮是否选中

CheckBox复选框
点击勾选,再点击则取消勾选。CheckBox是CompoundButton的一个子类,所以继承了CompoundButton的所有属性和方法。
CheckBox的勾选方法是setOnCheckedChangeListener,对应的监听器要实现接口CompoundButton.OnCheckedChangeListener。下面是CheckBox勾选监听器的代码例子:

cb.setOnCheckedChangeListener(new MyCbCheckListener());  
 class MyCbCheckListener implements CompoundButton.OnCheckedChangeListener{
 @Override  
 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {  
     String desc = String.format("您勾选了控件%d,当前状态为%b", buttonView.getId(), isChecked);  
     Toast.makeText(MainActivity.this, desc, Toast.LENGTH_LONG).show();  
 }  

RadioGroup和RadioButton
RadioButton是单选框,点击选中,但是再点击不会取消选中。只有点击同组的其他RadioButton,原来勾选的RadioButton才会取消选中。RadioButton也是CompoundButton的一个子类,所以继承了CompoundButton的所有属性和方法。
RadioGroup是容纳多个RadioButton的组布局,同组中只能有一个RadioButton被选中。下面是RadioGroup常用的几个方法:
setCheckedId : 选中指定ID的RadioButton。
getCheckedRadioButtonId : 获取选中状态RadioButton的ID。
setOnCheckedChangeListener : 设置勾选变化的监听器。

RadioGroup/RadioButton的选中事件一般由RadioGroup来响应,具体方法是setOnCheckedChangeListener,对应的监听器要实现接口RadioGroup.OnCheckedChangeListener。下面是RadioGroup选中监听器的代码例子:

 rg.setOnCheckedChangeListener(new MyRgCheckListener());   
 class MyRgCheckListener implements RadioGroup.OnCheckedChangeListener{  
     @Override  
     public void onCheckedChanged(RadioGroup group, int checkedId) {  
         Toast.makeText(MainActivity.this, "您选中了控件"+checkedId, Toast.LENGTH_LONG).show();  
     }  
  }  

Switch开关按钮
继承自CompoundButton,从Android 4.1.2开始支持。其实Switch就是个特殊UI的CheckBox,在选中与取消选中时,可展现的界面元素要比复选框要丰富些。
xml布局上新加的属性设置:
textOn : 指定右侧开启时候的文本。
textOff : 指定左侧关闭时候的文本。
switchPadding : 指定左右两个开关按钮之间的距离。
thumbTextPadding : 指定文本左右两边的距离。如果设置了该属性,则switchPadding属性失效。
thumb : 指定开关轨道的背景。
track : 指定开关标识的图标。
代码中新加的方法:
setTextOn : 设置右侧开启时候的文本。
setTextOff : 设置左侧关闭时候的文本。
setSwitchPadding : 设置左右两个开关按钮之间的距离。
setThumbTextPadding : 设置文本左右两边的距离。如果设置了该方法,则setSwitchPadding方法失效
setThumbDrawable/setThumbResource : 设置开关轨道的背景。
setTrackDrawable/setTrackResource : 设置开关标识的图标。

这里有个小测试:【不用图片,使用动画效果实现一个自定义Switch,看齐IOS的UISwitch TODO】

列表视图
AdapterView适配器视图【TODO 有时间要看这个源码】
Spinner、ListView和GridView都间接继承自AdapterView,这三个视图都存在多个元素并排展示的情况,所以需要引入适配器模式。
适配器视图的特点有:
1、定义了适配器的设置方法setAdapter,以及获取方法getAdapter。适配器用于传入视图展示需要的相关数据。
2、定义了一个数据观察者AdapterDataSetObserver,用于在列表数据发生变化时,可以通过notifyDataSetChanged方法来更新视图。
3、定义了单个元素的点击、长按、选中事件。其中点击方法为setOnItemClickListener,点击监听器为OnItemClickListener;长按方法为setOnItemLongClickListener,
长按监听器为OnItemLongClickListener;选中方法为setOnItemSelectedListener,选中监听器为OnItemSelectedListener。

Adapter
适配器Adapter与适配视图是配合使用的,每个适配类视图都要搭配相应的适配器,才能够正常工作。Adapter派生出两个接口SpinnerAdapter和ListAdapter,
然后BaseAdapter又同时实现了SpinnerAdapter和ListAdapter,所以实际开发中用的是BaseAdapter及其派生出的子类。

一般情况下自定义适配器继承自BaseAdapter就够用了,当然Android为了方便懒人,专门扩展了两种简单易用的适配器,如ArrayAdapter用于每行只显示文本的情况,
而SimpleAdapter用于每行显示左图标右文本的情况。实际开发中,ArrayAdapter多用于Spinner,但是SimpleAdapter却很少使用。
像ListView和GridView一般都是直接使用BaseAdapter,并不使用布局过于简单的SimpleAdapter。

Spinner下拉框
用于从一串列表中选择某项。下面是Spinner常用的属性和方法:
xml布局上的属性设置:
prompt : 指定弹窗的标题视图,在spinnerMode=dialog时有效。该属性值不可直接填字符串,但可通过”@string/…”方式来指定标题文字。
spinnerMode : 下拉列表的显示样式,有dialog弹窗和dropdown下拉两种。不过考虑到用户体验,实际开发中一般用dialog。spinnerMode只能在xml中设置,不能在代码中设置。
代码中的方法:
setPrompt : 设置标题文字。
setPromptId : 设置标题视图的资源ID。
setSelection : 设置当前选中哪项。
setAdapter : 设置适配器。源码中的适配器类型是SpinnerAdapter,但该类用起来很麻烦,所以实际中用的一般是ArrayAdapter,ArrayAdapter可以直接传入一个字符串数组。
setOnItemSelectedListener : 设置下拉列表的选中监听器。
下面是Spinner调用的代码例子:

ArrayAdapter starAdapter = new ArrayAdapter(this,  
            R.layout.spinner_item, starArray);  
    starAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item);  
    Spinner sp = (Spinner) findViewById(R.id.sp_hello);  
    sp.setPrompt("请选择行星");  
    sp.setAdapter(starAdapter);  
    sp.setOnItemSelectedListener(new MySelectedListener());    

 private String[] starArray = {"水星", "金星", "地球", "火星", "木星", "土星"};  
 class MySelectedListener implements OnItemSelectedListener {  
    public void onItemSelected(AdapterView arg0, View arg1, int arg2, long arg3) {  
        Toast.makeText(MainActivity.this, "您选择的是"+starArray[arg2], Toast.LENGTH_LONG).show();  
    }  

    public void onNothingSelected(AdapterView arg0) {  
    }  
 }

代码中用到的spinner_item元素布局的示例如下:

 <TextView xmlns:android="http://schemas.android.com/apk/res/android"   
    android:id="@android:id/text1"  
    style="?android:attr/spinnerItemStyle"  
    android:singleLine="true"  
    android:layout_width="match_parent"  
    android:layout_height="wrap_content"  
    android:ellipsize="marquee"  
    android:textAlignment="inherit"  
    android:textSize="17sp"  
    android:textColor="#0000ff" />  

上面这个xml布局用到了TextView的三个新属性,说明如下:
singleLine : 指定是否单行显示,取值true表示单行,false表示多行。代码中对应的方法是setSingleLine。
ellipsize : 指定字符超出TextView区域时的显示方式,取值说明如下:start表示在字符串开头显示省略号,end表示在字符串末尾显示省略号,middle表示在字符串中间显示省略号
,marquee表示以跑马灯方式显示字符串(即从左向右循环滚动,跑马灯方式需同时指定singleLine为true)。代码中对应的方法是setEllipsize。
textAlignment : 指定文本的对齐方式,常见的取值说明如下:inherit表示继承上级视图的对齐方式,center表示文本居中对齐,textStart表示文本开头对齐,textEnd表示文本末尾对齐
,viewStart表示视图开头对齐,viewEnd表示视图末尾对齐。该属性在API17后增加,即Android4.2.2以上版本才支持。代码中对应的方法是setTextAlignment。

ListView列表视图
xml布局上的属性设置:
divider : 指定分隔线的图形。如需取消分隔线,可设置该属性值为@null
dividerHeight : 指定分隔线的高度。注意如果divider设置为@null时,就不可将dividerHeight设置为大于0dp的数值,因为这样可能导致末尾的元素显示不全。
headerDividersEnabled : 指定是否显示列表开头的分隔线。但实际开发中发现这个设置不起作用,即使该属性设置为true,开头也不会显示分隔线。查看ListView的源码,发现分隔线是画在子视图的下方
,所以列表上方的分隔线就画不出来了。有种情况是例外,就是如果stackFromBottom设置为true,表示列表从下往上显示,那么此时会显示列表上方的分隔线,而不会显示列表下方的分隔线了。
footerDividersEnabled : 指定是否显示列表末尾的分隔线。
stackFromBottom : 指定列表项是否从下往上显示。

代码中的方法:
setDivider : 设置分隔线的图形。
setDividerHeight : 设置分隔线的高度。
setHeaderDividersEnabled : 设置是否显示列表开头的分隔线。该方法实际上不起作用。
setFooterDividersEnabled : 设置是否显示列表末尾的分隔线。
setStackFromBottom : 设置列表项是否从下往上显示。
setAdapter : 设置适配器。ListView使用的适配器一般继承自BaseAdapter。
setOnItemClickListener : 设置点击事件的监听器。
setOnItemLongClickListener : 设置长按事件的监听器。

ListView的使用方式
Android提供了两种使用ListView的方式:
1、ListActivity方式。首先xml布局中将ListView的id设置为系统id,即“@android:id/list”,然后页面的代码类继承ListActivity。
该方式无需在代码中获取ListView的对象,直接调用setListAdapter方法设置适配器,同时实现ListActivity的点击方法onListItemClick来响应点击事件。
2、普通Activity方式。xml布局中ListView的id可自定义,页面的代码类继承自Activity。该方式要从布局文件中获取ListView的对象,然后调用该对象的setAdapter方法设置适配器,
并调用ListView对象的setOnItemClickListener方法来设置点击事件的监听器。
两种使用方式的区别如下:
1、ListActivity方式的视图id被设置为系统id,不方便在代码中修改该列表视图的属性;
2、ListActivity方式只实现点击方法、未实现长按方法,不方便响应列表项的长按事件。
3、实际开发中经常自己写个Activity的基类,具体页面都从该Activity基类派生出来。如果有个页面采用ListActivity方式,就无法继承使用这个Activity基类了。
从上面可以看出,ListActivity方式的限制较多,所以实际开发中我们还是使用普通Activity方式来开发ListView

总结ListView的属性设置有两个注意点(不知算不算Android的bug,呵呵):
1、divider设置为@null时,就不能再设置dividerHeight为非0值,不然列表末尾元素显示有问题;
2、不管是否指定headerDividersEnabled,列表上方的分隔线都不会显示;
ListView代码示例(略)【TODO ListView 优化后续出详细demo】

RecyclerView
是Android 5.0提出的新UI控件,可以用来代替传统的ListView。【TODO 后续会出详细demo】

GridView 网格视图
【这里掌握的不是很好,有时间会测试每个属性的效果 TODO】
xml布局上的属性设置:
horizontalSpacing : 指定子视图在水平方向的间距。
verticalSpacing : 指定子视图在垂直方向的间距。
columnWidth : 指定每列的宽度。
numColumns : 指定列的数目。
stretchMode : 指定拉伸的模式。取值说明如下:none表示不做拉伸;columnWidth表示若有空余空间,则拉伸与列宽大小一致;spacingWidth表示若有空余空间,则列宽不变,把空余分配到每列间的空隙;
spacingWidthUniform与spacingWidth的区别在于,Uniform方式在每列左边和右边都补上空隙(即每行开头和末尾都补空隙),而spacingWidth在每行开头和末尾不补空隙
,只有列与列之间才补空隙。实际开发中一般把模式设置为columnWidth。
listSelector : 指定点击网格时的显示背景。

代码中的方法:
setHorizontalSpacing : 设置子视图在水平方向的间距。
setVerticalSpacing : 设置子视图在垂直方向的间距。
setColumnWidth : 设置每列的宽度。
setNumColumns : 设置列的数目。
setStretchMode : 设置拉伸的模式。
setAdapter : 设置适配器。GridView使用的适配器一般继承自BaseAdapter。
setOnItemClickListener : 设置点击事件的监听器。
setOnItemLongClickListener : 设置长按事件的监听器。

实际开发中有时需要设置网格之间表格线的颜色,可惜GridView并未直接给出相应的属性和方法,那得变通处理一下。具体的说,就是给GridView设置整个网格的背景色(例如黑色),以及网格之间的水平
间距和垂直间距;然后给每项网格的根布局设置背景色(例如白色),这样只有网格间距是黑色,从而间接画上了黑色表格线。

GridView偶尔会出现5dp的外边框,原因尚不明,要想去除这个该死的抽风边框,可将listSelector属性设置为@null,估计此问题与点击背景有关。

GridView的适配器模板与ListView是一样的,只要换掉代码里的布局文件名以及相关控件名称就好了,所以不再重复贴出GridView的适配器代码。下面是GridView的调用代码例子:

 String[] yearArray = {"鼠年", "牛年", "虎年", "兔年", "龙年", "蛇年",  
        "马年", "羊年", "猴年", "鸡年", "狗年", "猪年"};  
 ContentGridAdapter contentAdapter = new ContentGridAdapter(this, yearArray);  
 GridView gv_hello = (GridView) findViewById(R.id.gv_hello);  
 gv_hello.setNumColumns(5);  
 gv_hello.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);  
 gv_hello.setHorizontalSpacing(1);  
 gv_hello.setVerticalSpacing(1);  
 gv_hello.setAdapter(contentAdapter);  
 gv_hello.setOnItemClickListener(contentAdapter);  
 gv_hello.setOnItemLongClickListener(contentAdapter);  

布局这里也是需要多用,掌握属性,特性,控制技巧
这里感谢尚学堂在百度传课上发布的视频
https://chuanke.baidu.com/v1899056-134957-378030.html

关于适配器

适配器用于给不同的android基础控件放入数据的一个方式
一般使用系统的BaseAdapter 重写,来填充数据和布局
demo略 如:https://chuanke.baidu.com/v1899056-134957-378040.html 第20讲

关于存储位置获取

因为之前的项目中恰好涉及了手机中存储位置的处理,有真实的国内千奇百怪手机的内存获取方式,及具体情况对比,华为(emui),三星,小米(miui),乐视(),联想,oppo(),魅族(flyme)等,
【TODO 这部分整理中…】

【TODO】谷歌百分比布局 详解


这是基础篇,我这里只是搬运了官网及其他前辈的基础总结,方便日后复习及快速查找,与君共勉~


你可能感兴趣的:(android,图形,控件)