Android 实现圆圈扩散水波动画效果两种方法

 更新时间:2018年05月28日 08:58:52   作者:程序猿tx  
这篇文章主要介绍了Android 实现圆圈扩散水波动画效果两种方法,需要的朋友可以参考下

两种方式实现类似水波扩散效果,先上图为敬

  1. 自定义view实现
  2. 动画实现

自定义view实现

思路分析:通过canvas画圆,每次改变圆半径和透明度,当半径达到一定程度,再次从中心开始绘圆,达到不同层级的效果,通过不断绘制达到view扩散效果

private Paint centerPaint; //中心圆paint
private int radius = 100; //中心圆半径
private Paint spreadPaint; //扩散圆paint
private float centerX;//圆心x
private float centerY;//圆心y
private int distance = 5; //每次圆递增间距
private int maxRadius = 80; //最大圆半径
private int delayMilliseconds = 33;//扩散延迟间隔,越大扩散越慢
private List<Integer> spreadRadius = new ArrayList<>();//扩散圆层级数,元素为扩散的距离
private List<Integer> alphas = new ArrayList<>();//对应每层圆的透明度

style文件里自定义属性

<declare-styleable name="SpreadView">
  <!--中心圆颜色-->
  <attr name="spread_center_color" format="color" />
  <!--中心圆半径-->
  <attr name="spread_radius" format="integer" />
  <!--扩散圆颜色-->
  <attr name="spread_spread_color" format="color" />
  <!--扩散间距-->
  <attr name="spread_distance" format="integer" />
  <!--扩散最大半径-->
  <attr name="spread_max_radius" format="integer" />
  <!--扩散延迟间隔-->
  <attr name="spread_delay_milliseconds" format="integer" />
</declare-styleable>

初始化

public SpreadView(Context context) {
  this(context, null, 0);
}
public SpreadView(Context context, @Nullable AttributeSet attrs) {
  this(context, attrs, 0);
}
public SpreadView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SpreadView, defStyleAttr, 0);
  radius = a.getInt(R.styleable.SpreadView_spread_radius, radius);
  maxRadius = a.getInt(R.styleable.SpreadView_spread_max_radius, maxRadius);
  int centerColor = a.getColor(R.styleable.SpreadView_spread_center_color, ContextCompat.getColor(context, R.color.colorAccent));
  int spreadColor = a.getColor(R.styleable.SpreadView_spread_spread_color, ContextCompat.getColor(context, R.color.colorAccent));
  distance = a.getInt(R.styleable.SpreadView_spread_distance, distance);
  a.recycle();
  centerPaint = new Paint();
  centerPaint.setColor(centerColor);
  centerPaint.setAntiAlias(true);
  //最开始不透明且扩散距离为0
  alphas.add(255);
  spreadRadius.add(0);
  spreadPaint = new Paint();
  spreadPaint.setAntiAlias(true);
  spreadPaint.setAlpha(255);
  spreadPaint.setColor(spreadColor);
}

确定圆心位置

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  super.onSizeChanged(w, h, oldw, oldh);
  //圆心位置
  centerX = w / 2;
  centerY = h / 2;
}

自定义view的绘制

@Override
protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  for (int i = 0; i < spreadRadius.size(); i++) {
    int alpha = alphas.get(i);
    spreadPaint.setAlpha(alpha);
    int width = spreadRadius.get(i);
    //绘制扩散的圆
    canvas.drawCircle(centerX, centerY, radius + width, spreadPaint);
    //每次扩散圆半径递增,圆透明度递减
    if (alpha > 0 && width < 300) {
      alpha = alpha - distance > 0 ? alpha - distance : 1;
      alphas.set(i, alpha);
      spreadRadius.set(i, width + distance);
    }
  }
  //当最外层扩散圆半径达到最大半径时添加新扩散圆
  if (spreadRadius.get(spreadRadius.size() - 1) > maxRadius) {
    spreadRadius.add(0);
    alphas.add(255);
  }
  //超过8个扩散圆,删除最先绘制的圆,即最外层的圆
  if (spreadRadius.size() >= 8) {
    alphas.remove(0);
    spreadRadius.remove(0);
  }
  //中间的圆
  canvas.drawCircle(centerX, centerY, radius, centerPaint);
  //TODO 可以在中间圆绘制文字或者图片
  //延迟更新,达到扩散视觉差效果
  postInvalidateDelayed(delayMilliseconds);
}

xml样式

<com.airsaid.diffuseview.widget.SpreadView
  android:id="@+id/spreadView"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  app:spread_center_color="@color/colorAccent"
  app:spread_delay_milliseconds="35"
  app:spread_distance="5"
  app:spread_max_radius="90"
  app:spread_radius="100"
  app:spread_spread_color="@color/colorAccent" />

效果图

中心圆处可以自定义写文字,画图片等等...

动画实现

思路分析:通过动画实现,imageView不停做动画缩放+渐变

最中心的imageView保持不变

中间一层imageView从原始放大到1.4倍,同时从不透明变为半透明

最外层的imageView从1.4倍放大到1.8倍,同时从半透明变为全透明

利用shape画一个圆,作为动画基础视图

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
  <corners android:radius="65dp"/>
  <solid android:color="@color/colorAccent"/>
</shape>

布局视图

<FrameLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <!--中心imageView-->
  <ImageView
    android:id="@+id/iv_wave"
    android:layout_width="130dp"
    android:layout_height="130dp"
    android:layout_gravity="center"
    android:background="@drawable/shape_circle" />
  <!--中间的imageView-->
  <ImageView
    android:id="@+id/iv_wave_1"
    android:layout_width="130dp"
    android:layout_height="130dp"
    android:layout_gravity="center"
    android:background="@drawable/shape_circle" />
  <!--最外层imageView-->
  <ImageView
    android:id="@+id/iv_wave_2"
    android:layout_width="130dp"
    android:layout_height="130dp"
    android:layout_gravity="center"
    android:background="@drawable/shape_circle" />
</FrameLayout>

中间imageView的动画

private void setAnim1() {
  AnimationSet as = new AnimationSet(true);
  //缩放动画,以中心从原始放大到1.4倍
  ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 1.4f, 1.0f, 1.4f,
      ScaleAnimation.RELATIVE_TO_SELF, 0.5f,
      ScaleAnimation.RELATIVE_TO_SELF, 0.5f);
  //渐变动画
  AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.5f);
  scaleAnimation.setDuration(800);
  scaleAnimation.setRepeatCount(Animation.INFINITE);
  alphaAnimation.setRepeatCount(Animation.INFINITE);
  as.setDuration(800);
  as.addAnimation(scaleAnimation);
  as.addAnimation(alphaAnimation);
  iv1.startAnimation(as);
}

最外层imageView的动画

private void setAnim2() {
  AnimationSet as = new AnimationSet(true);
  //缩放动画,以中心从1.4倍放大到1.8倍
  ScaleAnimation scaleAnimation = new ScaleAnimation(1.4f, 1.8f, 1.4f, 1.8f,
      ScaleAnimation.RELATIVE_TO_SELF, 0.5f,
      ScaleAnimation.RELATIVE_TO_SELF, 0.5f);
  //渐变动画
  AlphaAnimation alphaAnimation = new AlphaAnimation(0.5f, 0.1f);
  scaleAnimation.setDuration(800);
  scaleAnimation.setRepeatCount(Animation.INFINITE);
  alphaAnimation.setRepeatCount(Animation.INFINITE);
  as.setDuration(800);
  as.addAnimation(scaleAnimation);
  as.addAnimation(alphaAnimation);
  iv2.startAnimation(as);
}

效果图

相比较而言,自定义view的效果更好点,动画实现起来更方便点。

两种方式实现的扩散效果介绍完毕,具体项目里还是要按需变动的。

总结

以上所述是小编给大家介绍的Android 实现圆圈扩散水波动画效果两种方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

相关文章

  • Android编程之计时器Chronometer简单示例

    Android编程之计时器Chronometer简单示例

    这篇文章主要介绍了Android计时器Chronometer简单用法,结合实例形式分析了Android计时器Chronometer的定义、事件响应及界面布局相关操作技巧,需要的朋友可以参考下
    2017-08-08
  • android实现简单的活动转盘

    android实现简单的活动转盘

    这篇文章主要为大家详细介绍了android实现简单的活动转盘,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • Android 10.0截屏流程详解

    Android 10.0截屏流程详解

    这篇文章主要为大家介绍了Android 10.0截屏流程详解,通常未通过特殊定制的 Android 系统,截屏都是经过同时按住音量下键和电源键来截屏,本篇文章就只讨论使用这些特殊按键来进行截屏
    2023-06-06
  • 在Android中动态添加Panel框架的实现代码

    在Android中动态添加Panel框架的实现代码

    项目经常会有这种需求,就是想动态的在某个界面上添加一个Panel。比如,有一个按钮,点击后会显示下拉菜单式的界面。这种需求,就属于动态添加一个Panel。需求多了,就要研究是否可以抽象出通用的框架代码,以方便开发,所以就有了以下内容
    2013-05-05
  • Android Flutter实现创意时钟的示例代码

    Android Flutter实现创意时钟的示例代码

    时钟这个东西很奇妙,总能当做创意实现的入口。这篇文章主要介绍了如何通过Android Flutter实现一个创意时钟,感兴趣的小伙伴可以了解一下
    2023-03-03
  • 详解Flutter混排瀑布流解决方案

    详解Flutter混排瀑布流解决方案

    这篇文章主要介绍了Flutter混排瀑布流解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • 详解Android(共享元素)转场动画开发实践

    详解Android(共享元素)转场动画开发实践

    本篇文章主要介绍了详解Android(共享元素)转场动画开发实践,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-08-08
  • Android实现RecyclerView添加分割线的简便方法

    Android实现RecyclerView添加分割线的简便方法

    这篇文章主要介绍了Android实现RecyclerView添加分割线的简便方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • Android在类微信程序中实现蓝牙聊天功能的示例代码

    Android在类微信程序中实现蓝牙聊天功能的示例代码

    这篇文章主要介绍了Android在类微信程序中实现蓝牙聊天功能,本文通过实例代码给大家介绍的非常想详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06
  • Android4.0开发之Keyguard解锁屏机制详解

    Android4.0开发之Keyguard解锁屏机制详解

    这篇文章主要介绍了Android4.0开发之Keyguard解锁屏机制,结合实例形式详细分析了Android开发中Keyguard解锁屏模块的原理、使用方法与相关操作注意事项,需要的朋友可以参考下
    2017-12-12

最新评论