Android自定義View實(shí)現(xiàn)支付寶咻一咻效果
本篇文章介紹自定義View配合屬性動(dòng)畫來(lái)實(shí)現(xiàn)如下的效果

實(shí)現(xiàn)思路挺簡(jiǎn)單:
- 畫一個(gè)半透明的圓
- 實(shí)現(xiàn)兩種動(dòng)畫效果,點(diǎn)擊時(shí)擴(kuò)散和不點(diǎn)擊時(shí)擴(kuò)散回收
- 使用線程的方式將上面兩步結(jié)合起來(lái)
首先看下畫半透明圓的部分
public class ClickCircleView extends View {
private Bitmap bitmap;
private Paint paint;
private Canvas canvas;
private boolean isSpreadFlag = false;//標(biāo)記是否發(fā)射完成
public boolean isSpreadFlag() {
return isSpreadFlag;
}
public void setIsSpreadFlag(boolean isSpreadFlag) {
this.isSpreadFlag = isSpreadFlag;
}
public ClickCircleView(Context context, int width, int height, int screenWidth, int screenHeight) {
super(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.WHITE);
paint.setStyle(Paint.Style.FILL);
paint.setAlpha(50);
canvas.drawCircle(screenWidth / 2, screenHeight / 2, width / 2 + 10, paint);
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, 0, 0, null);
}
}
可以看到相關(guān)的屬性都是設(shè)置在畫筆上,然后直接調(diào)用畫布的drawCircle()方法畫出一個(gè)半透明的圓,最后調(diào)用invalidate()方法刷新View
一定要重寫父類的onDraw()方法,否則自定義View不能生效
我們?cè)O(shè)置了一個(gè)標(biāo)志位isSpreadFlag,作用是用來(lái)標(biāo)記擴(kuò)散動(dòng)畫是否完成
然后我們來(lái)實(shí)現(xiàn)兩個(gè)動(dòng)畫效果
點(diǎn)擊時(shí)擴(kuò)散動(dòng)畫
<set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:duration="1000" android:propertyName="scaleY" android:valueFrom="1.0" android:valueTo="1.8" android:valueType="floatType" /> <objectAnimator android:duration="1000" android:propertyName="scaleX" android:valueFrom="1.0" android:valueTo="1.8" android:valueType="floatType" /> </set>
很簡(jiǎn)單,就是改變scale值,增大到1.8倍
不點(diǎn)擊時(shí)擴(kuò)散回收動(dòng)畫
<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 android:duration="1000" android:propertyName="scaleY" android:valueFrom="1.0" android:valueTo="1.2" android:valueType="floatType" /> <objectAnimator android:duration="1000" android:propertyName="scaleX" android:startOffset="1000" android:valueFrom="1.2" android:valueTo="1.0" android:valueType="floatType" /> <objectAnimator android:duration="1000" android:propertyName="scaleY" android:startOffset="1000" android:valueFrom="1.2" android:valueTo="1.0" android:valueType="floatType" /> </set>
和上個(gè)動(dòng)畫類似,startOffset參數(shù)可以用來(lái)控制Animation的運(yùn)行順序,比如Android:startOffset=”1000”表示設(shè)置該屬性的動(dòng)畫延遲1秒執(zhí)行
然后就是用線程來(lái)執(zhí)行動(dòng)畫和邏輯的部分了
不點(diǎn)擊時(shí)的動(dòng)畫部分
mXiuyixiuButton.post(new Runnable() {
@Override
public void run() {
clickCircleView = new ClickCircleView(CustomView1.this, mXiuyixiuButton.getWidth()
, mXiuyixiuButton.getHeight(), mXiuyixiuLayout.getMeasuredWidth(),
mXiuyixiuLayout.getMeasuredHeight());
clickCircleView.setVisibility(View.VISIBLE);
mXiuyixiuLayout.addView(clickCircleView);
mXiuyixiuLayout.postInvalidate();
// 加載動(dòng)畫
final Animator anim = AnimatorInflater.loadAnimator(CustomView1.this,
R.animator.circle_scale_animator);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (anim != null) {
anim.start();//循環(huán)執(zhí)行動(dòng)畫
}
}
});
anim.setTarget(clickCircleView);
anim.start();
}
});
初始化好clickCircleView之后將這個(gè)view加入父布局中,然后加載動(dòng)畫并設(shè)置循環(huán)執(zhí)行,最后使用postInvalidate()在子線程中刷新view
點(diǎn)擊時(shí)的動(dòng)畫部分
mXiuyixiuButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
clickCircleView.setVisibility(View.GONE);//發(fā)射圓圈,即將循環(huán)動(dòng)畫View隱藏
final ClickCircleView item = new ClickCircleView(CustomView1.this, mXiuyixiuButton.getWidth()
, mXiuyixiuButton.getHeight(), mXiuyixiuLayout.getWidth(),
mXiuyixiuLayout.getHeight());
Animator spreadAnim = AnimatorInflater.loadAnimator(CustomView1.this,
R.animator.circle_spread_animator);
spreadAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
item.setIsSpreadFlag(true);//動(dòng)畫執(zhí)行完成,標(biāo)記一下
}
});
spreadAnim.setTarget(item);
spreadAnim.start();
clickCircleViewList.add(item);
mXiuyixiuLayout.addView(item);
mXiuyixiuLayout.invalidate();
handler.post(circleViewRunnable);
}
});
隱藏不點(diǎn)擊動(dòng)畫,初始化好ClickCircleView后將該view加入List中并添加到父布局中,然后加載動(dòng)畫并在動(dòng)畫結(jié)束時(shí)添加isSpreadFlag標(biāo)記,最后調(diào)用invalidate()方法刷新view并開(kāi)啟線程
線程部分
private Runnable circleViewRunnable = new Runnable() {
public void run() {
for (int i = 0; i < clickCircleViewList.size(); i++) {
if (clickCircleViewList.get(i).isSpreadFlag()) {
mXiuyixiuLayout.removeView(clickCircleViewList.get(i));
clickCircleViewList.remove(i);
mXiuyixiuLayout.postInvalidate();
}
}
if (clickCircleViewList.size() <= 0) {
clickCircleView.setVisibility(View.VISIBLE);
}
handler.postDelayed(this, 100);
}
};
遍歷list,將有isSpreadFlag標(biāo)記的view從list和父布局中移除并刷新view,最后判斷l(xiāng)ist如果為空的話將不點(diǎn)擊時(shí)的動(dòng)畫顯示出來(lái)
最后記得在onDestroy()里移除線程
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacks(circleViewRunnable);
}
使用自定義View配合屬性動(dòng)畫來(lái)實(shí)現(xiàn)該效果耦合性較高,只是這種方式相比完全使用自定義View來(lái)說(shuō)更加流暢,該方式大部分參考別人博客上的代碼來(lái)實(shí)現(xiàn),但是如果僅僅只是就拿來(lái)用不總結(jié)是不會(huì)成為自己的知識(shí)的,因此有了這篇博客。
參考: android實(shí)現(xiàn)支付寶咻一咻的幾種思路方法
以上就是本文的全部?jī)?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幫你實(shí)現(xiàn)咻一咻
相關(guān)文章
Android用注解與反射實(shí)現(xiàn)Butterknife功能
Butterknife是一個(gè)在android上實(shí)現(xiàn)ioc(控制反轉(zhuǎn))的一個(gè)庫(kù)。ioc的核心是解耦。解耦的目的是修改耦合對(duì)象時(shí)不影響另外一個(gè)對(duì)象,降低模塊之間的關(guān)聯(lián)。在Spring中ioc更多的是依靠xml的配置。而android上的IOC框架可以不使用xml配置2022-11-11
Kotlin遍歷集合導(dǎo)致并發(fā)修改異常的原因和解決方法
這篇文章主要介紹了Kotlin遍歷集合導(dǎo)致并發(fā)修改異常的原因和解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
android:TextView簡(jiǎn)單設(shè)置文本樣式和超鏈接的方法
這篇文章主要介紹了android:TextView簡(jiǎn)單設(shè)置文本樣式和超鏈接的方法,涉及TextView常見(jiàn)文字屬性的相關(guān)操作技巧,需要的朋友可以參考下2016-08-08
Android 使用AsyncTask實(shí)現(xiàn)多線程斷點(diǎn)續(xù)傳
本文將詳細(xì)講解如何使用AsyncTask來(lái)實(shí)現(xiàn)多線程的斷點(diǎn)續(xù)傳下載功能,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧2018-05-05

