咻一咻 android代码,Android自定义View实现支付宝咻一咻效果

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

ffe9f7adbc8659e0abe15127c3b9dee8.gif

实现思路挺简单:

画一个半透明的圆

实现两种动画效果,点击时扩散和不点击时扩散回收

使用线程的方式将上面两步结合起来

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

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,作用是用来标记扩散动画是否完成

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

点击时扩散动画

android:duration="1000"

android:propertyName="scaleY"

android:valueFrom="1.0"

android:valueTo="1.8"

android:valueType="floatType" />

android:duration="1000"

android:propertyName="scaleX"

android:valueFrom="1.0"

android:valueTo="1.8"

android:valueType="floatType" />

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

不点击时扩散回收动画

android:ordering="together">

android:duration="1000"

android:propertyName="scaleX"

android:valueFrom="1.0"

android:valueTo="1.2"

android:valueType="floatType" />

android:duration="1000"

android:propertyName="scaleY"

android:valueFrom="1.0"

android:valueTo="1.2"

android:valueType="floatType" />

android:duration="1000"

android:propertyName="scaleX"

android:startOffset="1000"

android:valueFrom="1.2"

android:valueTo="1.0"

android:valueType="floatType" />

android:duration="1000"

android:propertyName="scaleY"

android:startOffset="1000"

android:valueFrom="1.2"

android:valueTo="1.0"

android:valueType="floatType" />

和上个动画类似,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来说更加流畅,该方式大部分参考别人博客上的代码来实现,但是如果仅仅只是就拿来用不总结是不会成为自己的知识的,因此有了这篇博客。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值