博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android自己定义组件系列【8】——面膜文字动画
阅读量:4927 次
发布时间:2019-06-11

本文共 9076 字,大约阅读时间需要 30 分钟。

我们掩盖文字动画Flash中非经货共同体共同,由于Android应用程序开发人员做你想要做这个动画在应用程序中去?本文中,我们看的是如何自己的定义ImageView来实现让一张文字图片实现文字的遮罩闪烁效果,以下先来看看效果吧。

(录屏幕延时导致效果看起来不是非常好)

一、实现原理

  实现原理是重写View的onCreate方法。获取图片资源后对每一个像素的透明度进行改动来实现,再启动一个线程来循环改变某个区域中的像素透明度。

RGBA基础知识:(以下几段介绍文字引用自维基百科)

  RGBA是代表Red()Green()Blue()和Alpha的。尽管它有的时候被描写叙述为一个颜色空间,可是它事实上不过模型的附加了额外的信息。

採用的颜色是RGB,能够属于不论什么一种RGB。可是和在1971至1972年间提出了这个不可或缺的alpha数值,使得和变得可能。

提出者以alpha来命名是源于经典的方程αA + (1-α)B所用的就是这个。

  alpha通道一般用作不透明度參数。假设一个像素的alpha通道数值为0%,那它就是全然透明的(也就是看不见的),而数值为100%则意味着一个全然不透明的像素(传统的数字图像)。在0%和100%之间的值则使得像素能够透过背景显示出来,就像透过玻璃(半透明性),这样的效果是简单的二元透明性(透明或不透明)做不到的。它使变得easy。alpha通道值能够用百分比、整数或者像RGB參数那样用0到1的实数表示。

  有时它也被写成ARGB(像RGBA一样,可是第一个数据是alpha),是的产品使用的术语。比方,0x80FFFF00是50%透明的黄色,由于全部的參数都在0到255的范围内表示。0x80是128,大约是255的一半。

是一种使用RGBA的图像格式。

二、具体实现

package com.example.helloworld;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graphics.Paint;import android.os.Handler;import android.os.Message;import android.os.SystemClock;import android.util.AttributeSet;import android.view.View;import android.widget.ImageView;/** * @author 阳光小强 * */public class SplashImageView extends ImageView{     private Bitmap alterBitmap;      private Canvas canvas;      private Paint paint;  	private Handler handler;	private static int START_POSITION = 20;	private final int speed;	private int nowPosition = START_POSITION;	private static int SHOW_WIDTH = 20;	private boolean isFirst = true;	private boolean isStop = false;    	private class MyHandler extends Handler {		private static final long SCALE = 10000;		private static final int MSG_PAINT = 1;		private final SplashImageView owner;		private final int speed;		private long angle;		private long lastTime;		public MyHandler(SplashImageView owner) {			this.owner = owner;			this.lastTime = SystemClock.elapsedRealtime();			this.speed = owner.speed;			sendEmptyMessage(MSG_PAINT);		}		@Override		public void handleMessage(Message msg) {			if (msg.what == MSG_PAINT) {				long now = SystemClock.elapsedRealtime();				long delta_time = now - lastTime;				System.out.println("delta_time = " + delta_time);				System.out.println("alterBitmap.Width = " + alterBitmap.getWidth());				if(nowPosition + speed >= alterBitmap.getWidth() - START_POSITION - SHOW_WIDTH){					if(isStop){						handler.removeCallbacksAndMessages(null);						handler = null;						isStop = false;						return;					}else{						nowPosition = START_POSITION;					}				}				nowPosition = nowPosition + speed;				if (delta_time > 0) {					if(!notifiDraw(nowPosition)){						return;					}				}				this.sendEmptyMessageDelayed(MSG_PAINT, 10);			}		}	}		private boolean notifiDraw(long position) {		System.out.println("nofityDrawToatal = " + position);		if(position < alterBitmap.getWidth() - START_POSITION - SHOW_WIDTH){			this.invalidate();			return true;		}		if (handler != null) {			handler.removeCallbacksAndMessages(null);			handler = null;		}		return false;	}		@Override	public void setVisibility(int visibility) {		super.setVisibility(visibility);		if(visibility == View.VISIBLE){			if(handler == null){	        	handler =  new MyHandler(this);	        }else{	        	handler.removeCallbacksAndMessages(null);	        	handler.sendEmptyMessage(MyHandler.MSG_PAINT);	        }		}else{			if(handler != null){				handler.removeCallbacksAndMessages(null);				handler = null;			}		}	}		public void stopSplashAnimation(){		if(handler != null){			isStop = true;		}	}		public SplashImageView(Context context, AttributeSet attrs) {		super(context, attrs);		TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FuseImageView, 0, 0);		int resId = a.getResourceId(R.styleable.FuseImageView_imageSrc, 0);		int speed = a.getInt(R.styleable.FuseImageView_speed, 5);		this.speed = speed <= 0 ? 1 : speed;		Bitmap up = BitmapFactory.decodeResource(context.getResources(), resId);        alterBitmap = Bitmap.createBitmap(up.getWidth(), up.getHeight(), up.getConfig());                     canvas = new Canvas(alterBitmap);           paint = new Paint();          paint.setStrokeWidth(5);          paint.setColor(Color.BLACK);          canvas.drawBitmap(up, new Matrix(), paint);                    setImageBitmap(alterBitmap);                 if(getVisibility() == View.VISIBLE){        	if(handler == null){	        	handler =  new MyHandler(this);	        }        }	}		@Override	protected void onDraw(Canvas canvas) {				super.onDraw(canvas);				if(isFirst){			isFirst = false;			 for(int i=nowPosition; i
200){ color = Color.argb(80, r, g, b); }else{ color = Color.argb(a, r, g, b); } alterBitmap.setPixel(i, j, color); } } } for(int i=nowPosition; i
START_POSITION){ for(int i= nowPosition - SHOW_WIDTH; i
200){ color = Color.argb(80, r, g, b); }else{ color = Color.argb(a, r, g, b); } alterBitmap.setPixel(i, j, color); } } } setImageBitmap(alterBitmap); }}
三、实现具体解释

1、构造方法中进行初始化操作

public SplashImageView(Context context, AttributeSet attrs) {		super(context, attrs);		TypedArray a = context.obtainStyledAttributes(attrs,				R.styleable.FuseImageView, 0, 0);		int resId = a.getResourceId(R.styleable.FuseImageView_imageSrc, 0);		int speed = a.getInt(R.styleable.FuseImageView_speed, 5);		this.speed = speed <= 0 ? 1 : speed;		Bitmap up = BitmapFactory.decodeResource(context.getResources(), resId);		alterBitmap = Bitmap.createBitmap(up.getWidth(), up.getHeight(),				up.getConfig());		canvas = new Canvas(alterBitmap);		paint = new Paint();		paint.setStrokeWidth(5);		paint.setColor(Color.BLACK);		canvas.drawBitmap(up, new Matrix(), paint);		setImageBitmap(alterBitmap);		if (getVisibility() == View.VISIBLE) {			if (handler == null) {				handler = new MyHandler(this);			}		}	}
上面的TypedArray是自己定义的属性,在res/values文件夹下新建一个attrs.xml加入自己定义属性

这里是自己定义的两个属性,一个是图片资源ID还有一个是遮罩移动速度(事实上上面也能够继承自View来实现自己定义。我这里是有特殊须要才继承自ImageView的)

然后通过BitmapFactory获取图片资源。并通过createBitmap方法创建一个可写的Bitmap资源给画布(Canvas)。将可写的Bitmap绘制到相同资源的背景上。

底下的判读View是否可看见,是用来判读View是否可见,假设可见才开启线程进行动画的。不然的话开启线程绘制会浪费资源的(由于它根本就看不见)。

2、怎样改变透明度而且绘制(onDraw方法)

for (int i = nowPosition; i < nowPosition + SHOW_WIDTH; i++) {			for (int j = 0; j < alterBitmap.getHeight(); j++) {				int color = alterBitmap.getPixel(i, j);				int r = Color.red(color);				int g = Color.green(color);				int b = Color.blue(color);				int a = Color.alpha(color);				if (a == 80) {					color = Color.argb(255, r, g, b);				} else {					color = Color.argb(a, r, g, b);				}				alterBitmap.setPixel(i, j, color);			}		}		if (nowPosition > START_POSITION) {			for (int i = nowPosition - SHOW_WIDTH; i < nowPosition; i++) {				for (int j = 0; j < alterBitmap.getHeight(); j++) {					int color = alterBitmap.getPixel(i, j);					int r = Color.red(color);					int g = Color.green(color);					int b = Color.blue(color);					int a = Color.alpha(color);					if (a > 200) {						color = Color.argb(80, r, g, b);					} else {						color = Color.argb(a, r, g, b);					}					alterBitmap.setPixel(i, j, color);				}			}		}
主要是上面两个循环来实现绘制的,上面的循环是绘制一块区域来将文字的透明度调为最小(255),这一部分的文字就显示为高亮了,其余部分的文字透明度调值调为80,就会显示背景颜色,文字的暗度就会下降。

3、怎样循环移动遮罩

private class MyHandler extends Handler {		private static final long SCALE = 10000;		private static final int MSG_PAINT = 1;		private final SplashImageView owner;		private final int speed;		private long angle;		private long lastTime;		public MyHandler(SplashImageView owner) {			this.owner = owner;			this.lastTime = SystemClock.elapsedRealtime();			this.speed = owner.speed;			sendEmptyMessage(MSG_PAINT);		}		@Override		public void handleMessage(Message msg) {			if (msg.what == MSG_PAINT) {				long now = SystemClock.elapsedRealtime();				long delta_time = now - lastTime;				System.out.println("delta_time = " + delta_time);				System.out.println("alterBitmap.Width = "						+ alterBitmap.getWidth());				if (nowPosition + speed >= alterBitmap.getWidth()						- START_POSITION - SHOW_WIDTH) {					if (isStop) {						handler.removeCallbacksAndMessages(null);						handler = null;						isStop = false;						return;					} else {						nowPosition = START_POSITION;					}				}				nowPosition = nowPosition + speed;				if (delta_time > 0) {					if (!notifiDraw(nowPosition)) {						return;					}				}				this.sendEmptyMessageDelayed(MSG_PAINT, 10);			}		}	}
循环移动遮罩是写在一个线程中的。每隔10毫秒就去移动speed(配置的速度)的距离。来实现遮罩的移动效果,再取图片的宽度来推断是否已经到了最右边。

总结:事实上上面的实现原理并不难。要点是要知道RGBA的知识和怎样去改变像素的透明度。这个不过个人临时想到的一个方法,假设有什么更好的方式实现。希望能交流一下。

另外“阳光小强”的还有一篇博文《》參加了CSDN举办的博文大赛。假设您认为这些博文对您有帮助。希望您投出您宝贵的一票。投票地址:http://vote.blog.csdn.net/Article/Details?articleid=30101091

版权声明:本文博主原创文章,博客,未经同意不得转载。

转载于:https://www.cnblogs.com/bhlsheji/p/4808308.html

你可能感兴趣的文章
jquery实现简单抽奖功能
查看>>
[leetcode]250. Count Univalue Subtrees统计节点值相同的子树
查看>>
理解Backtracking
查看>>
T3 光
查看>>
搭建交叉调试环境 arm-linux-gdb配合gdbserver
查看>>
使用Jsoup 抓取页面的数据
查看>>
使用命令批量对文件中出现的字符串进行替换
查看>>
C#获取URL参数值
查看>>
oracle extract 函数简介
查看>>
JVM——参数设置、分析
查看>>
Struts 框架 之 文件上传下载案例
查看>>
【重走Android之路】【路线篇(二)】知识点归纳
查看>>
graphviz入门
查看>>
JAVA编码(37)—— Java字符串转换为MAP对象
查看>>
jquery.validate.js 一个jQuery验证格式控件
查看>>
有表格的九九乘法表
查看>>
WPF 4 DataGrid 控件(自定义样式篇)
查看>>
改善C#程序的建议1:非用ICloneable不可的理由
查看>>
PHP的错误机制总结
查看>>
SharePoint 2013 工作流设计之Designer 使用“可视化视图”
查看>>