当前位置: 移动技术网 > IT编程>移动开发>Android > android实现支付宝咻一咻的几种思路方法

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

2019年07月24日  | 移动技术网IT编程  | 我要评论

从零开始全集,少妇被骗260万,江西人

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

1.自定义view实现咻一咻

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

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

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

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

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

public class xiuyixiuview extends view {
  /***
   * 中心图片画笔
   */
  private paint paint;
  /***
   * 水波圆圈画笔
   */
  private paint circlepaint;
  /***
   * 用bitmap创建画布
   */
  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;

/**
 * created by liyuanjing on 2016/2/3.
 */
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>

其效果图如下:

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网