Android 5.0 实现水波扩散效果

本文实例为大家分享了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>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android项目实战手把手教你画圆形水波纹loadingview

    本文实例讲解的是如何画一个满满圆形水波纹loadingview,这类效果应用场景很多,比如内存占用百分比之类的,分享给大家供大家参考,具体内容如下 效果图如下: 预备的知识: 1.贝塞尔曲线    如果你不了解,可以来这里进行基础知识储备:神奇的贝塞尔曲线 2.Paint.setXfermode()  以及PorterDuffXfermode 千万不要被这个b的名字吓到,不熟悉看到可能会认为很难记,其实 只要站在巨人的丁丁上 还是很简单的. 好了 废话不多说 ,跟我一步步来做一个炫酷的view吧

  • Android中Item实现点击水波纹效果

    前言 水波纹效果大致上可以分为两类,一类是有界水波纹,而另一类是无界水波纹,较为广泛使用的是有界水波纹. 系统自带的水波纹实现 系统自带的方法非常方便,只需要给相应的空间设置背景,背景内容则为系统自带的 selectableItemBackground ,这样的话,水波纹就会在TextView所在的区域内进行绘制. <TextView android:background="?android:attr/selectableItemBackground" ... /> 先上效

  • Android实现点击Button产生水波纹效果

    先上图,看看接下来我要向大家介绍的是个什么东西,如下图: 接下来要介绍的就是如何实现上述图中的波纹效果,这种效果如果大家没有体验过的话,可以看看百度手机卫士或者360手机卫士,里面的按钮点击效果都是这样的,另外Android 5.0以上的版本也出现了这种效果.不多说,下面聊聊具体的怎么实现. 首先大家看到的是三个button,水波纹的出现给我们的错觉是直接将波纹绘制在button上面的,但是这样能做到吗?首先button自己有background和src,如果把半透明的水波纹当作backgrou

  • Android仿水波纹流量球进度条控制器

    仿水波纹流球进度条控制器,Android实现高端大气的主流特效,供大家参考,具体内容如下 效果图: CircleView 这里主要是实现中心圆以及水波特效 package com.lgl.circleview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.gra

  • Android特效之水波纹的实现

    前言 水波纹特效,想必大家或多或少见过,在我的印象中,大致有如下几种: 支付宝 "咻咻咻" 式 流量球 "荡漾" 式 真实的水波纹效果,基于Bitmap处理式 话不多说,先来看看效果: 填充式水波纹,间距相等 非填充式水波纹,间距相等 非填充式水波纹,间距不断变大 填充式水波纹,间距不断变小 想必大家已经知道基本的原理了,就是用Canvas来画嘛,但可不是简单的画哦,请往下看. 分析 这种类型的水波纹,其实无非就是画圆而已,在给定的矩形中,一个个圆由最小半径扩大到最

  • Android实现水波纹扩散效果

    本文实例为大家分享了Android实现水波纹扩散效果的具体代码,供大家参考,具体内容如下 先上图 囧!没有图片所以就拿了小安代替了. 先看一下如何使用这个View. <jianpan.com.mybutton.view.RippleDiffuse android:layout_width="200dp" android:layout_height="200dp" app:btn_img_res="@drawable/rd" app:ripp

  • android自定义WaveView水波纹控件

    本文实例为大家分享了android自定义WaveView水波纹控件的使用方法,供大家参考,具体内容如下 Github Repository and libaray WaveView水波纹控件 首先看下演示demo demo中可以看到不同高度,不同速度,不同幅度的水波纹:你可以通过view的参数直接控制view的表现形式. 引入你的工程 在项目的根目录下的build.gradle文件中添加如下代码: allprojects { repositories { ... maven { url 'htt

  • Android实现水波纹特效

    最近需要做个类似于水波纹动画的效果,思考了一下不需要UI切个动态图,Android原生的技术利用动画或者自定义控件都可以实现,下面上个图类似于这样的效果 下面请看第一种动画实现,这种方式较为简单些,就是利用3个ImageView不断地做缩放和渐变的动画. 布局文件定义一下 <RelativeLayout android:id="@+id/rl" android:layout_width="match_parent" android:layout_height=

  • Android水波纹载入控件CircleWaterWaveView使用详解

    一.效果图 本控件已上传Github,欢迎Star和Fork,项目地址:CircleWaterWaveView 二.设计思路 观察效果图,可以看出,该自定义控件由三个部分构成:外圆.内圆.正弦曲线.他们的关系如下图: 因为控件是动态的,所以我们需要一个线程去不停地绘制,所以我选择了SurfaceView来作为该控件地父类.该控件地核心是如何去绘制波浪,我采用如下的思路来进行内圆下部地绘制.利用内圆与正弦曲线地交集,来绘制. 核心代码如下: /** * 绘制图像 * * @author luxun

  • Android自定义控件实现水波纹效果

    本文实例为大家分享了Android自定义控件实现水波纹的具体代码,供大家参考,具体内容如下 示例代码: MainActivity.java package com.example.mhy.shuibowen; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity { @Override protec

随机推荐