在View中通常有以下一些比较重要的回调方法:
- onFinishInflate():从XML加载组件后回调。
- onSizeChanged():组件大小改变时回调。
- onMeasure():回调该方法来确定显示的位置。
- onLayout():回调该方法来确定显示的位置。
- onTouchEvent():监听到触摸时间时回调。
当然,创建自定义View的时候,并不需要重写所有的方法,只需要重写特定条件的回调方法即可。通常情况下,有以下三种方法来实现自定义的控件:
- 对现有控件进行拓展
- 通过组合来实现新的控件
- 重写View来实现全新的控件
对现有控件进行拓展
我们以一个TextView为例,效果如下图所示:
我们来实现它,首先新建MyTextView继承TextView,其代码如下:
public class MyTextView extends TextView {
private Paint mPaint1;
private Paint mPaint2;
public MyTextView(Context context) {
super(context);
}
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
//在回调父类方法前,实现自己的逻辑,对TextView来说即在绘制文本内容之前。
mPaint1 = new Paint(); //初始化画笔1
mPaint1.setColor(getResources().getColor(android.R.color.holo_blue_bright));
mPaint1.setStyle(Paint.Style.FILL);
mPaint2 = new Paint(); //初始化画笔2
mPaint2.setColor(Color.YELLOW);
mPaint2.setStyle(Paint.Style.FILL);
//绘制外层矩形
canvas.drawRect(
0,
0,
getMeasuredWidth(),
getMeasuredHeight(),
mPaint1);
//绘制内层矩形
canvas.drawRect(
10,
10,
getMeasuredWidth() - 10,
getMeasuredHeight() - 10,
mPaint2);
canvas.save();
//绘制文字前平移10像素
canvas.translate(10, 0);
//父类完成的方法,即绘制文本
super.onDraw(canvas);
//在回调父类方法前,实现自己的逻辑,对TextView来说即在绘制文本内容之后。
canvas.restore();
}
}
下面来看一个稍微复杂一点的TextView。我们接下来利用LinearGradient、Shader和Matrix来实现一个动态的文字闪动效果,效果如下:
我们继续创建MyTextView02同样继承TextView,实现如下:
public class MyTextView02 extends TextView {
private int mViewWidth = 0;
private Paint mPaint; //带有LinearGradient属性的Paint对象
private LinearGradient mLinearGradient; //设置一个不断变化的LinearGradient
private Matrix mGradientMatrix;
private int mTranslate = 0;
public MyTextView02(Context context) {
super(context);
}
public MyTextView02(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyTextView02(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* 在onSizeChanged进行一些对象的初始化工作,并根据View的宽带设置一个LinearGradient渐变渲染器
*
* @param w
* @param h
* @param oldw
* @param oldh
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (mViewWidth == 0) {
mViewWidth = getMeasuredWidth();
if (mViewWidth > 0) {
mPaint = getPaint(); //使用getPaint()方法获取当前绘制TextView的Paint对象
mLinearGradient = new LinearGradient(
0,
0,
mViewWidth,
0,
new int[]{
Color.BLUE, 0Xffffffff, Color.BLUE},
null,
Shader.TileMode.CLAMP); //Shader渲染器
mPaint.setShader(mLinearGradient); //给这个Paint对象设置原生TextView没有的LinearGradient属性。
mGradientMatrix = new Matrix();
}
}
}
/**
* 最后在onDraw方法中,通过矩阵方式来不断平移渐变效果,从而在绘制文字时,产生动态的闪动效果
*
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mGradientMatrix != null) {
mTranslate += mViewWidth / 5;
if (mTranslate > 2 * mViewWidth) {
mTranslate = -mViewWidth;
}
mGradientMatrix.setTranslate(mTranslate, 0);
mLinearGradient.setLocalMatrix(mGradientMatrix);
postInvalidateDelayed(100);
}
}
}