本文实例为大家分享了Android 5.0 实现水波扩散效果的具体代码,供大家参考,具体内容如下
该效果是通过自定义界面来实现的
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为动画持续时间,maskAlpha为触摸遮掩层的透明度。
2、自定义RippleView类继承RelativeLayout布局,也可以由需求所定继承于其它类,实现水波扩散效果主要的有两点:水波扩散的绘制和动画
1)水波的绘制其实就是绘制一个圆形
- canvas.drawCircle(mDownX, mDownY, mRadius, mRipplePaint);
2)动画效果就是该圆形的绘制从小到大的过程,而该圆形到最大时的半径长度就是当前所在布局的对角线长度:
- @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来实现(ObjectAnimator是android3.0后出现的)如下
- mRippleAnim = ObjectAnimator.ofFloat(this, "radius", 0, mMaxRadius);
- mRippleAnim.setInterpolator(new AccelerateDecelerateInterpolator());
- mRippleAnim.setDuration(mRippleTime);
其中的radius为自定义的属性,在动画执行时会回调对应的方法,只需要在该方法中更新圆形的半径就行了
- 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;// 当前的半径
- 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();
-
- }
-
- // 属性动画回调的方法
- 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>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。