支付宝咻一咻怎么用 Android帮你实现咻一咻
对于之前最火的无外乎集五福了,而五福除了加十个好友获得外,最直接的途径就是支付宝的咻一咻了。那么咻一咻具体有哪些实现方式呢?下面我们将一一介绍这几种思路的实现过程。
1.自定义View实现咻一咻
那么这种实现方法需要掌握Canvas以及Paint几乎所有的方法。其对程序员的专业知识要求极高。
用该种方式实现的优点有:
- ㈠这种是最复杂的实现方法,但其兼容性最高,其支持android的所有设备。
- ㈡其对内存要求不大,几乎不占用任何内存。
下面我们来看看是怎样实现其效果的:
publicclassXiuYiXiuViewextendsView{ /*** *中心图片画笔 */ privatePaintpaint; /*** *水波圆圈画笔 */ privatePaintcirclePaint; /*** *用bitmap创建画布 */ privateBitmapbitmap; /*** *中心图片 */ privateBitmapimageBit; /*** *画布 */ privateCanvascanvas; /*** *屏幕的宽 */ privateintscreenWidth; /*** *屏幕的高 */ privateintscreenHeight; /*** *图片右上角坐标 */ privatePointpointLeftTop; /*** *图片右下角坐标 */ privatePointpointRightBottom; /*** *记录圆圈 */ privateList<LYJCircle>lyjCircleList; /*** *标记是否按下按钮,并且源泉是否扩散消失 */ privatebooleanisSpread=false; /*** *默认没有按动时候的圆圈 */ privateLYJCircledefaultCircle; publicXiuYiXiuView(Contextcontext,AttributeSetattrs){ super(context,attrs); this.lyjCircleList=newArrayList<>(); screenWidth=LYJUtils.getScreenWidth((Activity)context); screenHeight=LYJUtils.getScreenHeight((Activity)context); bitmap=Bitmap.createBitmap(screenWidth,screenHeight,Bitmap.Config.ARGB_8888);//设置位图的宽高 canvas=newCanvas(); canvas.setBitmap(bitmap); paint=newPaint(Paint.DITHER_FLAG); paint.setAntiAlias(true); circlePaint=newPaint(Paint.DITHER_FLAG); circlePaint.setAntiAlias(true); imageBit=BitmapFactory.decodeResource(getResources(),R.drawable.bwa_homepage_yuyin); pointLeftTop=newPoint((screenWidth/2)-(imageBit.getWidth()/2),(screenHeight/2)-(imageBit.getHeight()/2)); pointRightBottom=newPoint(pointLeftTop.x+imageBit.getWidth(),pointLeftTop.y+imageBit.getHeight()); canvas.drawBitmap(imageBit,pointLeftTop.x,pointLeftTop.y,paint); //取图片上的颜色 Palette.generateAsync(imageBit,newPalette.PaletteAsyncListener(){ @Override publicvoidonGenerated(Palettepalette){ Palette.Swatchswatch1=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=newint[]{//渲染颜色 Color.TRANSPARENT,swatch1.getRgb() }; //范围,这里可以微调,实现你想要的渐变 float[]mPositions=newfloat[]{ 0f,0.1f }; Shadershader=newRadialGradient(screenWidth/2,screenHeight/2,imageBit.getWidth()/2+10,mColors,mPositions, Shader.TileMode.MIRROR); circlePaint.setShader(shader); defaultCircle=newLYJCircle(screenWidth/2,screenHeight/2,imageBit.getWidth()/2+10); clearScreenAndDrawList(); Messagemessage=handler.obtainMessage(1); handler.sendMessageDelayed(message,1000);//发送message } }); } @Override publicbooleanonTouchEvent(MotionEventevent){ switch(event.getAction()){ caseMotionEvent.ACTION_DOWN: break; caseMotionEvent.ACTION_MOVE: break; caseMotionEvent.ACTION_UP: isSpread=true;//是否按下图片 lyjCircleList.add(newLYJCircle(screenWidth/2,screenHeight/2,imageBit.getWidth()/2+10)); clearScreenAndDrawList(); invalidate(); break; default: break; } returntrue; } privateHandlerhandler=newHandler(){ publicvoidhandleMessage(Messagemsg){ switch(msg.what){ case1: //定时更新界面 clearScreenAndDrawList(); invalidate(); Messagemessage=handler.obtainMessage(1); handler.sendMessageDelayed(message,200); } super.handleMessage(msg); } }; /** *清掉屏幕上所有的圆圈,然后画出集合里面的圆圈 */ privatevoidclearScreenAndDrawList(){ canvas.drawColor(Color.TRANSPARENT,PorterDuff.Mode.CLEAR); //判断是否按下图片,并且外圈执行完成没有。 if(!isSpread){ circlePaint.setMaskFilter(null); canvas.drawCircle(defaultCircle.getRoundX(),defaultCircle.getRoundY(),defaultCircle.getRadiuLoop(),circlePaint);//画线 }else{ for(LYJCirclelyjCircle:lyjCircleList){ if(lyjCircle.getSpreadRadiu()==0){ }elseif(lyjCircle.getSpreadRadiu()>(lyjCircle.getRadiu()+99)){ //如果圆圈扩散半径大于图片半径+99,那么设置边缘模糊,也就是淡出的效果 circlePaint.setMaskFilter(newBlurMaskFilter(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(inti=0;i<lyjCircleList.size();i++){ if(lyjCircleList.get(i).getSpreadRadiu()==0){ lyjCircleList.remove(i); } } //如果没有点击图片发射出去的圆圈,那么就恢复默认缩放。 if(lyjCircleList.size()<=0){ isSpread=false; } } @Override protectedvoidonDraw(Canvascanvas){ canvas.drawBitmap(bitmap,0,0,null); } }
圆类:
packagecom.example.liyuanjing.model; /** *Createdbyliyuanjingon2016/2/3. */ publicclassLYJCircle{ privateintroundX;//圆中心点X坐标 privateintroundY;//圆中心点Y坐标 privateintradiu;//圆半径 privateintcurrentRadiu;//当前radiu privateintlastRadiu;//历史radiu privateintspreadRadiu;//加速半径 privateint[]speed=newint[]{6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6};//半径扩大速度。这里为匀速 privateintspeedLast=0;//记录历史值 publicLYJCircle(introundX,introundY,intradiu){ this.roundX=roundX; this.roundY=roundY; this.radiu=radiu; this.spreadRadiu=radiu; this.currentRadiu=this.radiu; this.lastRadiu=this.currentRadiu; } //获取半径 publicintgetRadiu(){ returnradiu; } publicvoidsetRadiu(intradiu){ this.radiu=radiu; } //获取加速半径 publicintgetSpreadRadiu(){ if(speedLast>=speed.length){ return0; } spreadRadiu+=speed[speedLast]; ++speedLast; returnspreadRadiu; } //获取循环缩放半径 publicintgetRadiuLoop(){ if(currentRadiu==lastRadiu){ ++currentRadiu; }elseif(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; } } returncurrentRadiu; } publicintgetRoundX(){ returnroundX; } publicintgetRoundY(){ returnroundY; } }
你可以修改如下两个地方,会产生视觉上真真的波纹效果:
①支付宝的背景图片是淡红色,衬托了红色的波纹。当然了你也可以将画布设置为透明淡红色。
②其为填充圆圈渲染,不是我的边框渲染效果,你可以将circlePaint.setStyle(Paint.Style.STROKE);换成Paint.Style.FILL.然后,微调shader的mPositions实现环形填充渐变。你也许会觉得,你看支付宝咻一咻圆圈弹开的时候内圈有波纹也像外弹开,其实那就是环形渐变,当你圆圈变大后,其渐变的范围也就变大了,自然你看到有颜色周围扩散的迹象。
2.属性动画实现咻一咻
其要掌握的只是基本只需要属性动画,在加一点线程方面有关的知识而已。
下面我们看看其实现步骤:
㈠自定义View实现一个圆即可,代码如下:
publicclassLYJCircleViewextendsView{ privateBitmapbitmap; privatePaintpaint; privateCanvascanvas; privateintscreenWidth; privateintscreenHeight; privatebooleanisSpreadFlag=false;//标记是否发射完成 publicbooleanisSpreadFlag(){ returnisSpreadFlag; } publicvoidsetIsSpreadFlag(booleanisSpreadFlag){ this.isSpreadFlag=isSpreadFlag; } publicLYJCircleView(Contextcontext,intwidth,intheight,intstatusHeight){ super(context); screenWidth=LYJUtils.getScreenWidth((Activity)context); screenHeight=LYJUtils.getScreenHeight((Activity)context); bitmap=Bitmap.createBitmap(screenWidth,screenHeight,Bitmap.Config.ARGB_8888);//设置位图的宽高 canvas=newCanvas(); canvas.setBitmap(bitmap); paint=newPaint(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=newint[]{ Color.TRANSPARENT,Color.RED }; float[]mPositions=newfloat[]{ 0f,0.1f }; Shadershader=newRadialGradient(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 protectedvoidonDraw(Canvascanvas){ canvas.drawBitmap(bitmap,0,0,null); } }
代码与上面差不多,就不注释了。
㈡实现Activity即可
publicclassXiuYiXiuActivityextendsAppCompatActivity{ privateImageButtonmImageButton; privateLYJCircleViewlyjCircleView; privateRelativeLayoutrelativeLayout; privateList<LYJCircleView>lyjCircleViewList; privateintstatusBarHeight; privateAnimatoranim; @Override protectedvoidonCreate(BundlesavedInstanceState){ 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=newArrayList<>(); this.mImageButton.setOnClickListener(newView.OnClickListener(){ @Override publicvoidonClick(Viewv){ lyjCircleView.setVisibility(View.GONE);//发射圆圈,即将循环动画View隐藏 finalLYJCircleViewitem=newLYJCircleView(XiuYiXiuActivity.this,mImageButton.getWidth(),mImageButton.getHeight(),statusBarHeight); AnimatorspreadAnim=AnimatorInflater.loadAnimator(XiuYiXiuActivity.this,R.animator.circle_spread_animator); spreadAnim.addListener(newAnimator.AnimatorListener(){ @Override publicvoidonAnimationStart(Animatoranimation){ } @Override publicvoidonAnimationEnd(Animatoranimation){ item.setIsSpreadFlag(true);//动画执行完成,标记一下 } @Override publicvoidonAnimationCancel(Animatoranimation){ } @Override publicvoidonAnimationRepeat(Animatoranimation){ } }); spreadAnim.setTarget(item); spreadAnim.start(); lyjCircleViewList.add(item); relativeLayout.addView(item); relativeLayout.invalidate(); Messagemessage=handler.obtainMessage(1); handler.sendMessageDelayed(message,10);//发送message,定时释放LYJCircleView } }); } privateHandlerhandler=newHandler(){ publicvoidhandleMessage(Messagemsg){ switch(msg.what){ case1: for(inti=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); } Messagemessage=handler.obtainMessage(1); handler.sendMessageDelayed(message,10); } super.handleMessage(msg); } }; @Override publicvoidonWindowFocusChanged(booleanhasFocus){ super.onWindowFocusChanged(hasFocus); //获取状态栏高度 Rectframe=newRect(); getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); statusBarHeight=frame.top; this.mImageButton.post(newRunnable(){ @Override publicvoidrun(){ lyjCircleView=newLYJCircleView(XiuYiXiuActivity.this,mImageButton.getWidth(),mImageButton.getHeight(),statusBarHeight); relativeLayout.addView(lyjCircleView); relativeLayout.postInvalidate(); //加载动画 anim=AnimatorInflater.loadAnimator(XiuYiXiuActivity.this,R.animator.circle_scale_animator); anim.addListener(newAnimator.AnimatorListener(){ @Override publicvoidonAnimationStart(Animatoranimation){ } @Override publicvoidonAnimationEnd(Animatoranimation){ anim.start();//循环执行动画 } @Override publicvoidonAnimationCancel(Animatoranimation){ } @Override publicvoidonAnimationRepeat(Animatoranimation){ } }); anim.setTarget(lyjCircleView); anim.start(); } }); } }
㈢布局文件代码如下:
<?xmlversion="1.0"encoding="utf-8"?> <RelativeLayoutxmlns: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:
<?xmlversion="1.0"encoding="utf-8"?> <setxmlns: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为:
<?xmlversion="1.0"encoding="utf-8"?> <setxmlns: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>
以上就是本文的详细内容,希望对大家的学习有所帮助。