Android 两种方式实现类似水波扩散效果

taixiang 2018-05-27 原文

Android 两种方式实现类似水波扩散效果

原文链接 https://mp.weixin.qq.com/s/M19tp_ShOO6esKdozi7Nlg

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

  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的效果更好点,动画实现起来更方便点。

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

欢迎关注我的博客:https://blog.manjiexiang.cn/
同时欢迎关注微信公众号
image.png

发表于 2018-05-27 13:46 程序猿tx 阅读() 评论() 编辑 收藏

 

版权声明:本文为taixiang原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/taixiang/p/9095464.html

Android 两种方式实现类似水波扩散效果的更多相关文章

  1. Android事件分发机制五:面试官你坐啊

    前言 很高兴遇见你~ 事件分发系列文章已经到最后一篇了,先来回顾一下前面四篇,也当个目录: Android事件 […]...

  2. Android 对话框(Dialog)大全【转】

    图1 图1效果:该效果是当按返回按钮时弹出一个提示,来确保无误操作,采用常见的对话框样式。      代码: […]...

  3. ExpandableListView的完美实现,JSON数据源,右边自定义图片

    转载请标明出处: http://www.cnblogs.com/dingxiansen/p/8194669.h […]...

  4. Android 实现微信QQ分享以及第三方登录

    集成准备 在微信开放平台创建移动应用,输入应用的信息,包括移动应用名称,移动应用简介,移动应用图片信息,点击下 […]...

  5. Android Studio安装及其使用

    为了不与Java开发混用,所以不使用IDEA开发安卓应用而选择Android Studio。 官网下载安装 A […]...

  6. 缩放手势 ScaleGestureDetector 源码解析,这一篇就够了

    其实在我们日常的编程中,对于缩放手势的使用并不是很经常,这一手势主要是用在图片浏览方面,比如下方例子。但是(敲 […]...

  7. 收藏 – android

    收藏 – android开发 2018-05-04 16:39:36 介绍:这篇文章是收藏系列的开 […]...

  8. Android NDK开发学习教程(一)JNI语法

    Android NDK开发学习教程(一)JNI语法 一、对照表 Java类型    本地类型         […]...

随机推荐

  1. linux分析利刃之sar命令详解

     一、sar的概述     在我使用的众多linux分析工具中,sar是一个非常全面的一个分析工具,可以比较瑞 […]...

  2. 1 Spring 框架概述

    目录 Spring 框架概述 1 我们所说的 “Spring “是什么意思 2. Sp […]...

  3. 大数据运维:大数据平台+海量数据

    大数据开发独揽大权 大数据技术很早就在BAT这些公司生根发芽,但直到14、15年大数据技术才广泛应用在各大互联 […]...

  4. 个人代码规范分享

    前言 本文总结了下我在前端开发过程中编写JavaScript的一些习惯的代码规范,以前端开发背景为主,但有些规 […]...

  5. 通俗易懂–线性回归算法讲解(算法+案例) – mantch

    通俗易懂–线性回归算法讲解(算法+案例) 1.线性回归(Linear Regression) 1. […]...

  6. RPC(Remote Procedure Calls)远程过程调用 – sea的博客

    RPC(Remote Procedure Calls)远程过程调用 RPC(Remote Procedure […]...

  7. 从软件公司的异同点讲起,聊聊未来的程序员该如何选公司和谋规划

        过了年以后,新的一轮春招又要开始,于是一个迫切的问题就摆在广大计算机相关专业的毕业生面前,那就是,找工 […]...

  8. 苹果之硬盘启动安装

    交流群:286866978 一、 部署篇 1. 显示隐藏文件 2. 加载光盘如下 3. 重新添加一块存储 4. […]...

展开目录

目录导航