Android 5.0 實(shí)現(xiàn)水波擴(kuò)散效果
本文實(shí)例為大家分享了Android 5.0 實(shí)現(xiàn)水波擴(kuò)散效果的具體代碼,供大家參考,具體內(nèi)容如下
該效果是通過自定義界面來實(shí)現(xiàn)的
1、首先自定義屬性,attrs.xml代碼如下:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="RippleView"> <attr name="rippleColor" format="color" /> <attr name="rippleAlpha" format="float" /> <attr name="maskAlpha" format="float" /> <attr name="rippleTime" format="integer" /> </declare-styleable> </resources>
其中屬性rippleColor為水波動(dòng)畫的顏色,rippleAlpha為其透明度,rippleTime為動(dòng)畫持續(xù)時(shí)間,maskAlpha為觸摸遮掩層的透明度。
2、自定義RippleView類繼承RelativeLayout布局,也可以由需求所定繼承于其它類,實(shí)現(xiàn)水波擴(kuò)散效果主要的有兩點(diǎn):水波擴(kuò)散的繪制和動(dòng)畫
1)水波的繪制其實(shí)就是繪制一個(gè)圓形
canvas.drawCircle(mDownX, mDownY, mRadius, mRipplePaint);
2)動(dòng)畫效果就是該圓形的繪制從小到大的過程,而該圓形到最大時(shí)的半徑長度就是當(dāng)前所在布局的對(duì)角線長度:
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); // 獲取最大半徑 mMaxRadius = (float) Math.sqrt(w * w + h * h); }
動(dòng)畫效果用屬性動(dòng)畫ObjectAnimator來實(shí)現(xiàn)(ObjectAnimator是android3.0后出現(xiàn)的)如下
mRippleAnim = ObjectAnimator.ofFloat(this, "radius", 0, mMaxRadius); mRippleAnim.setInterpolator(new AccelerateDecelerateInterpolator()); mRippleAnim.setDuration(mRippleTime);
其中的radius為自定義的屬性,在動(dòng)畫執(zhí)行時(shí)會(huì)回調(diào)對(duì)應(yīng)的方法,只需要在該方法中更新圓形的半徑就行了
public void setRadius(final float radius) { mRadius = radius; invalidate(); }
RippleView完整代碼如下:
public class RippleView extends RelativeLayout { private int mRippleColor;// 水波顏色 private float mMaskAlpha;// 遮掩透明度 private float mRippleAlpha;// 水波透明度 private int mRippleTime;// 水波動(dòng)畫時(shí)間 private ObjectAnimator mRippleAnim;// 顯示水波動(dòng)畫 private float mRadius;// 當(dāng)前的半徑 private float mMaxRadius;// 水波最大半徑 private float mDownX; // 記錄手指按下的位置 private float mDownY; private boolean mIsMask; private boolean mIsAnimating;// 是否正在播放動(dòng)畫 private RectF mRect; private Path mPath; private Paint mMaskPaint; private Paint mRipplePaint; public RippleView(Context context) { this(context, null); } public RippleView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public RippleView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); // 獲取自定義屬性 TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RippleView); mRippleColor = ta.getColor(R.styleable.RippleView_rippleColor, mRippleColor); mMaskAlpha = ta.getFloat(R.styleable.RippleView_maskAlpha, mMaskAlpha); mRippleAlpha = ta.getFloat(R.styleable.RippleView_rippleAlpha, mRippleAlpha); mRippleTime = ta.getInt(R.styleable.RippleView_rippleTime, mRippleTime); ta.recycle(); initLast(); } // 初始化方法 private void init() { mRippleColor = Color.BLACK; mMaskAlpha = 0.4f; mRippleAlpha = 0.8f; mRippleTime = 800; mPath = new Path(); mMaskPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mRipplePaint = new Paint(Paint.ANTI_ALIAS_FLAG); } // 初始化 private void initLast() { mMaskPaint.setColor(mRippleColor); mRipplePaint.setColor(mRippleColor); mMaskPaint.setAlpha((int) (mMaskAlpha * 255)); mRipplePaint.setAlpha((int) (mRippleAlpha * 255)); } // 初始化動(dòng)畫 private void initAnim() { mRippleAnim = ObjectAnimator.ofFloat(this, "radius", 0, mMaxRadius); mRippleAnim.setInterpolator(new AccelerateDecelerateInterpolator()); mRippleAnim.setDuration(mRippleTime); mRippleAnim.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { mIsAnimating = true; } @Override public void onAnimationEnd(Animator animator) { setRadius(0); mIsMask = false; mIsAnimating = false; } @Override public void onAnimationCancel(Animator animator) { } @Override public void onAnimationRepeat(Animator animator) { } }); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); // 獲取最大半徑 mMaxRadius = (float) Math.sqrt(w * w + h * h); // 獲取該類布局范圍 mRect = new RectF(0f, 0f, getMeasuredWidth() * 1.0f, getMeasuredHeight() * 1.0f); // 初始化動(dòng)畫 initAnim(); } @Override public boolean onTouchEvent(MotionEvent event) { // 按下事件 if (event.getAction() == MotionEvent.ACTION_DOWN) { mIsMask = true; invalidate(); } else if (event.getAction() == MotionEvent.ACTION_MOVE) { invalidate(); } // 抬起事件 else if (event.getAction() == MotionEvent.ACTION_UP) { mDownX = event.getX(); mDownY = event.getY(); if (mIsAnimating) { mRippleAnim.cancel(); } boolean isInView = mRect.contains(mDownX, mDownY); if (isInView) { mRippleAnim.start(); } else { mIsMask = false; invalidate(); } } return true; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 繪制遮掩 if (mIsMask) { canvas.save(Canvas.CLIP_SAVE_FLAG); mPath.reset(); mPath.addRect(mRect, Path.Direction.CW); canvas.clipPath(mPath); canvas.drawRect(mRect, mMaskPaint); canvas.restore(); } // 繪制水波 canvas.save(Canvas.CLIP_SAVE_FLAG); mPath.reset(); mPath.addCircle(mDownX, mDownY, mRadius, Path.Direction.CW); canvas.clipPath(mPath); canvas.drawCircle(mDownX, mDownY, mRadius, mRipplePaint); canvas.restore(); } // 屬性動(dòng)畫回調(diào)的方法 public void setRadius(final float radius) { mRadius = radius; invalidate(); } }
界面布局代碼
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:ripple="http://schemas.android.com/apk/res/com.example.rippleview" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#000000" > <com.example.rippleview.RippleView android:layout_width="match_parent" android:layout_height="100dp" android:layout_centerInParent="true" android:background="#ffffff" android:clickable="true" ripple:rippleColor="#ababab" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="click me" android:textSize="18sp" /> </com.example.rippleview.RippleView> </RelativeLayout>
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android實(shí)現(xiàn)水波紋擴(kuò)散效果
- Android實(shí)現(xiàn)水波紋特效
- Android自定義控件實(shí)現(xiàn)水波紋效果
- Android水波紋載入控件CircleWaterWaveView使用詳解
- android自定義WaveView水波紋控件
- Android中Item實(shí)現(xiàn)點(diǎn)擊水波紋效果
- Android實(shí)現(xiàn)點(diǎn)擊Button產(chǎn)生水波紋效果
- Android特效之水波紋的實(shí)現(xiàn)
- Android項(xiàng)目實(shí)戰(zhàn)手把手教你畫圓形水波紋loadingview
- Android仿水波紋流量球進(jìn)度條控制器
相關(guān)文章
android教程viewpager自動(dòng)循環(huán)和手動(dòng)循環(huán)
這篇文章主要介紹了android的viewpager自動(dòng)循環(huán)和手動(dòng)循環(huán)示例,需要的朋友可以參考下2014-02-02Android模擬用戶點(diǎn)擊的實(shí)現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于Android模擬用戶點(diǎn)擊的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)學(xué)習(xí)學(xué)習(xí)吧。2018-02-02Android程序開發(fā)之自定義設(shè)置TabHost,TabWidget樣式
這篇文章主要介紹了Android程序開發(fā)之自定義設(shè)置TabHost,TabWidget樣式的相關(guān)資料,需要的朋友可以參考下2016-03-03Android Studio中引入Lambda表達(dá)式的方法
這篇文章主要給大家介紹了在Android Studio中引入Lambda表達(dá)式的方法,文中通過圖文介紹的非常詳細(xì),對(duì)大家具有一定的參考價(jià)值,需要的朋友們下面來一起看看吧。2017-03-03Android WebView實(shí)現(xiàn)頂部進(jìn)度條
這篇文章主要為大家詳細(xì)介紹了Android WebView實(shí)現(xiàn)頂部進(jìn)度條,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11使用androidx BiometricPrompt實(shí)現(xiàn)指紋驗(yàn)證功能
這篇文章主要介紹了使用androidx BiometricPrompt實(shí)現(xiàn)指紋驗(yàn)證功能,對(duì)android指紋驗(yàn)證相關(guān)知識(shí)感興趣的朋友跟隨小編一起看看吧2021-07-07Android自定義View實(shí)現(xiàn)字母導(dǎo)航欄
通常手機(jī)通訊錄都會(huì)有索引欄,這篇文章主要介紹了Android自定義View實(shí)現(xiàn)字母導(dǎo)航欄,現(xiàn)在分享給大家。2016-10-10