支付寶咻一咻怎么用 Android幫你實(shí)現(xiàn)咻一咻
對(duì)于之前最火的無(wú)外乎集五福了,而五福除了加十個(gè)好友獲得外,最直接的途徑就是支付寶的咻一咻了。那么咻一咻具體有哪些實(shí)現(xiàn)方式呢?下面我們將一一介紹這幾種思路的實(shí)現(xiàn)過(guò)程。
1.自定義View實(shí)現(xiàn)咻一咻
那么這種實(shí)現(xiàn)方法需要掌握Canvas以及Paint幾乎所有的方法。其對(duì)程序員的專業(yè)知識(shí)要求極高。
用該種方式實(shí)現(xiàn)的優(yōu)點(diǎn)有:
- ㈠這種是最復(fù)雜的實(shí)現(xiàn)方法,但其兼容性最高,其支持android的所有設(shè)備。
- ㈡其對(duì)內(nèi)存要求不大,幾乎不占用任何內(nèi)存。
下面我們來(lái)看看是怎樣實(shí)現(xiàn)其效果的:
public class XiuYiXiuView extends View { /*** * 中心圖片畫(huà)筆 */ private Paint paint; /*** * 水波圓圈畫(huà)筆 */ private Paint circlePaint; /*** * 用bitmap創(chuàng)建畫(huà)布 */ private Bitmap bitmap; /*** * 中心圖片 */ private Bitmap imageBit; /*** * 畫(huà)布 */ private Canvas canvas; /*** * 屏幕的寬 */ private int screenWidth; /*** * 屏幕的高 */ private int screenHeight; /*** * 圖片右上角坐標(biāo) */ private Point pointLeftTop; /*** * 圖片右下角坐標(biāo) */ private Point pointRightBottom; /*** * 記錄圓圈 */ private List<LYJCircle> lyjCircleList; /*** * 標(biāo)記是否按下按鈕,并且源泉是否擴(kuò)散消失 */ private boolean isSpread=false; /*** * 默認(rèn)沒(méi)有按動(dòng)時(shí)候的圓圈 */ 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); // 設(shè)置位圖的寬高 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());//設(shè)置陰影效果 int[] mColors = new int[] {//渲染顏色 Color.TRANSPARENT,swatch1.getRgb() }; //范圍,這里可以微調(diào),實(shí)現(xiàn)你想要的漸變 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); //發(fā)送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: //定時(shí)更新界面 clearScreenAndDrawList(); invalidate(); Message message = handler.obtainMessage(1); handler.sendMessageDelayed(message, 200); } super.handleMessage(msg); } }; /** * 清掉屏幕上所有的圓圈,然后畫(huà)出集合里面的圓圈 */ private void clearScreenAndDrawList() { canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); //判斷是否按下圖片,并且外圈執(zhí)行完成沒(méi)有。 if(!isSpread){ circlePaint.setMaskFilter(null); canvas.drawCircle(defaultCircle.getRoundX(), defaultCircle.getRoundY(),defaultCircle.getRadiuLoop(), circlePaint);// 畫(huà)線 }else{ for (LYJCircle lyjCircle : lyjCircleList) { if(lyjCircle.getSpreadRadiu()==0){ }else if(lyjCircle.getSpreadRadiu()>(lyjCircle.getRadiu()+99)){ //如果圓圈擴(kuò)散半徑大于圖片半徑+99,那么設(shè)置邊緣模糊,也就是淡出的效果 circlePaint.setMaskFilter(new BlurMaskFilter(5, BlurMaskFilter.Blur.OUTER)); canvas.drawCircle(lyjCircle.getRoundX(), lyjCircle.getRoundY(),lyjCircle.getSpreadRadiu(), circlePaint);// 畫(huà)線 }else{ //不是則按正常的環(huán)形渲染來(lái) circlePaint.setMaskFilter(null); canvas.drawCircle(lyjCircle.getRoundX(), lyjCircle.getRoundY(),lyjCircle.getSpreadRadiu(), circlePaint);// 畫(huà)線 } } } canvas.drawBitmap(imageBit,pointLeftTop.x,pointLeftTop.y,paint); //釋放小時(shí)了的圓圈 for(int i=0;i<lyjCircleList.size();i++){ if(lyjCircleList.get(i).getSpreadRadiu()==0){ lyjCircleList.remove(i); } } //如果沒(méi)有點(diǎn)擊圖片發(fā)射出去的圓圈,那么就恢復(fù)默認(rèn)縮放。 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;//圓中心點(diǎn)X坐標(biāo) private int roundY;//圓中心點(diǎn)Y坐標(biāo) private int radiu;//圓半徑 private int currentRadiu;//當(dāng)前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};//半徑擴(kuò)大速度。這里為勻速 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; } //獲取循環(huán)縮放半徑 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; } }
你可以修改如下兩個(gè)地方,會(huì)產(chǎn)生視覺(jué)上真真的波紋效果:
①支付寶的背景圖片是淡紅色,襯托了紅色的波紋。當(dāng)然了你也可以將畫(huà)布設(shè)置為透明淡紅色。
②其為填充圓圈渲染,不是我的邊框渲染效果,你可以將circlePaint.setStyle(Paint.Style.STROKE);換成Paint.Style.FILL.然后,微調(diào)shader的mPositions實(shí)現(xiàn)環(huán)形填充漸變。你也許會(huì)覺(jué)得,你看支付寶咻一咻圓圈彈開(kāi)的時(shí)候內(nèi)圈有波紋也像外彈開(kāi),其實(shí)那就是環(huán)形漸變,當(dāng)你圓圈變大后,其漸變的范圍也就變大了,自然你看到有顏色周圍擴(kuò)散的跡象。
2.屬性動(dòng)畫(huà)實(shí)現(xiàn)咻一咻
其要掌握的只是基本只需要屬性動(dòng)畫(huà),在加一點(diǎn)線程方面有關(guān)的知識(shí)而已。
下面我們看看其實(shí)現(xiàn)步驟:
㈠自定義View實(shí)現(xiàn)一個(gè)圓即可,代碼如下:
public class LYJCircleView extends View { private Bitmap bitmap; private Paint paint; private Canvas canvas; private int screenWidth; private int screenHeight; private boolean isSpreadFlag=false;//標(biāo)記是否發(fā)射完成 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); // 設(shè)置位圖的寬高 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); } }
代碼與上面差不多,就不注釋了。
㈡實(shí)現(xiàn)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);//發(fā)射圓圈,即將循環(huán)動(dòng)畫(huà)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);//動(dòng)畫(huà)執(zhí)行完成,標(biāo)記一下 } @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); //發(fā)送message,定時(shí)釋放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); //獲取狀態(tài)欄高度 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(); // 加載動(dòng)畫(huà) 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();//循環(huán)執(zhí)行動(dòng)畫(huà) } @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>
當(dāng)然上面兩個(gè)實(shí)現(xiàn)方法,我都只設(shè)置圓邊框,沒(méi)有填充,你可以設(shè)置為填充后,在微調(diào)漸變值。
其屬性動(dòng)畫(huà)文件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>
另一個(gè)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>
以上就是本文的詳細(xì)內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。
- Android 自定義view仿支付寶咻一咻功能
- Android中RecyclerView布局代替GridView實(shí)現(xiàn)類似支付寶的界面
- Android波紋擴(kuò)散效果之仿支付寶咻一咻功能實(shí)現(xiàn)波紋擴(kuò)散特效
- Android app第三方支付寶支付接入教程
- Android支付寶支付封裝代碼
- Android支付寶和微信支付集成
- Android開(kāi)發(fā)之實(shí)現(xiàn)GridView支付寶九宮格
- Android仿支付寶支付從底部彈窗效果
- Android支付寶支付設(shè)計(jì)開(kāi)發(fā)
- Android自定義View實(shí)現(xiàn)支付寶咻一咻效果
相關(guān)文章
Android采用雙緩沖技術(shù)實(shí)現(xiàn)畫(huà)板
這篇文章主要為大家詳細(xì)介紹了Android采用雙緩沖技術(shù)實(shí)現(xiàn)畫(huà)板的相關(guān)資料,思路清晰,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-05-05Flutter 快速實(shí)現(xiàn)聊天會(huì)話列表效果示例詳解
這篇文章主要為大家介紹了Flutter 快速實(shí)現(xiàn)聊天會(huì)話列表效果示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10Android自定義View仿IOS圓盤時(shí)間選擇器
這篇文章主要介紹了Android自定義View仿IOS圓盤時(shí)間選擇器,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-03-03Android實(shí)現(xiàn)從相冊(cè)截圖的功能
這篇文章主要介紹了Android實(shí)現(xiàn)從相冊(cè)截圖的功能,簡(jiǎn)單介紹了Android實(shí)現(xiàn)從相冊(cè)截圖功能的步驟,供大家參考,感興趣的小伙伴們可以參考一下2016-01-01Android實(shí)現(xiàn)Activity界面切換添加動(dòng)畫(huà)特效的方法
這篇文章主要介紹了Android實(shí)現(xiàn)Activity界面切換添加動(dòng)畫(huà)特效的方法,非常實(shí)用的技巧,需要的朋友可以參考下2014-08-08Android開(kāi)發(fā)之a(chǎn)ndroid_gps定位服務(wù)簡(jiǎn)單實(shí)現(xiàn)
這篇文章主要介紹了Android開(kāi)發(fā)之a(chǎn)ndroid_gps定位服務(wù)簡(jiǎn)單實(shí)現(xiàn) ,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-04-04Android viewpager中動(dòng)態(tài)添加view并實(shí)現(xiàn)偽無(wú)限循環(huán)的方法
這篇文章主要介紹了Android viewpager中動(dòng)態(tài)添加view并實(shí)現(xiàn)偽無(wú)限循環(huán)的方法,涉及Android使用viewpager動(dòng)態(tài)加載view及view無(wú)限循環(huán)顯示的相關(guān)技巧,需要的朋友可以參考下2016-01-01EditText限制輸入數(shù)字,精確到小數(shù)點(diǎn)后1位的設(shè)置方法
下面小編就為大家?guī)?lái)一篇EditText限制輸入數(shù)字,精確到小數(shù)點(diǎn)后1位的設(shè)置方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04