软件编程
位置:首页>> 软件编程>> Android编程>> 支付宝咻一咻怎么用 Android帮你实现咻一咻

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

作者:Git_Android  发布时间:2023-01-31 03:34:09 

标签: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>

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com