我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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

支付宝咻一咻在过年的时候很火热。那么咻一咻具体有哪些实现方式呢?下面我们将一一介绍这几种思路的实现过程。

1.自定义View实现咻一咻

那么这种实现方法需要掌握Canvas以及Paint几乎所有的方法。其对程序员的专业知识要求极高。

用该种方式实现的优点有:

㈠这种是最复杂的实现方法,但其兼容性最高,其支持Android的所有设备。

㈡其对内存要求不大,几乎不占用任何内存。

下面我们来看看是怎样实现其效果的:


public class XiuYiXiuView extends View {
  
  private Paint paint;
  
  private Paint circlePaint;
  
  private Bitmap bitmap;
  
  private Bitmap imageBit;
  
  private Canvas canvas;
  
  private int screenWidth;
  
  private int screenHeight;
  
  private Point pointLeftTop;
  
  private Point pointRightBottom;
  
  private List<LYJCircle> lyjCircleList;
  
  private boolean isSpread=false;
  
  private LYJCircle defaultCircle;
  public XiuYiXiuView(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.lyjCircleList=new ArrayList<>();
    screenWidth=LYJUtils.getScreenWidth((Activity) context);
    screenHeight=LYJUtils.getScreenHeight((Activity) 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);
    circlePaint=new Paint(Paint.DITHER_FLAG);
    circlePaint.setAntiAlias(true);
    imageBit= BitmapFactory.decodeResource(getResources(), R.drawable.bwa_homepage_yuyin);
    pointLeftTop=new Point((screenWidth/2)-(imageBit.getWidth()/2),(screenHeight/2)-(imageBit.getHeight()/2));
    pointRightBottom=new Point(pointLeftTop.x+imageBit.getWidth(),pointLeftTop.y+imageBit.getHeight());
    canvas.drawBitmap(imageBit,pointLeftTop.x,pointLeftTop.y,paint);
    //取图片上的颜色
    Palette.generateAsync(imageBit, new Palette.PaletteAsyncListener() {
      @Override
      public void onGenerated(Palette palette) {
        Palette.Swatch swatch1 = palette.getVibrantSwatch(); //充满活力的色板
        circlePaint.setColor(swatch1.getRgb());
        circlePaint.setStyle(Paint.Style.STROKE);
        circlePaint.setStrokeWidth(10);
        circlePaint.setAlpha(100);
        paint.setShadowLayer(15, 0, 0, swatch1.getRgb());//设置阴影效果
        int[] mColors = new int[] {//渲染颜色
            Color.TRANSPARENT,swatch1.getRgb()
        };
        //范围,这里可以微调,实现你想要的渐变
        float[] mPositions = new float[] {
            0f, 0.1f
        };
        Shader shader=new RadialGradient(screenWidth / 2,screenHeight / 2,imageBit.getWidth() / 2 + 10,mColors, mPositions,
            Shader.TileMode.MIRROR);
        circlePaint.setShader(shader);
        defaultCircle=new LYJCircle(screenWidth / 2, screenHeight / 2, imageBit.getWidth() / 2 + 10);
        clearScreenAndDrawList();
        Message message = handler.obtainMessage(1);
        handler.sendMessageDelayed(message, 1000); //发送message
      }
    });
  }
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()){
      case MotionEvent.ACTION_DOWN:
        break;
      case MotionEvent.ACTION_MOVE:
        break;
      case MotionEvent.ACTION_UP:
        isSpread=true;//是否按下图片
        lyjCircleList.add(new LYJCircle(screenWidth / 2, screenHeight / 2, imageBit.getWidth() / 2 + 10));
        clearScreenAndDrawList();
        invalidate();
        break;
      default:
        break;
    }
    return true;
  }
  private Handler handler = new Handler(){
    public void handleMessage(Message msg){
      switch (msg.what) {
        case 1:
          //定时更新界面
          clearScreenAndDrawList();
          invalidate();
          Message message = handler.obtainMessage(1);
          handler.sendMessageDelayed(message, 200);
      }
      super.handleMessage(msg);
    }
  };
  
  private void clearScreenAndDrawList() {
    canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
    //判断是否按下图片,并且外圈执行完成没有。
    if(!isSpread){
        circlePaint.setMaskFilter(null);
        canvas.drawCircle(defaultCircle.getRoundX(), defaultCircle.getRoundY(),defaultCircle.getRadiuLoop(), circlePaint);// 画线
    }else{
      for (LYJCircle lyjCircle : lyjCircleList) {
        if(lyjCircle.getSpreadRadiu()==0){
        }else if(lyjCircle.getSpreadRadiu()>(lyjCircle.getRadiu()+99)){
          //如果圆圈扩散半径大于图片半径+99,那么设置边缘模糊,也就是淡出的效果
          circlePaint.setMaskFilter(new BlurMaskFilter(5, BlurMaskFilter.Blur.OUTER));
          canvas.drawCircle(lyjCircle.getRoundX(), lyjCircle.getRoundY(),lyjCircle.getSpreadRadiu(), circlePaint);// 画线
        }else{
          //不是则按正常的环形渲染来
          circlePaint.setMaskFilter(null);
          canvas.drawCircle(lyjCircle.getRoundX(), lyjCircle.getRoundY(),lyjCircle.getSpreadRadiu(), circlePaint);// 画线
        }
      }
    }
    canvas.drawBitmap(imageBit,pointLeftTop.x,pointLeftTop.y,paint);
    //释放小时了的圆圈
    for(int i=0;i<lyjCircleList.size();i++){
      if(lyjCircleList.get(i).getSpreadRadiu()==0){
        lyjCircleList.remove(i);
      }
    }
    //如果没有点击图片发射出去的圆圈,那么就恢复默认缩放。
    if(lyjCircleList.size()<=0){
      isSpread=false;
    }
  }
  @Override
  protected void onDraw(Canvas canvas) {
    canvas.drawBitmap(bitmap, 0, 0, null);
  }
}

圆类:


package com.example.liyuanjing.model;

public class LYJCircle {
  private int roundX;//圆中心点X坐标
  private int roundY;//圆中心点Y坐标
  private int radiu;//圆半径
  private int currentRadiu;//当前radiu
  private int lastRadiu;//历史radiu
  private int spreadRadiu;//加速半径
  private int[] speed=new int[]{6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6};//半径扩大速度。这里为匀速
  private int speedLast=0;//记录历史值
  public LYJCircle(int roundX,int roundY,int radiu){
    this.roundX=roundX;
    this.roundY=roundY;
    this.radiu=radiu;
    this.spreadRadiu=radiu;
    this.currentRadiu=this.radiu;
    this.lastRadiu=this.currentRadiu;
  }
  //获取半径
  public int getRadiu() {
    return radiu;
  }
  public void setRadiu(int radiu) {
    this.radiu = radiu;
  }
  //获取加速半径
  public int getSpreadRadiu(){
    if(speedLast>=speed.length){
      return 0;
    }
    spreadRadiu+=speed[speedLast];
    ++speedLast;
    return spreadRadiu;
  }
  //获取循环缩放半径
  public int getRadiuLoop() {
    if(currentRadiu==lastRadiu){
      ++currentRadiu;
    }else if(currentRadiu>lastRadiu){
      if(currentRadiu>(radiu+20)){
        currentRadiu=19+radiu;
        lastRadiu=20+radiu;
      }else{
        lastRadiu=currentRadiu;
        currentRadiu+=5;
      }
    }else{
      if(currentRadiu<(radiu+9)){
        currentRadiu=10+radiu;
        lastRadiu=9+radiu;
      }else{
        lastRadiu=currentRadiu;
        currentRadiu-=5;
      }
    }
    return currentRadiu;
  }
  public int getRoundX() {
    return roundX;
  }
  public int getRoundY() {
    return roundY;
  }
}

看看其效果图:

你可以修改如下两个地方,会产生视觉上真真的波纹效果:

①支付宝的背景图片是淡红色,衬托了红色的波纹。当然了你也可以将画布设置为透明淡红色。

②其为填充圆圈渲染,不是我的边框渲染效果,你可以将circlePaint.setStyle(Paint.Style.STROKE);换成Paint.Style.FILL.然后,微调shader的mPositions实现环形填充渐变。你也许会觉得,你看支付宝咻一咻圆圈弹开的时候内圈有波纹也像外弹开,其实那就是环形渐变,当你圆圈变大后,其渐变的范围也就变大了,自然你看到有颜色周围扩散的迹象。

2.属性动画实现咻一咻

其要掌握的只是基本只需要属性动画,在加一点线程方面有关的知识而已。

下面我们看看其实现步骤:

㈠自定义View实现一个圆即可,代码如下:


public class LYJCircleView extends View {
  private Bitmap bitmap;
  private Paint paint;
  private Canvas canvas;
  private int screenWidth;
  private int screenHeight;
  private boolean isSpreadFlag=false;//标记是否发射完成
  public boolean isSpreadFlag() {
    return isSpreadFlag;
  }
  public void setIsSpreadFlag(boolean isSpreadFlag) {
    this.isSpreadFlag = isSpreadFlag;
  }
  public LYJCircleView(Context context,int width,int height,int statusHeight) {
    super(context);
    screenWidth= LYJUtils.getScreenWidth((Activity) context);
    screenHeight=LYJUtils.getScreenHeight((Activity) 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.RED);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(5);
    paint.setAlpha(100);
    paint.setShadowLayer(10, 0, 0, Color.RED);
    int[] mColors = new int[] {
        Color.TRANSPARENT,Color.RED
    };
    float[] mPositions = new float[] {
        0f, 0.1f
    };
    Shader shader=new RadialGradient(screenWidth / 2,screenHeight / 2,width / 2 + 10,mColors, mPositions,
        Shader.TileMode.MIRROR);
    paint.setShader(shader);
    canvas.drawCircle(screenWidth / 2, (screenHeight - statusHeight) / 2, width / 2 + 10, paint);
    invalidate();
  }
  @Override
  protected void onDraw(Canvas canvas) {
    canvas.drawBitmap(bitmap,0,0,null);
  }
}

代码与上面差不多,就不注释了。
㈡实现Activity即可


public class XiuYiXiuActivity extends AppCompatActivity {
  private ImageButton mImageButton;
  private LYJCircleView lyjCircleView;
  private RelativeLayout relativeLayout;
  private List<LYJCircleView> lyjCircleViewList;
  private int statusBarHeight;
  private Animator anim;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.xiuyixiu_activity_main);
    this.mImageButton=(ImageButton)findViewById(R.id.xiuyixiu_imagebutton);
    this.relativeLayout=(RelativeLayout)findViewById(R.id.xiuyixiu_relativelayout);
    this.lyjCircleViewList=new ArrayList<>();
    this.mImageButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        lyjCircleView.setVisibility(View.GONE);//发射圆圈,即将循环动画View隐藏
        final LYJCircleView item=new LYJCircleView(XiuYiXiuActivity.this, mImageButton.getWidth(), mImageButton.getHeight(), statusBarHeight);
        Animator spreadAnim = AnimatorInflater.loadAnimator(XiuYiXiuActivity.this, R.animator.circle_spread_animator);
        spreadAnim.addListener(new Animator.AnimatorListener() {
          @Override
          public void onAnimationStart(Animator animation) {
          }
          @Override
          public void onAnimationEnd(Animator animation) {
            item.setIsSpreadFlag(true);//动画执行完成,标记一下
          }
          @Override
          public void onAnimationCancel(Animator animation) {
          }
          @Override
          public void onAnimationRepeat(Animator animation) {
          }
        });
        spreadAnim.setTarget(item);
        spreadAnim.start();
        lyjCircleViewList.add(item);
        relativeLayout.addView(item);
        relativeLayout.invalidate();
        Message message = handler.obtainMessage(1);
        handler.sendMessageDelayed(message, 10); //发送message,定时释放LYJCircleView
      }
    });
  }
  private Handler handler = new Handler(){
    public void handleMessage(Message msg){
      switch (msg.what) {
        case 1:
          for(int i=0;i<lyjCircleViewList.size();i++){
            if(lyjCircleViewList.get(i).isSpreadFlag()){
              relativeLayout.removeView(lyjCircleViewList.get(i));
              lyjCircleViewList.remove(i);
              relativeLayout.invalidate();
            }
          }
          if(lyjCircleViewList.size()<=0){
            lyjCircleView.setVisibility(View.VISIBLE);
          }
          Message message = handler.obtainMessage(1);
          handler.sendMessageDelayed(message, 10);
      }
      super.handleMessage(msg);
    }
  };
  @Override
  public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    //获取状态栏高度
    Rect frame = new Rect();
    getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
    statusBarHeight = frame.top;
    this.mImageButton.post(new Runnable() {
      @Override
      public void run() {
        lyjCircleView = new LYJCircleView(XiuYiXiuActivity.this, mImageButton.getWidth(), mImageButton.getHeight(), statusBarHeight);
        relativeLayout.addView(lyjCircleView);
        relativeLayout.postInvalidate();
        // 加载动画
        anim = AnimatorInflater.loadAnimator(XiuYiXiuActivity.this, R.animator.circle_scale_animator);
        anim.addListener(new Animator.AnimatorListener() {
          @Override
          public void onAnimationStart(Animator animation) {
          }
          @Override
          public void onAnimationEnd(Animator animation) {
            anim.start();//循环执行动画
          }
          @Override
          public void onAnimationCancel(Animator animation) {
          }
          @Override
          public void onAnimationRepeat(Animator animation) {
          }
        });
        anim.setTarget(lyjCircleView);
        anim.start();
      }
    });
  }
}

㈢布局文件代码如下:


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/xiuyixiu_relativelayout"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <ImageButton
    android:id="@+id/xiuyixiu_imagebutton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:background="@drawable/bwa_homepage_yuyin"/>
</RelativeLayout>

当然上面两个实现方法,我都只设置圆边框,没有填充,你可以设置为填充后,在微调渐变值。

其属性动画文件circle_scale_animator.xml:


<?xml version="1.0" encoding="utf-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>
  <objectAnimator
    android:duration="1000"
    android:propertyName="scaleY"
    android:valueFrom="1.0"
    android:valueTo="1.2"
    android:valueType="floatType">
  </objectAnimator>
  <objectAnimator
    android:startOffset="1000"
    android:duration="1000"
    android:propertyName="scaleX"
    android:valueFrom="1.2"
    android:valueTo="1.0"
    android:valueType="floatType">
  </objectAnimator>
  <objectAnimator
    android:startOffset="1000"
    android:duration="1000"
    android:propertyName="scaleY"
    android:valueFrom="1.2"
    android:valueTo="1.0"
    android:valueType="floatType">
  </objectAnimator>
</set>

另一个circle_spread_animator.xml为:


<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
  <objectAnimator
    android:duration="1000"
    android:propertyName="scaleY"
    android:valueFrom="1.0"
    android:valueTo="2.0"
    android:valueType="floatType">
  </objectAnimator>
  <objectAnimator
    android:duration="1000"
    android:propertyName="scaleX"
    android:valueFrom="1.0"
    android:valueTo="2.0"
    android:valueType="floatType">
  </objectAnimator>
</set>

其效果图如下:

您可能感兴趣的文章:Android自定义ViewGroup实现绚丽的仿支付宝咻一咻雷达脉冲效果Android波纹扩散效果之仿支付宝咻一咻功能实现波纹扩散特效支付宝咻一咻怎么用 Android帮你实现咻一咻


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

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

支付宝咻一咻在过年的时候很火热。那么咻一咻具体有哪些实现方式呢?下面我们将一一介绍这几种思路的实现过程。1.自定义View实现咻一咻 那么这种实现方法需要掌握Canvas以及Paint几乎所有的方法。其对程序员的专业知识要求极高。 用该种方
2022-06-06

支付宝咻一咻怎么用 Android帮你实现咻一咻

对于之前最火的无外乎集五福了,而五福除了加十个好友获得外,最直接的途径就是支付宝的咻一咻了。那么咻一咻具体有哪些实现方式呢?下面我们将一一介绍这几种思路的实现过程。 1.自定义View实现咻一咻 那么这种实现方法需要掌握Canvas以及Pa
2022-06-06

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

本篇文章介绍自定义View配合属性动画来实现如下的效果实现思路挺简单:画一个半透明的圆实现两种动画效果,点击时扩散和不点击时扩散回收使用线程的方式将上面两步结合起来 首先看下画半透明圆的部分public class ClickCircleV
2022-06-06

Android自定义ViewGroup实现绚丽的仿支付宝咻一咻雷达脉冲效果

去年春节的时候支付宝推行的集福娃活动着实火的不能再火了,更给力的是春晚又可以全民参与咻一咻集福娃活动,集齐五福就可平分亿元大红包,只可惜没有敬业福……那时候在家没事写了个咻一咻插件,只要到了咻一咻的时间点插件就可以自动的点击咻一咻来咻红包,
2022-06-06

Android波纹扩散效果之仿支付宝咻一咻功能实现波纹扩散特效

今年春节晚会没看尽兴,被支付宝集福给添了一段插曲,朋友们都在那数定时间段不停的咻一咻,哇,我咻到一个敬业福,不可能的,哈哈。那么咻一咻功能基于程序代码是怎么实现的呢?下面编程网小编给大家分享本教程帮助大家学习Android波纹扩散效果之仿支
2022-06-06

在Android项目中实现一个底部支付弹窗的方法

在Android项目中实现一个底部支付弹窗的方法?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Android底部支付弹窗实现的效果:实现的思路:1.通过继承PopupWindo
2023-05-31

android编程实现类似于支付宝余额快速闪动效果的方法

本文实例讲述了android编程实现类似于支付宝余额快速闪动效果的方法。分享给大家供大家参考,具体如下: 效果如下: 此图片不会动,但实际上是会快速跳动的。 之前看到有支付宝的效果非常牛逼。就是进去看到余额呼噜噜的直接上蹿下跳到具体数字,效
2022-06-06

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录