我们掩盖文字动画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
版权声明:本文博主原创文章,博客,未经同意不得转载。