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

Gella ·
更新时间:2024-11-13
· 607 次阅读

本篇文章介绍自定义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 自定义view仿支付宝咻一咻功能Android中RecyclerView布局代替GridView实现类似支付宝的界面Android波纹扩散效果之仿支付宝咻一咻功能实现波纹扩散特效Android app第三方支付宝支付接入教程Android支付宝支付封装代码Android支付宝和微信支付集成Android开发之实现GridView支付宝九宫格Android仿支付宝支付从底部弹窗效果Android支付宝支付设计开发支付宝咻一咻怎么用 Android帮你实现咻一咻



view 咻一咻 支付宝 Android

需要 登录 后方可回复, 如果你还没有账号请 注册新账号