android自定义view实现字体变色
来源:互联网 发布:网络竞价排名 编辑:程序博客网 时间:2024/06/05 02:51
上次看了鸿洋的博客,其中有一篇博客实现的是字体逐渐变色的效果,不过其使用的是clipRect实现的,今天给大家带来另一种实现方式,通过XferMode来实现。先看效果吧。
先说下实现原理:我们首先绘制当前显示的文本内容,然后设置xfermode的值为PorterDuff.Mode.SRC_IN,然后子啊绘制一个和我们当前view高度相同,并且宽度不断增大的绿色矩形。废话不多说,下面看具体实现:
自定义属性
<?xml version="1.0" encoding="utf-8"?><resources> <attr name="text_value" format="string"/> <attr name="text_size" format="dimension"/> <declare-styleable name="filter_text"> <attr name="text_value" /> <attr name="text_size" /> </declare-styleable></resources>
这里我只定义了两个属性:
- text_value 表示需要绘制的文本内容
- text_size 表示绘制的文本字体的大小
获取自定义属性并且初始化
在构造方法中,获取自定义的属性,并且进行必要的初始化工作。
public FilterText(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //获取自定义属性的值 TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.filter_text); mTextValue = array.getString(R.styleable.filter_text_text_value); mTextSize = array.getDimensionPixelSize(R.styleable.filter_text_text_size, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics())); //TypedArray用完记得回收 array.recycle(); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); //设置文本的字体大小 mPaint.setTextSize(mTextSize); mBound = new Rect(); //用来计算当前mTextValue的宽度和高度 mPaint.getTextBounds(mTextValue, 0, mTextValue.length(),mBound); }
这里需要注意,由于我们等下对于该自定义view的宽高会设置为wrap_content,所以需要重写onMeasure方法来测量我们当前的view的宽高,所以需要在测量之前设置好字体的大小,否则会影响测量值。
重写onMeasure方法
/** * 测量当前view的大小 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int finalWidth = 0; int finalHeight = 0; if (widthMode == MeasureSpec.EXACTLY) { //如果测量模式是EXACTLY类型,则直接使用推荐值加上padding的值 finalWidth = widthSize + getPaddingLeft() + getPaddingRight(); } else { finalWidth = getPaddingLeft() + getPaddingRight() + mBound.width(); if (widthMode == MeasureSpec.AT_MOST) { //如果测量模式是AT_MOST,则取期望值和我们计算出的最小值 finalWidth = Math.min(finalWidth, widthSize); } } if (heightMode == MeasureSpec.EXACTLY) { finalHeight = heightSize + getPaddingBottom() + getPaddingTop(); } else { finalHeight = getPaddingTop() + getPaddingBottom() + mBound.height(); if (heightMode == MeasureSpec.AT_MOST) { finalHeight = Math.min(finalHeight, heightSize); } } //记得调用setMeasuredDimension方法 setMeasuredDimension(finalWidth, finalHeight); }
这里首先获得宽高的测量模式和推荐的值,然后根据具体的测量模式来计算当前view的宽度和高度。最后记得调用setMeasuredDimension方法。
重写onDraw方法
@Overrideprotected void onDraw(Canvas canvas) { super.onDraw(canvas); int width = getWidth(); int height = getHeight(); Paint paint = new Paint(); //创建一个图层,在图层上演示图形混合后的效果 int sc = canvas.saveLayer(0, 0, width, height, null, Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG); //先绘制“dest canvas.drawBitmap(getDesBitmap(width,height), 0 , 0 , paint); //设置Paint的Xfermode paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); mRectWidth += 10; canvas.drawBitmap(getSrcBitmap(mRectWidth,height), 0 , 0, paint); //重置当前Xfermode paint.setXfermode(null); // 还原画布 canvas.restoreToCount(sc); if (mRectWidth < width) {//不断重绘当前view try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } invalidate(); } }
主要分为以下几步:
- 首先获得当前view的宽度和高度
int width = getWidth();int height = getHeight();
- 创建一个图层,在图层上演示图形混合后的效果,注意一定要创建该图层,否则会出现两个图形交集之外部分为黑色
int sc = canvas.saveLayer(0, 0, width, height, null, Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
- 绘制src和dst
//先绘制srccanvas.drawBitmap(getSrcBitmap(width,height), 0 , 0 , paint);//设置Paint的Xfermodepaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));//每次绘制之前将dst的宽度加上10个像素,高度保持和src相同mRectWidth += 10;canvas.drawBitmap(getDesBitmap(mRectWidth,height), 0 , 0, paint);//重置当前Xfermodepaint.setXfermode(null);// 还原画布canvas.restoreToCount(sc);
这里的getSrcBitmap和getDesBitmap就是我们分别绘制的文本和过滤的背景色矩形,如下:
// 创建一个矩形bitmap,作为src的bitmapprivate Bitmap getSrcBitmap(int w, int h) { Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); Canvas c = new Canvas(bm); Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); //绘制边框 p.setStrokeWidth(3); p.setColor(Color.RED); p.setStyle(Paint.Style.STROKE); c.drawRect(0, 0, w, h, p); //绘制文字 p.setColor(Color.BLACK); p.setStyle(Paint.Style.FILL); p.setTextSize(mTextSize); c.drawText(mTextValue,w / 2 - mBound.width() / 2, h / 2 + mBound.height() / 2, p); return bm;}// 创建一个矩形bitmap,作为dst的bitmapprivate Bitmap getDesBitmap(int w, int h) { //首先创建一个位图 Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); //创建一个和当前位图相同大小的canvas对象 Canvas c = new Canvas(bm); Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); p.setColor(Color.GREEN); c.drawRect(0,0,w,h ,p); return bm;}
总结以下:
- 测量当前view的宽和高,如果有字体大小需要在onMeasure测量之前就设置其大小,否则影响测量值
- 在onDraw方法中具体的绘制工作:
- 创建一个图层,在图层上演示图形混合后的效果
- 先绘制src
- 设置Paint的Xfermode,PorterDuff.Mode.SRC_IN
- 绘制dst
- 重置当前Xfermode
还原画布
ok,今天就到这里了,希望大家喜欢。
源码下载
0 0
- android自定义view实现字体变色
- Android自定义view-玩转字体变色
- Android自定义字体变色控件
- Android自定义view字体居中
- 【android】设置View字体点击变色和边框背景设置
- Android 自定义View-图片文字变色,实现酷炫LoadingView或者进度条
- Android自定义字体实现
- android-实现自定义字体
- Android自定义View——滑动变色指示器
- Android自定义View实现
- Android 实现自定义View
- Android实现自定义View
- Android实现自定义View
- android实现自定义view
- (android实战)控件选中字体颜色变色实现
- textview中实现字体变色
- 自动变色自定义View和自定义关键字变色TextView
- 自动变色自定义View和自定义关键字变色TextView
- 软件研发管理:置身其中看问题
- solr.in.action-ch05
- 如何利用s3c2440的gpio实现数据输入和输出
- Eclipse代码托管到GitHub
- fs4412开发板学习笔记(七)
- android自定义view实现字体变色
- 143 Reorder List [Leetcode]
- 顺便贴一下无聊的Java作业20151027
- Wildcard Matching
- 进制转换
- Codeforces Round #327 (Div. 1) E. Birthday【AC自动机+网络流】
- codeforces#292B_Drazil and His Happy Friends-暴力水题
- Codeforces 590B Chip 'n Dale Rescue Rangers
- Cookie深度解析