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

作者:鲁提辖_Ga 时间:2022-08-06 11:02:14 

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

Android自定义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实现支付宝咻一咻的几种思路方法

标签:Android,支付宝
0
投稿

猜你喜欢

  • Quarkus中ConfigSourceInterceptor的加密配置实现

    2021-10-08 10:47:14
  • C#实现获取不同对象中名称相同属性的方法

    2021-11-04 19:26:32
  • Android开发之实现GridView支付宝九宫格

    2023-01-26 15:26:16
  • 解析Android获取系统cpu信息,内存,版本,电量等信息的方法详解

    2023-11-20 10:50:15
  • SpringBoot集成cache缓存的实现

    2023-11-27 16:37:39
  • C#程序(含多个Dll)合并成一个Exe的简单方法

    2023-04-09 15:55:08
  • android连接wifi时获取广播地址代码

    2022-11-20 13:08:32
  • C++ OpenCV单峰三角阈值法Thresh_Unimodal详解

    2022-06-09 14:36:46
  •  Java SE 面向对象编程的3个常用接口

    2023-01-14 06:42:32
  • 详解使用SSM实现简单工作流系统之实现篇

    2021-10-21 07:49:23
  • IntelliJ IDEA中properties文件显示乱码问题的解决办法

    2021-09-08 04:59:03
  • java中MultipartFile互转File的方法

    2022-12-14 16:52:09
  • JAVA NIO实现简单聊天室功能

    2023-05-01 10:32:49
  • Android RippleDrawable 水波纹/涟漪效果的实现

    2022-05-24 23:12:37
  • eclipse的web项目实现Javaweb购物车的方法

    2023-07-28 15:55:53
  • SpringMVC的注解@RequestMapping属性及使用

    2022-12-31 02:03:00
  • Springboot整合MongoDB进行CRUD操作的两种方式(实例代码详解)

    2021-12-16 18:29:04
  • 学习Java的Date、Calendar日期操作

    2023-09-04 22:26:38
  • Android获取分享应用列表详解及实例

    2023-11-17 05:47:47
  • 浅谈C#六大设计原则

    2023-05-02 16:29:58
  • asp之家 软件编程 m.aspxhome.com