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為水波動畫的顏色,rippleAlpha為其透明度,rippleTime為動畫持續(xù)時間,maskAlpha為觸摸遮掩層的透明度。
2、自定義RippleView類繼承RelativeLayout布局,也可以由需求所定繼承于其它類,實(shí)現(xiàn)水波擴(kuò)散效果主要的有兩點(diǎn):水波擴(kuò)散的繪制和動畫
1)水波的繪制其實(shí)就是繪制一個圓形
canvas.drawCircle(mDownX, mDownY, mRadius, mRipplePaint);
2)動畫效果就是該圓形的繪制從小到大的過程,而該圓形到最大時的半徑長度就是當(dāng)前所在布局的對角線長度:
@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);
}
動畫效果用屬性動畫ObjectAnimator來實(shí)現(xiàn)(ObjectAnimator是android3.0后出現(xiàn)的)如下
mRippleAnim = ObjectAnimator.ofFloat(this, "radius", 0, mMaxRadius); mRippleAnim.setInterpolator(new AccelerateDecelerateInterpolator()); mRippleAnim.setDuration(mRippleTime);
其中的radius為自定義的屬性,在動畫執(zhí)行時會回調(diào)對應(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;// 水波動畫時間
private ObjectAnimator mRippleAnim;// 顯示水波動畫
private float mRadius;// 當(dāng)前的半徑
private float mMaxRadius;// 水波最大半徑
private float mDownX; // 記錄手指按下的位置
private float mDownY;
private boolean mIsMask;
private boolean mIsAnimating;// 是否正在播放動畫
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));
}
// 初始化動畫
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);
// 初始化動畫
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();
}
// 屬性動畫回調(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)容,希望對大家的學(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項目實(shí)戰(zhàn)手把手教你畫圓形水波紋loadingview
- Android仿水波紋流量球進(jìn)度條控制器
相關(guān)文章
Android編程中activity的完整生命周期實(shí)例詳解
這篇文章主要介紹了Android編程中activity的完整生命周期,結(jié)合實(shí)例形式較為詳細(xì)的分析了Android編程中activity的原理與具體用法,需要的朋友可以參考下2015-12-12
Android實(shí)現(xiàn)自動提取短信驗證碼功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)自動提取短信驗證碼功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-01-01
Android 自定義通用的loadingview實(shí)現(xiàn)代碼
本篇文章主要介紹了Android 自定義通用的loadingview實(shí)現(xiàn)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-01-01
Android EditText限制輸入字?jǐn)?shù)的方法
這篇文章主要介紹了Android EditText限制輸入字?jǐn)?shù)的方法,涉及Android針對EditText文本與字符串操作相關(guān)技巧,需要的朋友可以參考下2016-01-01
Android編程實(shí)現(xiàn)手機(jī)震動功能的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)手機(jī)震動功能的方法,結(jié)合實(shí)例形式分析了Android實(shí)現(xiàn)手機(jī)震動功能的核心代碼與權(quán)限控制操作技巧,需要的朋友可以參考下2017-06-06
使用OkHttp包在Android中進(jìn)行HTTP頭處理的教程
HTTP頭部處理是HTTP網(wǎng)絡(luò)編程中的基本操作,安卓中使用OkHttp包(github.com/square/okhttp)進(jìn)行相關(guān)操作當(dāng)然也是得心應(yīng)手,這里我們就來看一下使用OkHttp包在Android中進(jìn)行HTTP頭處理的教程2016-07-07
Flutter?WebView?預(yù)加載實(shí)現(xiàn)方法(Http?Server)
這篇文章主要介紹了Flutter?WebView?預(yù)加載實(shí)現(xiàn)方法,包括資源的配置,資源的下載和存儲,版本的管理,如何根據(jù)實(shí)際url獲取對應(yīng)HttpServer?bind的url等,需要的朋友可以參考下2022-05-05
android閱讀器長按選擇文字功能實(shí)現(xiàn)代碼
本篇文章主要介紹了android閱讀器長按選擇文字功能實(shí)現(xiàn)代碼,具有一定的參考價值,有興趣的可以了解一下2017-07-07

