支付宝咻一咻在过年的时候很火热。那么咻一咻具体有哪些实现方式呢?下面我们将一一介绍这几种思路的实现过程。
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,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,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,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(),circlePaint);// 画线 } } } canvas.drawBitmap(imageBit,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,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};//半径扩大速度。这里为匀速 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实现环形填充渐变。你也许会觉得,你看支付宝咻一咻圆圈d开的时候内圈有波纹也像外d开,其实那就是环形渐变,当你圆圈变大后,其渐变的范围也就变大了,自然你看到有颜色周围扩散的迹象。
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,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,color.RED); int[] mcolors = new int[] { color.transparent,color.RED }; float[] mpositions = new float[] { 0f,0.1f }; Shader shader=new RadialGradIEnt(screenWIDth / 2,wIDth / 2 + 10,Shader.TileMode.MIRROR); paint.setShader(shader); canvas.drawCircle(screenWIDth / 2,(screenHeight - statusHeight) / 2,paint); invalIDate(); } @OverrIDe protected voID onDraw(Canvas canvas) { canvas.drawBitmap(bitmap,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,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实现支付宝咻一咻的几种思路方法全部内容,希望文章能够帮你解决android实现支付宝咻一咻的几种思路方法所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)