Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android實現支付寶咻一咻的幾種思路方法

android實現支付寶咻一咻的幾種思路方法

編輯:關於Android編程

支付寶咻一咻在過年的時候很火熱。那麼咻一咻具體有哪些實現方式呢?下面我們將一一介紹這幾種思路的實現過程。

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>

其效果圖如下:

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved