您的位置:首页 > 其它

自定义View并自定义其属性学习小Demo

2015-10-23 12:16 218 查看
最近在看徐老师的《Android群英传》,里面有一章是讲的如何自定义View,之前一直觉得自定义挺复杂的,感觉像座大山一直压在自己的Android之路上,看了书中讲解之后,发现原来一直神秘的自定义View也没那么神秘,下面就和我一起来通过一个简单的小Demo一起来体验一下吧。

重写TextView实现一个简单的动态渐变效果的TextView

首先讲一下思路和知识准备,实现渐变需要使用到一个渲染对象LinearGradient,只有一个渲染对象还不行,因为这样知识一个静态的效果,要实现动态还需要一个矩阵位移对象Matrix。

1、首先我们重写View的onSizeChanged方法,在里面执行一些初始化的操作,比如为TextView的Paint画笔对象设置渲染对象等,代码如下:

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// 初始化操作
if (mViewWidth == 0) {
// 设置自定义textview的宽度值
mViewWidth = getMeasuredWidth();
if (mViewWidth > 0) {
// 获取到TextView的paint对象
mPaint = getPaint();
// 设置自定义的线性渲染
// CLAMP重复最后一个颜色至最后
// MIRROR重复着色的图像水平或垂直方向已镜像方式填充会有翻转效果
// REPEAT重复着色的图像水平或垂直方向
mLinearGradient = new LinearGradient(0, 0, mViewWidth, 0, new int[]{colorOne, colorTwo, colorThree}, null, Shader.TileMode.CLAMP);
// 为textview的paint设置渲染器
mPaint.setShader(mLinearGradient);
// 初始化全局矩阵
mGradientMatrix = new Matrix();
}
}
}


2、重写onDraw方法,在里面实现动态的渐变效果,代码如下:

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mGradientMatrix != null) {
// 每次执行一次,就将偏移增加一个值
mTranslate += mViewWidth / 5;
Log.e("gu", "mTranslate==>" + mTranslate);
// 如果偏移值大于了两倍的textview宽度,则将偏移值置为-mViewWidth
if (mTranslate > 2 * mViewWidth) {
mTranslate = -mViewWidth;
}
// 为矩阵设置偏移
mGradientMatrix.setTranslate(mTranslate, 0);
// 为渲染器加上偏移矩阵
mLinearGradient.setLocalMatrix(mGradientMatrix);
// 设置延迟重新提交绘制View
postInvalidateDelayed(delayTime);
}
}


3、我们有时也需要自定义一些属性,使我们的控件用起来更加的人性化,这个其实也简单,首先在values目录下新建一个attrs.xml文件,然后在里面自定义一些自定义控件想要的属性:

<declare-styleable name="CustomTextViewTwo">
<attr name="shaperColorOne" format="color"></attr>
<attr name="shaperColorTwo" format="color"></attr>
<attr name="shaperColorThree" format="color"></attr>
<attr name="delayTime" format="integer"></attr>
</declare-styleable>


4、设置好上面的属性列表之后,就可以在布局文件中使用上面的参数了,只不过要先加一个命名空间
xmlns:app="http://schemas.android.com/apk/res-auto"
,这样编译器就可以找到我们自己定义的属性了:

<com.gu.customviewtest.CustomTextViewTwo
android:layout_width="100dp"
android:layout_height="50dp"
android:gravity="center"
android:text="我是测试的文字"
app:delayTime="1000"
app:shaperColorOne="#cc0e0e"
app:shaperColorThree="#cc0e0e"
app:shaperColorTwo="#f6d605" />


5、现在万事具备,只欠东风了,我们还要在自定义View的构造器中,获取到上面xml布局中设置的这些属性值:

private void init(Context context, AttributeSet attrs) {
//获取到ta对象
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomTextViewTwo);
//从ta对象中,获取到xml中对象属性配置值
colorOne = ta.getColor(R.styleable.CustomTextViewTwo_shaperColorOne, Color.BLACK);
colorTwo = ta.getColor(R.styleable.CustomTextViewTwo_shaperColorTwo, Color.BLACK);
colorThree = ta.getColor(R.styleable.CustomTextViewTwo_shaperColorThree, Color.BLACK);
delayTime = ta.getInteger(R.styleable.CustomTextViewTwo_delayTime, 100);
//TypeArray 对象用完以后必须得回收
ta.recycle();
}


6、至此,整个一个简单的自定义View代码就实现了,下面我贴一下完整的代码供大家参考:

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;

/**
* Created by Nate on 2015/10/22.
*/
public class CustomTextViewTwo extends TextView {

private int mViewWidth = 0;
private Paint mPaint;
private LinearGradient mLinearGradient;
private Matrix mGradientMatrix;
private int mTranslate;
private int colorOne;
private int colorTwo;
private int colorThree;
private int delayTime;

/**
* 在java代码创建视图的时候被调用,如果是从xml填充的视图,就不会调用这个
*
* @param context
*/
public CustomTextViewTwo(Context context) {
super(context);
}

/**
* 这个是在xml创建但是没有指定style的时候被调用
*
* @param context
* @param attrs
*/
public CustomTextViewTwo(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}

/**
* 这个是在xml创建,并且指定style的时候被调用
*
* @param context
* @param attrs
* @param defStyleAttr
*/
public CustomTextViewTwo(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}

private void init(Context context, AttributeSet attrs) { //获取到ta对象 TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomTextViewTwo); //从ta对象中,获取到xml中对象属性配置值 colorOne = ta.getColor(R.styleable.CustomTextViewTwo_shaperColorOne, Color.BLACK); colorTwo = ta.getColor(R.styleable.CustomTextViewTwo_shaperColorTwo, Color.BLACK); colorThree = ta.getColor(R.styleable.CustomTextViewTwo_shaperColorThree, Color.BLACK); delayTime = ta.getInteger(R.styleable.CustomTextViewTwo_delayTime, 100); //TypeArray 对象用完以后必须得回收 ta.recycle(); }
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); // 初始化操作 if (mViewWidth == 0) { // 设置自定义textview的宽度值 mViewWidth = getMeasuredWidth(); if (mViewWidth > 0) { // 获取到TextView的paint对象 mPaint = getPaint(); // 设置自定义的线性渲染 // CLAMP重复最后一个颜色至最后 // MIRROR重复着色的图像水平或垂直方向已镜像方式填充会有翻转效果 // REPEAT重复着色的图像水平或垂直方向 mLinearGradient = new LinearGradient(0, 0, mViewWidth, 0, new int[]{colorOne, colorTwo, colorThree}, null, Shader.TileMode.CLAMP); // 为textview的paint设置渲染器 mPaint.setShader(mLinearGradient); // 初始化全局矩阵 mGradientMatrix = new Matrix(); } } }
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mGradientMatrix != null) { // 每次执行一次,就将偏移增加一个值 mTranslate += mViewWidth / 5; Log.e("gu", "mTranslate==>" + mTranslate); // 如果偏移值大于了两倍的textview宽度,则将偏移值置为-mViewWidth if (mTranslate > 2 * mViewWidth) { mTranslate = -mViewWidth; } // 为矩阵设置偏移 mGradientMatrix.setTranslate(mTranslate, 0); // 为渲染器加上偏移矩阵 mLinearGradient.setLocalMatrix(mGradientMatrix); // 设置延迟重新提交绘制View postInvalidateDelayed(delayTime); } }}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: