Android初级基础知识复习(十五) —— 自定义控件

自定义视图

自定义视图的过程,包括声明属性与编写代码两个过程。编写代码的过程分为构造对象、测 量尺寸、绘制视图3个步骤。另外,详细说明绘制视图的3种途径:重写onLayout方法、重写onDraw方法和重写dispatchDraw方法。

声明属性

通过扩展自定义属 性,以满足在布局文件指定属性的要求。

1.在res\values目录下创建attrs.xml。其中,declare-styleable的name属性值表示新视图名为 CustomPagerTab,两个attr节点表示新增的两个属性分别是textColor和textSize。
2.在代码的widget目录中创建CustomPagerTab.java。
3.在布局文件根节点增加命名空间声明xmlns:app=“http://schemas.android.com/apk/res-auto”,并 把android.support.v4.view.PagerTabStrip的节点名称改为自定义视图的全路径名称(如 com.example.custom.widget.CustomPagerTab),同时在该节点下指定新增的两个属性——app:textColor与 app:textSize。

在自定义视图的步骤1中,attr节点的name表示新属性的名称format表示新属性的格式(数据类型);在步骤2中,调用getColor方法获取颜色值,调用getDimensionPixelSize方法获取文字大小不同的数据类型调用不同的获取方法

在这里插入图片描述

enum类型与flag类型的使用稍微复杂,枚举类型的属性常见的有LinearLayout的orientation和 ImageView的scaleType;标志类型的属性常见的有TextView的gravity和EditText的inputType。

构造对象

新增视图属性的声明很简单,麻烦的是在代码中进行视图的自定义处理自定义视图的编码主要由3部分组成:
(1)重写构造函数初始化该视图的自有属性
(2)重写测量函数onMeasure计算该视图的(一般只有复杂视图才重写该函数)。
(3)重写绘图函数onLayout、onDraw、dispatchDraw,视情况重写3个中的一个或多个。

一般要重写3个构造函数。前面在演示新控件CustomPagerTab时,示例代码给出了3个构造函数(实际 只实现了两个),分别是:
(1)只带一个参数的public CustomPagerTab (Context context)。在代码中声明对象时采用该构造函数。
(2)带两个参数的public CustomPagerTab (Context context,AttributeSet attrs)。在布局文件中引用自定义视图时采用该构造函数。
步骤01 在styles.xml中定义一种风格样式
步骤02 在attrs.xml中声明该风格样式的参照属性
步骤03 在代码中由第二种构造函数调用第三种构造函数,在调用时把该参照属性传到第三个参数中。

测量尺寸

一般在布局文件中对视图的宽和高有3种赋值方式:
在这里插入图片描述
方式1和方式3都好办,要么取上级视图的数值,要么取具体数值。难办的是方式2,这个尺寸究竟要如 何度量,不可能让开发者人手一把尺子在屏幕上比划。Android提供了相关度量方法,可以在不同情况下进 行尺寸测量。需要测量的对象主要有3种,分别是文本尺寸、图形尺寸和布局尺寸。

1. 文本尺寸测量

文本尺寸分为文本的宽度和高度,要根据文本大小分别进行计算。其中,文本宽度使用Paint类的 measureText方法测量;

文本高度的计算要烦琐一些,用到了FontMetrics类,该类提供了5个与高度相关的属性:
在这里插入图片描述之所以区分这些属性,是为了计算不同规格的高度。如果要得到文本自身的高度,高度值就是descent 减去ascent;如果要得到文本所在行的行高,高度值就是bottom减去top再加上leading。

2. 图形尺寸测量

相对于文本尺寸,图形尺寸的计算反而简单些,因为Android提供了可以直接使用的宽、高获取方法。 如果图形是Bitmap格式,就通过getWidth和getHeight方法获取位图对象的宽度和高度;如果图形是Drawable 格式,就通过getIntrinsicWidth方法获取该图形的宽度,通过getIntrinsicHeight方法获取该图形的高度。

3. 布局尺寸测量

文本尺寸测量主要用于TextView、Button等文本控件,图形尺寸测量主要用于ImageView、ImageButton 等图像控件。在实际开发中,有更多场合需要测量布局视图的尺寸。布局视图内部可能有文本控件、图像控件,还可能有padding和margin。如此一来,对布局视图的内部控件一个个单独测量变得不切实际。View 类提供了一种对布局整体进行测量的思路。对应layout_width和layout_height的3种赋值方式,Android的视图提供了3种测量模式,具体取值说明见表6-4。
在这里插入图片描述

宽高尺寸的动态调整

一个视图的宽和高,其实在页面布局的时候就决定了,视图节点的android:layout_width属性指定了该视图的宽度,而android:layout_height属性指定了该视图的高度。这两个属性又有三种取值方式,分别是:取值match_parent表示与上级视图一样尺寸取值wrap_content表示按照自身内容的实际尺寸,最后一种则直接指定了具体的dp数值。在多数情况之下,系统按照这三种取值方 式,完全能够自动计算正确的视图宽度和视图高度。 当然也有例外,像列表视图ListView就是个另类,尽管ListView在多数场合的高度计算也不会出错,但是把它放到ScrollView之中便出现问题了。ScrollView本身叫做滚动视图,而列表视图ListView也是可以滚动的,于是一个滚动视图嵌套另一个也能滚动的视图,那么在双方的重叠区域,上下滑动的手势究竟表示要滚动哪个视图?这个滚动冲突的问题,不光令开发者脑袋浆糊,便是Android系统也得神经错乱。所以 Android目前的处理对策是:如果ListView的高度被设置为wrap_content,则此时列表视图只显示一行的高度,然后布局内部只支持滚动ScrollView。 如此虽然滚动冲突的问题暂时解决,但是又带来一个新问题,好好的列表视图仅仅显示一行内容,这 让出不了头的剩余列表行情何以堪?按照用户正常的思维逻辑,列表视图应该显示所有行,并且列表内容 要跟着整个页面一齐向上或者向下滚动。显然此时系统对ListView的默认处理方式并不符合用户习惯,只能对其进行改造使之满足用户的使用习惯。改造列表视图的一个可行方案,便是重写它的测量函数 onMeasure,不管布局文件中设定的视图高度为何,都把列表视图的高度改为最大高度,即所有列表项高度加起来的总高度。

绘制视图

在自定义视图中,可重写3个函数用于视图的绘制,分别是onLayout、onDraw和dispatchDraw。这3个函 数的执行顺序是onLayout→onDraw→dispatchDraw。其中,onLayout和dispatchDraw通常用于布局类视图。 下面逐一介绍这3个函数的用途与用法。

1. onLayout

onLayout方法用于定位子视图在本布局视图中的位置。该方法的入参表示本布局在上级视图的上、 下、左、右位置,子视图在本布局中的位置要另行计算,计算完毕调用子视图的layout方法调整子视图的位置。

2. onDraw

onDraw是最常使用的绘图方法,该方法的入参为Canvas画布对象,在画布上绘图相当于在屏幕上绘 图。绘图本身是个很大的课题,画布的用法也多种多样,如Canvas提供了3类方法,分别是划定可绘制的区域、在区域内部绘制图形和画布的控制操作。
(1)划定可绘制的区域虽然本视图内的所有区域都是可以绘制的,但是有时候开发者只想在某个矩形区域内部画画,这时在 绘图之前就得指定允许绘图的区域界限,相关方法说明如下:

  1. clipPath:裁剪不规则曲线区域。
  2. clipRect:裁剪矩形区域。
  3. clipRegion:裁剪一块组合区域。

(2)在区域内部绘制图形
该类方法用来绘制各种基本几何图形,相关方法说明如下:

  1. drawArc:绘制扇形/弧形。第4个参数为true时画扇形、为false时画弧形。
  2. drawBitmap:绘制图像。
  3. drawCircle:绘制圆形。
  4. drawLine:绘制直线。
  5. drawOval:绘制椭圆。
  6. drawPath:绘制路径,即不规则曲线。
  7. drawPoint:绘制点。
  8. drawRect:绘制矩形。
  9. drawRoundRect:绘制圆角矩形。
  10. drawText:绘制文本。

(3)画布的控制操作 控制操作包括旋转、缩放、平移以及存取画布状态的操作,相关方法说明如下:

  1. rotate:旋转画布。
  2. scale:缩放画布。
  3. translate:平移画布。
  4. save:保存画布状态。
  5. restore:恢复画布状态。

上面绘图用的draw***方法只是指定绘制哪个几何图形,真正的细节描绘还要靠画笔Paint类实现。Paint 类定义了画笔的颜色、样式、粗细、阴影等,常用方法说明如下:

  1. setAntiAlias:设置是否使用抗锯齿功能。主要用于画圆圈等曲线。
  2. setDither:设置是否使用防抖动功能。
  3. setColor:设置画笔的颜色。
  4. setShadowLayer:设置画笔的阴影区域与颜色。
  5. setStyle:设置画笔的样式。Style.STROKE表示线条,Style.FILL表示填充。
  6. setStrokeWidth:设置画笔线条的宽度。

3. dispatchDraw

dispatchDraw与onDraw函数一样都是绘图方法,区别在于onDraw的调用在绘制子视图之前, dispatchDraw的调用在绘制子视图之后。如果不想自身视图被子视图覆盖,就只能在dispatchDraw方法中进 行绘图处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值