seo 发表于 2022-5-31 12:58:23

Android特效专辑(五)——自定义圆形头像和仿MIUI卸载动画—粒子爆炸

Android特效专辑(五)——自定义圆形头像和仿MIUI卸载动画—粒子爆炸

好的,各位亲爱的朋友,今天讲的特效还是比较炫的,首先,我们会讲一个自定义圆形的imageView,接着,我们会来实现粒子爆炸的特效,按照国际惯例,无图无真相的没这个效果也是模仿大神的,现在应用在了我的《Only》上

截图
好的,我们新建一个工程——AnimView,我们要用到的图片
https://s6.51cto.com/images/blog/202205/27182726_6290a78e6795224297.jpg?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=
一.自定义圆形头像——直接开写了,要实现的东西都在注释上了
1.编写自定义属性attr.xml

   
      
      
      
   
2.自定义View紧接着我们就可以编写这个类了
package com.lgl.animview;
/**
* 圆形头像
* Created by LGL on 2016/1/12.
*/
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.util.AttributeSet;
import android.widget.ImageView;
/**
* 圆形ImageView,可设置最多两个宽度不同且颜色不同的圆形边框。 设置颜色在xml布局文件中由自定义属性配置参数指定
*/
public class RoundImageView extends ImageView {
    private int mBorderThickness = 0;
    private Context mContext;
    private int defaultColor = 0xFFFFFFFF;
    // 如果只有其中一个有值,则只画一个圆形边框
    private int mBorderOutsideColor = 0;
    private int mBorderInsideColor = 0;
    // 控件默认长、宽
    private int defaultWidth = 0;
    private int defaultHeight = 0;
    public RoundImageView(Context context) {
      super(context);
      mContext = context;
    }
    public RoundImageView(Context context, AttributeSet attrs) {
      super(context, attrs);
      mContext = context;
      setCustomAttributes(attrs);
    }
    public RoundImageView(Context context, AttributeSet attrs, int defStyle) {
      super(context, attrs, defStyle);
      mContext = context;
      setCustomAttributes(attrs);
    }
    private void setCustomAttributes(AttributeSet attrs) {
      // 获取自定义的属性
      TypedArray a = mContext.obtainStyledAttributes(attrs,
                R.styleable.roundedimageview);
      mBorderThickness = a.getDimensionPixelSize(
                R.styleable.roundedimageview_border_thickness, 0);
      mBorderOutsideColor = a
                .getColor(R.styleable.roundedimageview_border_outside_color,
                        defaultColor);
      mBorderInsideColor = a.getColor(
                R.styleable.roundedimageview_border_inside_color, defaultColor);
    }
    @Override
    protected void onDraw(Canvas canvas) {
      Drawable drawable = getDrawable();
      if (drawable == null) {
            return;
      }
      if (getWidth() == 0 || getHeight() == 0) {
            return;
      }
      this.measure(0, 0);
      if (drawable.getClass() == NinePatchDrawable.class)
            return;
      Bitmap b = ((BitmapDrawable) drawable).getBitmap();
      Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);
      if (defaultWidth == 0) {
            defaultWidth = getWidth();
      }
      if (defaultHeight == 0) {
            defaultHeight = getHeight();
      }
      int radius = 0;
      if (mBorderInsideColor != defaultColor
                && mBorderOutsideColor != defaultColor) {// 定义画两个边框,分别为外圆边框和内圆边框
            radius = (defaultWidthbmpWidth) {// 高大于宽
            squareWidth = squareHeight = bmpWidth;
            x = 0;
            y = (bmpHeight - bmpWidth) / 2;
            // 截取正方形图片
            squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth,
                  squareHeight);
      } else if (bmpHeight 3.引用引用起来就比较简单了,我们首先来引入他的命名空间
xmlns:imagecontrol="http://schemas.android.com/apk/res-auto"然后我们直接写xml
好的,让我们运行下吧
https://s3.51cto.com/images/blog/202205/27182726_6290a78e82b4622059.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=
二.MUI卸载动画——粒子爆炸关于这个粒子特效,在开篇的时候已经展示了效果,那么我们接下来,要怎么做尼?
1.ParticleUtils用于粒子动画的单位转换
package com.lgl.animview;
import android.content.res.Resources;
/**
* 粒子动画
*/
public class ParticleUtils {
    /**
   * 密度
   */
    public static final float DENSITY = Resources.getSystem().getDisplayMetrics().density;
    public static int dp2px(int dp) {
      return Math.round(dp * DENSITY);
    }
}
2.Particle用于爆破效果的分子计算
package com.lgl.animview;
import java.util.Random;
import android.graphics.Point;
import android.graphics.Rect;
/**
* Created by lgl on 16/01/14. 爆破粒子
*/
public class Particle {
    public static final int PART_WH = 8; // 默认小球宽高
    // 原本的值(不可变)
    // float originCX;
    // float originCY;
    // float originRadius;
    // 实际的值(可变)
    float cx; // center x of circle
    float cy; // center y of circle
    float radius;
    int color;
    float alpha;
    static Random random = new Random();
    Rect mBound;
    public static Particle generateParticle(int color, Rect bound, Point point) {
      int row = point.y; // 行是高
      int column = point.x; // 列是宽
      Particle particle = new Particle();
      particle.mBound = bound;
      particle.color = color;
      particle.alpha = 1f;
      particle.radius = PART_WH;
      particle.cx = bound.left + PART_WH * column;
      particle.cy = bound.top + PART_WH * row;
      return particle;
    }
    public void advance(float factor) {
      cx = cx + factor * random.nextInt(mBound.width())
                * (random.nextFloat() - 0.5f);
      cy = cy + factor * random.nextInt(mBound.height() / 2);
      radius = radius - factor * random.nextInt(2);
      alpha = (1f - factor) * (1 + random.nextFloat());
    }
}
3.ExplosionAnimator属性动画,用于动画展示
package com.lgl.animview;
import android.animation.ValueAnimator;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.view.View;
/**
* Created by lgl on 16/01/14.
*/
public class ExplosionAnimator extends ValueAnimator {
    public static final int DEFAULT_DURATION = 1500;
    private Particle[][] mParticles;
    private Paint mPaint;
    private View mContainer;
    public ExplosionAnimator(View view, Bitmap bitmap, Rect bound) {
      mPaint = new Paint();
      mContainer = view;
      setFloatValues(0.0f, 1.0f);
      setDuration(DEFAULT_DURATION);
      mParticles = generateParticles(bitmap, bound);
    }
    private Particle[][] generateParticles(Bitmap bitmap, Rect bound) {
      int w = bound.width();
      int h = bound.height();
      int partW_Count = w / Particle.PART_WH; // 横向个数
      int partH_Count = h / Particle.PART_WH; // 竖向个数
      int bitmap_part_w = bitmap.getWidth() / partW_Count;
      int bitmap_part_h = bitmap.getHeight() / partH_Count;
      Particle[][] particles = new Particle;
      Point point = null;
      for (int row = 0; row 4.ExplosionField开始执行这个实例的动画了
package com.lgl.animview;
import java.util.ArrayList;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
/**
* Created by lgl on 16/01/14.
*/
public class ExplosionField extends View {
    private static final String TAG = "ExplosionField";
    private static final Canvas mCanvas = new Canvas();
    private ArrayList explosionAnimators;
    private OnClickListener onClickListener;
    public ExplosionField(Context context) {
      super(context);
      init();
    }
    public ExplosionField(Context context, AttributeSet attrs) {
      super(context, attrs);
      init();
    }
    private void init() {
      explosionAnimators = new ArrayList();
      attach2Activity((Activity) getContext());
    }
    @Override
    protected void onDraw(Canvas canvas) {
      super.onDraw(canvas);
      for (ExplosionAnimator animator : explosionAnimators) {
            animator.draw(canvas);
      }
    }
    /**
   * 爆破
   *
   * @param view
   *            使得该view爆破
   */
    public void explode(final View view) {
      Rect rect = new Rect();
      view.getGlobalVisibleRect(rect); // 得到view相对于整个屏幕的坐标
      rect.offset(0, -ParticleUtils.dp2px(25)); // 去掉状态栏高度
      final ExplosionAnimator animator = new ExplosionAnimator(this,
                createBitmapFromView(view), rect);
      explosionAnimators.add(animator);
      animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                view.animate().alpha(0f).setDuration(150).start();
            }
            @Override
            public void onAnimationEnd(Animator animation) {
                view.animate().alpha(1f).setDuration(150).start();
                // 动画结束时从动画集中移除
                explosionAnimators.remove(animation);
                animation = null;
            }
      });
      animator.start();
    }
    private Bitmap createBitmapFromView(View view) {
      /*
         * 为什么屏蔽以下代码段? 如果ImageView直接得到位图,那么当它设置背景(backgroud)时,不会读取到背景颜色
         */
      // if (view instanceof ImageView) {
      // Drawable drawable = ((ImageView)view).getDrawable();
      // if (drawable != null && drawable instanceof BitmapDrawable) {
      // return ((BitmapDrawable) drawable).getBitmap();
      // }
      // }
      // view.clearFocus(); //不同焦点状态显示的可能不同——(azz:不同就不同有什么关系?)
      Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),
                Bitmap.Config.ARGB_8888);
      if (bitmap != null) {
            synchronized (mCanvas) {
                mCanvas.setBitmap(bitmap);
                view.draw(mCanvas);
                mCanvas.setBitmap(null); // 清除引用
            }
      }
      return bitmap;
    }
    /**
   * 给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 5.MainActivity好的,一切准备好了之后我们就可以使用了
package com.lgl.animview;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
    // 实例化粒子动画
    private ExplosionField explosionField;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      explosionField = new ExplosionField(this);
      // 绑定哪个控件哪个控件就有效果,如果需要整个layout,只要绑定根布局的id即可
      explosionField.addListener(findViewById(R.id.iv_round));
    }
}
在xml中我们什么也不用做,好的,让我们来运行一下
https://s3.51cto.com/images/blog/202205/27182726_6290a78eac63364027.gif

               
               


            
               
      
      

https://www.yilongzhijia.cn/tupian/seo365t.jpg
页: [1]
查看完整版本: Android特效专辑(五)——自定义圆形头像和仿MIUI卸载动画—粒子爆炸