自定义控件
使用场景: 在实际开发中经常会遇到现有的UI控件不能满足项目需求,或一个功能涉及到多个UI控件的组合,或实现某一特效的UI,这时必须通过自定义View的方式,实现这些功能,例如股票的实时统计图、电子书等。
分类
绘制控件 - 自绘控件
1.继承View
需要自定义绘制内容,需要继承View,必须要重写onDraw方法,在onDraw方法中来进行绘制,实现onMeasure方法,来测量控件的空间。
2.继承ViewGroup
- 通过在ViewGroup中通过this.addView(<控件对象>)来添加控件
- onMeasure方法,来测量控件的空间
- onLayout方法必须实现,在此方法中处理子控件的位置。当视图初始化,或者视图位置发生改变时候,调用此方法。
组合控件
通过继承系统已经存在的视图容器,在初始化时候,直接加载布局
mInflater.inflate(<布局资源的ID>,this);
mIvBack = (ImageView) findViewById(R.id.btn_back);
继承控件
通过继承系统已经存在的视图或者视图容器,在内部改变此视图或者视图容器的功能
例如:通过改变ListView添加删除功能
自定义View步骤
- 创建类,继承View及View的子类,并提供相关的构造方法
- 重写onMeasure()方法,并调用setMeasuredDimension(int width, int height)设置控件的大小
- 重写onDraw()方法,实现绘制特定内容
- 重写onTouchEvent()方式处理触摸事件
- 在布局文件中使用<类全名>并设置属性
自定义View属性
1.位置:res/values/attrs.xml
2.属性集
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 声明属性集 -->
<declare-styleable name="LabelView">
<attr name="text" format="string"/>
<attr name="textSize" format="dimension"/>
<attr name="textColor" format="color" />
</declare-styleable>
</resources>
3.指定属性名及其内容格式
例:<attr name="text" format="string" />
string 字符型
integer 整数型
dimension 尺寸值
color 颜色值
reference 参考某一资源ID
boolean:布尔值
使用自定义View属性
在布局控件标签中引用:xmlns:my="http://schemas.android.com/apk/res/{package_name}"
或xmlns:app="http://schemas.android.com/apk/res-auto"
在自定义控件中使用:my:text=““或app:text=""
在自定义View的View(Context context, AttributeSet attrs)构造方法中,获取自定义属性的值
//TypedArray是一个用来存放由context.obtainStyledAttributes获得的属性的数组
//在使用完成后,一定要调用recycle方法
TypedArray ta = context.obtainStyledAttributes(attrs,
R.styleable.LabelView);
CharSequence s = ta.getString(R.styleable.LabelView_text);
if (s != null) {
setText(s.toString());
}
setTextColor(ta.getColor(R.styleable.LabelView_textColor, 0xFF000000));
int textSize = ta.getDimensionPixelSize(R.styleable.LabelView_textSize, 0);
if (textSize > 0) {
setTextSize(textSize);
}
ta.recycle();
涉及相关类
View 类
- View(Context) 动态实例化控件的构造方法
- View(Context context, AttributeSet attrs) 布局中使用控件的构造的方法
- onMeasure(int widthMeasureSpec, int heightMeasureSpec) 自定义控件时重写的方法,用于测量控件大小
- onDraw(Canvas canvas) 在自义控件上绘制相关内容
- onTouchEvent(MotionEvent) 实现触摸事件处理方法
- setPadding(int l,int t,int r,int b) 设置内部间距
- layout(int l, int t, int r,int b) 改变控件位置的方法
- requestLayout() //清除布局,获取新的布局空间(刷新UI,重新调用onDraw()方法绘制UI)
- invalidate() //重新绘制新的数据(刷新UI,重新调用onDraw()方法绘制UI)
MeasureSpec 测量空间工具类
- int MeasureSpec.getMode(mSpec) 获取控件大小模式
- MeasureSpec.EXACTLY,确切空间,布局中的属性值一般为match_parent或160dp固定值
- MeasureSpec.AT_MOST 尽量多的空间,布局中的属性值wrap_content
- MeasureSpec.UNSPECIFIED 未指定的,一般在父控件中使用
- MeasureSpec.getSize(mSpec) 获取控件大小
TypedArray 属性数组类
- TypeArray Context.obtainStyledAttributes(attrs,R.styleable.LabelView) 获取指定attrs中的所有属性
- String getString(R.styleable.LabelView_text) 获取指定属性的文本值
- int getDimensionPixelSize(R.styleable.LabelView_textSize, 0) 获取指定属性的间距值
- int getColor(R.styleable.LabelView_textColor, 0xFF000000) 获取指定属性的颜色值
Paint 画笔类
- Paint.setAntiAlias(true) 启用抗锯齿
- Paint.setTextSize(int pixes) 设置字体大小,像素,一般转成sp
- Paint.setColor(int color) 设置颜色
- Paint.setStyle(Paint.Style) 设置画笔样式
- float mTextPaint.measureText(String) 测量文字的大小
- Paint.ascent() 获取文字基准线以上到文字顶部的间距,负数
- Paint.descent() 获取文字基准线以下到文字底部的间距
Canvas 画布类
- canvas.drawText(String,int x,int y,Paint) 绘制文本
- canvas.drawRoundRect(RectF,int rx,int ry,Paint) 绘制圆角四边方形
- canvas.drawBitmap(bitmap, left, top, paint) 绘制图片
- canvas.drawCircle(cx, cy, radius, paint) 绘制圆
- canvas.drawLine(startX, startY, stopX, stopY, paint) 绘制线条
Xfermode 两个图层的转换模式
Xfermode有三个子类 :
AvoidXfermode 指定了一个颜色和容差,强制Paint避免在它上面绘图(或者只在它上面绘图)。
PixelXorXfermode 当覆盖已有的颜色时,应用一个简单的像素异或操作。
PorterDuffXfermode 这是一个非常强大的转换模式,使用它,可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互。
要应用转换模式,可以使用setXferMode方法,如下所示:
AvoidXfermode avoid = new AvoidXfermode(Color.BLUE, 10, AvoidXfermode.Mode. AVOID);
borderPen.setXfermode(avoid);
PorterDuff.Mode为枚举类,一共有16个枚举值:
1.PorterDuff.Mode.CLEAR
所绘制不会提交到画布上。
2.PorterDuff.Mode.SRC
显示上层绘制图片
3.PorterDuff.Mode.DST
显示下层绘制图片
4.PorterDuff.Mode.SRC_OVER
正常绘制显示,上下层绘制叠盖。
5.PorterDuff.Mode.DST_OVER
上下层都显示。下层居上显示。
6.PorterDuff.Mode.SRC_IN
取两层绘制交集。显示上层。
7.PorterDuff.Mode.DST_IN
取两层绘制交集。显示下层。
8.PorterDuff.Mode.SRC_OUT
取上层绘制非交集部分。
9.PorterDuff.Mode.DST_OUT
取下层绘制非交集部分。
10.PorterDuff.Mode.SRC_ATOP
取下层非交集部分与上层交集部分
11.PorterDuff.Mode.DST_ATOP
取上层非交集部分与下层交集部分
12.PorterDuff.Mode.XOR
异或:去除两图层交集部分
13.PorterDuff.Mode.DARKEN
取两图层全部区域,交集部分颜色加深
14.PorterDuff.Mode.LIGHTEN
取两图层全部,点亮交集部分颜色
15.PorterDuff.Mode.MULTIPLY
取两图层交集部分叠加后颜色
16.PorterDuff.Mode.SCREEN
取两图层全部区域,交集部分变为透明色
网友评论