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

實現(xiàn)思路挺簡單:
- 畫一個半透明的圓
- 實現(xiàn)兩種動畫效果,點擊時擴散和不點擊時擴散回收
- 使用線程的方式將上面兩步結(jié)合起來
首先看下畫半透明圓的部分
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()方法畫出一個半透明的圓,最后調(diào)用invalidate()方法刷新View
一定要重寫父類的onDraw()方法,否則自定義View不能生效
我們設(shè)置了一個標(biāo)志位isSpreadFlag,作用是用來標(biāo)記擴散動畫是否完成
然后我們來實現(xiàn)兩個動畫效果
點擊時擴散動畫
<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>
很簡單,就是改變scale值,增大到1.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 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>
和上個動畫類似,startOffset參數(shù)可以用來控制Animation的運行順序,比如Android:startOffset=”1000”表示設(shè)置該屬性的動畫延遲1秒執(zhí)行
然后就是用線程來執(zhí)行動畫和邏輯的部分了
不點擊時的動畫部分
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();
// 加載動畫
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í)行動畫
}
}
});
anim.setTarget(clickCircleView);
anim.start();
}
});
初始化好clickCircleView之后將這個view加入父布局中,然后加載動畫并設(shè)置循環(huán)執(zhí)行,最后使用postInvalidate()在子線程中刷新view
點擊時的動畫部分
mXiuyixiuButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
clickCircleView.setVisibility(View.GONE);//發(fā)射圓圈,即將循環(huán)動畫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);//動畫執(zhí)行完成,標(biāo)記一下
}
});
spreadAnim.setTarget(item);
spreadAnim.start();
clickCircleViewList.add(item);
mXiuyixiuLayout.addView(item);
mXiuyixiuLayout.invalidate();
handler.post(circleViewRunnable);
}
});
隱藏不點擊動畫,初始化好ClickCircleView后將該view加入List中并添加到父布局中,然后加載動畫并在動畫結(jié)束時添加isSpreadFlag標(biāo)記,最后調(diào)用invalidate()方法刷新view并開啟線程
線程部分
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如果為空的話將不點擊時的動畫顯示出來
最后記得在onDestroy()里移除線程
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacks(circleViewRunnable);
}
使用自定義View配合屬性動畫來實現(xiàn)該效果耦合性較高,只是這種方式相比完全使用自定義View來說更加流暢,該方式大部分參考別人博客上的代碼來實現(xiàn),但是如果僅僅只是就拿來用不總結(jié)是不會成為自己的知識的,因此有了這篇博客。
參考: android實現(xiàn)支付寶咻一咻的幾種思路方法
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android用注解與反射實現(xiàn)Butterknife功能
Butterknife是一個在android上實現(xiàn)ioc(控制反轉(zhuǎn))的一個庫。ioc的核心是解耦。解耦的目的是修改耦合對象時不影響另外一個對象,降低模塊之間的關(guān)聯(lián)。在Spring中ioc更多的是依靠xml的配置。而android上的IOC框架可以不使用xml配置2022-11-11
Kotlin遍歷集合導(dǎo)致并發(fā)修改異常的原因和解決方法
這篇文章主要介紹了Kotlin遍歷集合導(dǎo)致并發(fā)修改異常的原因和解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
android:TextView簡單設(shè)置文本樣式和超鏈接的方法
這篇文章主要介紹了android:TextView簡單設(shè)置文本樣式和超鏈接的方法,涉及TextView常見文字屬性的相關(guān)操作技巧,需要的朋友可以參考下2016-08-08
Android 使用AsyncTask實現(xiàn)多線程斷點續(xù)傳
本文將詳細(xì)講解如何使用AsyncTask來實現(xiàn)多線程的斷點續(xù)傳下載功能,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧2018-05-05

