首页 > 系统 > Android > 正文

Android自定义View实现支付宝咻一咻效果

2019-12-12 03:42:05
字体:
来源:转载
供稿:网友

本篇文章介绍自定义View配合属性动画来实现如下的效果

实现思路挺简单:

  • 画一个半透明的圆
  • 实现两种动画效果,点击时扩散和不点击时扩散回收
  • 使用线程的方式将上面两步结合起来

首先看下画半透明圆的部分

public class ClickCircleView extends View { private Bitmap bitmap; private Paint paint; private Canvas canvas; private boolean isSpreadFlag = false;//标记是否发射完成 public boolean isSpreadFlag() {  return isSpreadFlag; } public void setIsSpreadFlag(boolean isSpreadFlag) {  this.isSpreadFlag = isSpreadFlag; } public ClickCircleView(Context context, int width, int height, int screenWidth, int screenHeight) {  super(context);  bitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888); // 设置位图的宽高  canvas = new Canvas();  canvas.setBitmap(bitmap);  paint = new Paint(Paint.DITHER_FLAG);  paint.setAntiAlias(true);  paint.setColor(Color.WHITE);  paint.setStyle(Paint.Style.FILL);  paint.setAlpha(50);  canvas.drawCircle(screenWidth / 2, screenHeight / 2, width / 2 + 10, paint);  invalidate(); } @Override protected void onDraw(Canvas canvas) {  canvas.drawBitmap(bitmap, 0, 0, null); }}

可以看到相关的属性都是设置在画笔上,然后直接调用画布的drawCircle()方法画出一个半透明的圆,最后调用invalidate()方法刷新View
一定要重写父类的onDraw()方法,否则自定义View不能生效
我们设置了一个标志位isSpreadFlag,作用是用来标记扩散动画是否完成

然后我们来实现两个动画效果

点击时扩散动画

<set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator  android:duration="1000"  android:propertyName="scaleY"  android:valueFrom="1.0"  android:valueTo="1.8"  android:valueType="floatType" /> <objectAnimator  android:duration="1000"  android:propertyName="scaleX"  android:valueFrom="1.0"  android:valueTo="1.8"  android:valueType="floatType" /></set>

很简单,就是改变scale值,增大到1.8倍

不点击时扩散回收动画

<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together"> <objectAnimator  android:duration="1000"  android:propertyName="scaleX"  android:valueFrom="1.0"  android:valueTo="1.2"  android:valueType="floatType" /> <objectAnimator  android:duration="1000"  android:propertyName="scaleY"  android:valueFrom="1.0"  android:valueTo="1.2"  android:valueType="floatType" /> <objectAnimator  android:duration="1000"  android:propertyName="scaleX"  android:startOffset="1000"  android:valueFrom="1.2"  android:valueTo="1.0"  android:valueType="floatType" /> <objectAnimator  android:duration="1000"  android:propertyName="scaleY"  android:startOffset="1000"  android:valueFrom="1.2"  android:valueTo="1.0"  android:valueType="floatType" /></set>

和上个动画类似,startOffset参数可以用来控制Animation的运行顺序,比如Android:startOffset=”1000”表示设置该属性的动画延迟1秒执行

然后就是用线程来执行动画和逻辑的部分了

不点击时的动画部分

mXiuyixiuButton.post(new Runnable() {   @Override   public void run() {    clickCircleView = new ClickCircleView(CustomView1.this, mXiuyixiuButton.getWidth()      , mXiuyixiuButton.getHeight(), mXiuyixiuLayout.getMeasuredWidth(),      mXiuyixiuLayout.getMeasuredHeight());    clickCircleView.setVisibility(View.VISIBLE);    mXiuyixiuLayout.addView(clickCircleView);    mXiuyixiuLayout.postInvalidate();    // 加载动画    final Animator anim = AnimatorInflater.loadAnimator(CustomView1.this,      R.animator.circle_scale_animator);    anim.addListener(new AnimatorListenerAdapter() {     @Override     public void onAnimationEnd(Animator animation) {      if (anim != null) {       anim.start();//循环执行动画      }     }    });    anim.setTarget(clickCircleView);    anim.start();   }  });

初始化好clickCircleView之后将这个view加入父布局中,然后加载动画并设置循环执行,最后使用postInvalidate()在子线程中刷新view

点击时的动画部分

mXiuyixiuButton.setOnClickListener(new View.OnClickListener() {   @Override   public void onClick(View v) {    clickCircleView.setVisibility(View.GONE);//发射圆圈,即将循环动画View隐藏    final ClickCircleView item = new ClickCircleView(CustomView1.this, mXiuyixiuButton.getWidth()      , mXiuyixiuButton.getHeight(), mXiuyixiuLayout.getWidth(),      mXiuyixiuLayout.getHeight());    Animator spreadAnim = AnimatorInflater.loadAnimator(CustomView1.this,      R.animator.circle_spread_animator);    spreadAnim.addListener(new AnimatorListenerAdapter() {     @Override     public void onAnimationEnd(Animator animation) {      item.setIsSpreadFlag(true);//动画执行完成,标记一下     }    });    spreadAnim.setTarget(item);    spreadAnim.start();    clickCircleViewList.add(item);    mXiuyixiuLayout.addView(item);    mXiuyixiuLayout.invalidate();    handler.post(circleViewRunnable);   }  });


隐藏不点击动画,初始化好ClickCircleView后将该view加入List中并添加到父布局中,然后加载动画并在动画结束时添加isSpreadFlag标记,最后调用invalidate()方法刷新view并开启线程

线程部分

private Runnable circleViewRunnable = new Runnable() {  public void run() {   for (int i = 0; i < clickCircleViewList.size(); i++) {    if (clickCircleViewList.get(i).isSpreadFlag()) {     mXiuyixiuLayout.removeView(clickCircleViewList.get(i));     clickCircleViewList.remove(i);     mXiuyixiuLayout.postInvalidate();    }   }   if (clickCircleViewList.size() <= 0) {    clickCircleView.setVisibility(View.VISIBLE);   }   handler.postDelayed(this, 100);  } };

遍历list,将有isSpreadFlag标记的view从list和父布局中移除并刷新view,最后判断list如果为空的话将不点击时的动画显示出来

最后记得在onDestroy()里移除线程

@Override protected void onDestroy() {  super.onDestroy();  handler.removeCallbacks(circleViewRunnable); }

使用自定义View配合属性动画来实现该效果耦合性较高,只是这种方式相比完全使用自定义View来说更加流畅,该方式大部分参考别人博客上的代码来实现,但是如果仅仅只是就拿来用不总结是不会成为自己的知识的,因此有了这篇博客。

参考: android实现支付宝咻一咻的几种思路方法

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表