支付宝咻一咻怎么用 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>
以上就是本文的详细内容,希望对大家的学习有所帮助。