小米手机用户可以看到,小米手机在应用卸载时会有一个粒子爆炸的特效效果,对此类动画效果垂涎已久,奈何一直没有机会用。正好最近项目里需要用到粒子爆炸的特效,于是便抽时间自己也试着仿写了一个效果出来。

先看下效果:

How to use:

**

Step 1. Add the JitPack repository to your build file
Add it in your root build.gradle at the end of repositories:

    allprojects {repositories {...maven { url 'https://jitpack.io' }}}

Step 2.Add the dependency

    dependencies {compile 'com.github.zhaolei9527:Particle-master:v1.0.1'}

代码中这样使用:

首先提供了响应式触发的方式,首先进行埋雷,当控件被点击时,触发爆炸。是不是很刺激?

   //目前提供了六种的粒子爆炸特效explosionSite1 = new ExplosionSite(this, new BooleanFactory());explosionSite2 = new ExplosionSite(this, new ExplodeParticleFactory());explosionSite3 = new ExplosionSite(this, new FallingParticleFactory());explosionSite4 = new ExplosionSite(this, new FlyawayFactory());explosionSite5 = new ExplosionSite(this, new InnerFallingParticleFactory());explosionSite6 = new ExplosionSite(this, new VerticalAscentFactory());//爆炸激活方式一:将View或ViewGroup添加至雷管监听,View被点击时,触发爆炸explosionSite1.addListener(img_1);explosionSite2.addListener(img_2);explosionSite3.addListener(img_6);explosionSite4.addListener(img_4);explosionSite5.addListener(img_5);explosionSite6.addListener(img_3);

其次针对一些情况,提供了另外一种直接的触发方式。是不是更刺激?

                //爆炸激活方式二:将View或ViewGroup直接点燃爆炸explosionSite1.explode(img_1);explosionSite2.explode(img_2);explosionSite3.explode(img_3);explosionSite4.explode(img_4);explosionSite5.explode(img_5);explosionSite6.explode(img_6);

看下原理:GitHub项目地址
网上实现类似相同效果的很多,基本规则也都差不多。
主要对象如下:
ExplosionSite:爆炸效果发生的场地,是一个View。当一个控件需要爆炸时,需要为控件生成一个ExplosionSite,这个ExplosionSite覆盖整个屏幕,于是我们才能看到完整的爆炸效果,在ExplosionField的构造函数中,传入不同的ParticleFactory,就可以生成不同的爆炸效果。

ExplosionAnimator:爆炸动画,其实是一个计时器,继承自ValueAnimator。0x400s内,完成爆炸动画,每次计时,就更新所有粒子的运动状态。draw()方法是它最重要的方法,也就是使所有粒子重绘自身,从而实现动画效果。

ParticleFactory:是一个抽象类。用于产生粒子数组,不同的ParticleFactory可以产生不同类型的粒子数组。

Particle:抽象的粒子类。代表粒子本身,必须拥有的属性包括,当前自己的cx,cy坐标和颜色color。必须实现两个方法,draw()方法选择怎么绘制自身(圆形还是方形等),caculate()计算当前时间,自己所处的位置。


实现原理:
1、获取当前控件背景bitmap
例如,例子中使用的是imageview,对于控件,在Utils中提供有一个工具类,可以获得其背景的Bitmap对象

   public static Bitmap createBitmapFromView(View view) {view.clearFocus();Bitmap bitmap = createBitmapSafely(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888, 1);if (bitmap != null) {synchronized (sCanvas) {Canvas canvas = sCanvas;canvas.setBitmap(bitmap);view.draw(canvas);canvas.setBitmap(null);}}return bitmap;}public static Bitmap createBitmapSafely(int width, int height, Bitmap.Config config, int retryCount) {try {return Bitmap.createBitmap(width, height, config);} catch (OutOfMemoryError e) {e.printStackTrace();if (retryCount > 0) {System.gc();return createBitmapSafely(width, height, config, retryCount - 1);}return null;}}

2、将View镜像转换成粒子对象
获取Bitmap以后,我们交给工厂对象进行加工,根据Bitmap生产Particle数组。
我们知道Bitmap可以看成是一个像素矩阵,矩阵上面的点,就是一个个带有颜色的像素,于是我们可以获取到每个点的颜色和位置,组装成一个对象Particle,这么一来,Particle就代表带有颜色的点了。

public abstract class ParticleFactory {public abstract Particle[][] generateParticles(Bitmap bitmap, Rect bound);
}

简单来说都一样,就是拿要爆炸的View制作一个镜像出来然后返回。

然后来看一个粒子效果的具体实现。

  public Particle[][] generateParticles(Bitmap bitmap, Rect bound) {int w = bound.width();int h = bound.height();int partW_Count = w / PART_WH; //横向个数int partH_Count = h / PART_WH; //竖向个数int bitmap_part_w = bitmap.getWidth() / partW_Count;int bitmap_part_h = bitmap.getHeight() / partH_Count;Particle[][] particles = new Particle[partH_Count][partW_Count];for (int row = 0; row < partH_Count; row ++) { //行for (int column = 0; column < partW_Count; column ++) { //列//取得当前粒子所在位置的颜色int color = bitmap.getPixel(column * bitmap_part_w, row * bitmap_part_h);float x = bound.left + BooleanFactory.PART_WH * column;float y = bound.top + BooleanFactory.PART_WH * row;particles[row][column] = new BooleanParticle(color,x,y,bound);}}return particles;}

很简单,其中Rect类型的bound,是代表原来View控件的宽高信息。
根据我们设定的每个粒子的大小,和控件的宽高,我们就可以计算出,有多少个粒子组成这个控件的背景。
我们取得每个粒子所在位置的颜色,位置,用于生产粒子,这就是BooleanParticle。

3、爆炸对象及主要流程

public class ExplosionSite extends View {private static final String TAG = "ExplosionField";private ArrayList<ExplosionAnimator> explosionAnimators;private HashMap<View, ExplosionAnimator> explosionAnimatorsMap;private OnClickListener onClickListener;private ParticleFactory mParticleFactory;public ExplosionSite(Context context, ParticleFactory particleFactory) {super(context);init(particleFactory);}public ExplosionSite(Context context, AttributeSet attrs, ParticleFactory particleFactory) {super(context, attrs);init(particleFactory);}private void init(ParticleFactory particleFactory) {explosionAnimators = new ArrayList<ExplosionAnimator>();explosionAnimatorsMap = new HashMap<View, ExplosionAnimator>();mParticleFactory = particleFactory;attach2Activity((Activity) getContext());}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);for (ExplosionAnimator animator : explosionAnimators) {animator.draw(canvas);}}/*** 爆破** @param view 使得该view爆破*/public void explode(final View view) {//防止重复点击if (explosionAnimatorsMap.get(view) != null && explosionAnimatorsMap.get(view).isStarted()) {return;}if (view.getVisibility() != View.VISIBLE || view.getAlpha() == 0) {return;}final Rect rect = new Rect();view.getGlobalVisibleRect(rect); //得到view相对于整个屏幕的坐标int contentTop = ((ViewGroup) getParent()).getTop();Rect frame = new Rect();((Activity) getContext()).getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);int statusBarHeight = frame.top;rect.offset(0, -contentTop - statusBarHeight);//去掉状态栏高度和标题栏高度if (rect.width() == 0 || rect.height() == 0) {return;}//震动动画ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f).setDuration(150);animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {Random random = new Random();@Overridepublic void onAnimationUpdate(ValueAnimator animation) {view.setTranslationX((random.nextFloat() - 0.5f) * view.getWidth() * 0.05f);view.setTranslationY((random.nextFloat() - 0.5f) * view.getHeight() * 0.05f);}});animator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {super.onAnimationEnd(animation);explode(view, rect);}});animator.start();}private void explode(final View view, Rect rect) {final ExplosionAnimator animator = new ExplosionAnimator(this, Utils.createBitmapFromView(view), rect, mParticleFactory);explosionAnimators.add(animator);explosionAnimatorsMap.put(view, animator);animator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationStart(Animator animation) {//缩小,透明动画view.animate().setDuration(150).scaleX(0f).scaleY(0f).alpha(0f).start();}@Overridepublic void onAnimationEnd(Animator animation) {view.animate().alpha(1f).scaleX(1f).scaleY(1f).setDuration(150).start();//动画结束时从动画集中移除explosionAnimators.remove(animation);explosionAnimatorsMap.remove(view);animation = null;}});animator.start();}/*** 给Activity加上全屏覆盖的ExplosionField*/private void attach2Activity(Activity activity) {ViewGroup rootView = (ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT);ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);rootView.addView(this, lp);}/*** 希望谁有破碎效果,就给谁加Listener** @param view 可以是ViewGroup*/public void addListener(View view) {if (view instanceof ViewGroup) {ViewGroup viewGroup = (ViewGroup) view;int count = viewGroup.getChildCount();for (int i = 0; i < count; i++) {addListener(viewGroup.getChildAt(i));}} else {view.setClickable(true);view.setOnClickListener(getOnClickListener());}}private OnClickListener getOnClickListener() {if (null == onClickListener) {onClickListener = new OnClickListener() {@Overridepublic void onClick(View v) {ExplosionSite.this.explode(v);}};}return onClickListener;}
}

总结:总体来说实现很简单,就是根据工厂类,生成粒子数组。
而其实质是一个ValueAnimator,在一定时间内,从0数到1。
然后提供了一个draw()方法,方法里面调用了每个粒子的advance()方法,并且传入了当前数到的数字。
advance()方法里,其实调用了draw()方法和caculate()方法。

上面的实现,其实是一个固定的流程,添加了爆炸场地以后,我们就开始从0数到1,在这个过程中,粒子会根据当前时间,绘制自己的位置,所以粒子的位置,其实是它自己决定的,和流程无关。
也就是说,我们只要用不同的算法,绘制粒子的位置即可,实现了流程和粒子运动的分离。
所以除了提供的六种爆炸特效之外,只要遵循这个原则,就能生成更多的粒子爆炸特效。

有了需求才有了功能,有了想法才有了创作,你的反馈会是使我进步的最大动力。
觉得还不够方便?还想要什么功能?告诉我!欢迎反馈,欢迎Star。源码入口:GitHub项目地址

Android粒子爆炸特效[可用于任意控件]相关推荐

  1. android 粒子爆炸特效

    先上图: 这是一个高级UI特效,是个动画. 完成这个动画只要3步: 1.控件完成振动效果动画. 2.控件振动动画完成后消失,然后将控件转换成Bitmap. 3.Bitmap完成粒子爆炸特效. 其实完成 ...

  2. Android 粒子爆炸效果,可以给任意 view 添加该效果

    ViewExplosion 项目地址:835127729/ViewExplosion 简介:Android 粒子爆炸效果,可以给任意 view 添加该效果 更多:作者   提 Bug   官网    ...

  3. Android UI - 粒子爆炸特效

    Android UI - 粒子爆炸特效 效果 实现 分析 关键代码 源码 效果 实现 分析 首先动画效果需要在一个位于顶层的view上绘制,目的是不被其他控件遮挡. 添加点击事件,触发后给控件加一个抖 ...

  4. Android制作粒子爆炸特效

    简介 最近在闲逛的时候,发现了一款粒子爆炸特效的控件,觉得比较有意思,效果也不错. 但是代码不好扩展,也就是说如果要提供不同的爆炸效果,需要修改的地方比较多.于是我对源代码进行了一些重构,将爆炸流程和 ...

  5. android 按键双击,实现Android监控任意控件或按键双击事件方法

    为了实现对Android任意控件和按键进行双击事件的监听,所以写了一个可以在代码中任意移植的解决方法. 一.解决思路 为了实现双击事件的监听,首先需要一个线程来执行两次点击事件的判断,决定是否属于一次 ...

  6. MOGRT 金色粒子爆炸特效logo展示pr片头模板mogrt

    这是一个PR动态图形模板Mogrt,金色粒子爆炸特效logo展示PR片头模板mogrt.具有粒子效果的组合,这些效果结合在一起以显示和增强您的媒体. 此模板包含 1 个logo占位符和 1 个可编辑文 ...

  7. android 固定底部 布局_Android系统列表控件

    在android系统控件中,有多个控件可以展示列表数据. 一.ListView 该组件是android中最常用的一个UI组件,用于实现在屏幕上显示多个内容,以便于我们用手指进行滑动. ListView ...

  8. android listview添加数据_Android系统列表控件

    在android系统控件中,有多个控件可以展示列表数据. 一.ListView 该组件是android中最常用的一个UI组件,用于实现在屏幕上显示多个内容,以便于我们用手指进行滑动. ListView ...

  9. android自定义控件不显示,解决Android Studio Design界面不显示layout控件的问题

    Android Studio更新到3.1.3后,发现拖到Design中的控件在预览界面中不显示: 解决办法: 在Styles.xml中的parent="..."中的Theme前添加 ...

最新文章

  1. 解决Minimum supported Gradle version is 3.3. Current version is 2.14.1问题
  2. 一年一度程序员“补课”季来袭,618 背后技术大公开!
  3. 常用的Firefox浏览器插件、Chrome浏览器插件收藏
  4. 【数学建模】图论模型-dijkstra算法(最优化)
  5. python读excel 包含格式_python里读写excel等数据文件的几种常用方式
  6. Raft当初为什么会被命名为Raft?
  7. cf375D. Tree and Queries
  8. 春招我借这份PDF的复习思路,论程序员成长的正确姿势
  9. Codeforces Round #496 (Div. 3 ) E1. Median on Segments (Permutations Edition)(中位数计数)
  10. JavaScript 函数定义+内置函数使用+array对象+object类型
  11. flstudio插件找不到_【干货】音频插件完全指引手册
  12. 内容主题windows下简单的vbscript自动发送邮件--带附件
  13. 事务学习总结(1)——事务的基本概念
  14. python表单验证_python表单验证封装
  15. php导入json文件_php读取json文件的实例(本地与远程),笔记
  16. Html学习手册(W3CSchool.chm)
  17. linux驱动编译成kext,Hackintosh:制作AppleALC以驱动原生AppleHDA
  18. 菩提心的修法-菩提心的修法
  19. 示波器的主要功能 示波器作用介绍
  20. php站长统计,如何巧妙去除隐藏“站长统计”文字链接?

热门文章

  1. Jenkins不同job之间传递参数
  2. tomcat下如何才能运行shtml文件?
  3. MediaPlayer的错误修复
  4. ASP.NET多附件上传和附件编辑的实现
  5. 数据源改变后,BarChart组件的运动效果.
  6. 谷歌紧急修复已遭在野利用的0day
  7. 2022,虎年大吉!
  8. NAME:WRECK 漏洞影响近亿台物联网设备
  9. 今天是个特殊的日子,养活我的Java爸爸诞生,发送一波福利!
  10. activeMQ 问题