谁说Android的动画不廉价(五)之水波纹动画

本系列文章一共5篇
谁说Android的动画不廉价(一)之项目分层
谁说Android的动画不廉价(二)之转场动画
谁说Android的动画不廉价(三)之共享元素动画
谁说Android的动画不廉价(四)之元素动画
谁说Android的动画不廉价(五)之水波纹动画
GitHub源码

引言

本篇博文是基于上一篇博文谁说Android的动画不廉价(四)之元素动画的基础上做的拓展。

目标效果图

转场动画

前提说明

水波纹动画通过ViewAnimationUtils.createCircularReveal(View view, int centerX, int centerY, float startRadius, float endRadius);创建。返回一个属性动画类Animator

  • view : 水波纹动画作用的View
  • centerX : 水波纹动画开始的X坐标
  • centerY :水波纹动画开始的Y坐标
  • startRadius : 水波纹开始时圆的半径
  • endRadius : 水波纹扩散半径

编码

布局文件

水波纹动画布局文件
<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include layout="@layout/tool_bar" />

    <ImageView
        android:id="@+id/img1"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dp"
        android:src="@drawable/circle_yellow"
        android:transitionName="share1" />

    <TextView
        android:id="@+id/target"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/toolBar"
        android:padding="20dp"
        android:text="水波纹动画"
        android:textSize="30sp" />

    <ImageView
        android:id="@+id/circle_orange"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_margin="10dp"
        android:onClick="orange"
        android:scaleX="0"
        android:scaleY="0"
        android:src="@drawable/circle_orange" />


    <ImageView
        android:id="@+id/circle_red"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:layout_margin="10dp"
        android:layout_toRightOf="@+id/circle_orange"
        android:onClick="red"
        android:scaleX="0"
        android:scaleY="0"
        android:src="@drawable/circle_red" />


    <ImageView
        android:id="@+id/circle_blue"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:layout_margin="10dp"
        android:layout_toLeftOf="@+id/circle_yellow"
        android:onClick="blue"
        android:scaleX="0"
        android:scaleY="0"
        android:src="@drawable/circle_blue" />

    <ImageView
        android:id="@+id/circle_yellow"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_margin="10dp"
        android:onClick="yellow"
        android:scaleX="0"
        android:scaleY="0"
        android:src="@drawable/circle_yellow" />

</RelativeLayout>

MainActivity.java

    public void circularAnimations(View v) {
        View view = findViewById(R.id.img1);
        /**
         * view是用于共享元素toolbar上面那一点
         * 希望达到从共享元素扩散的效果
         */
        Intent intent = new Intent(this, CircularAnimationsActivity.class);
        ActivityOptionsCompat activityOptionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(this, new Pair(view, view.getTransitionName()));
        startActivity(intent, activityOptionsCompat.toBundle());
    }

CircularAnimations.java

package demo.august1996.top.transitionanimationsdemo;

import android.animation.Animator;
import android.graphics.Color;
import android.transition.ChangeBounds;
import android.transition.Transition;
import android.transition.TransitionInflater;
import android.transition.TransitionManager;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

import demo.august1996.top.transitionanimationsdemo.Activity.ToolbarActivity;

public class CircularAnimationsActivity extends ToolbarActivity {


    /**
     * 产生水波纹的View
     */
    TextView target;

    /**
     * Toolbar的那个圆点
     */
    ImageView imageView;

    /**
     * 产生进入动画效果的底部ImageView
     */
    List<View> imageViewList = new ArrayList<>();

    /**
     * 可以产生动画的ViewGroup
     */
    ViewGroup container;

    /**
     * 蓝色点的原始参数,用于位置移动后恢复位置
     */
    RelativeLayout.LayoutParams originlParams;

    @Override
    protected String getToolbarTitle() {
        return "水波纹动画";
    }

    /**
     * 初始化View和动画
     */
    @Override
    protected void initView() {
        container = (ViewGroup) findViewById(R.id.container);
        target = (TextView) findViewById(R.id.target);
        imageView = (ImageView) findViewById(R.id.img1);
        imageViewList.add(findViewById(R.id.circle_orange));
        imageViewList.add(findViewById(R.id.circle_blue));
        imageViewList.add(findViewById(R.id.circle_yellow));
        imageViewList.add(findViewById(R.id.circle_red));

        getWindow().setSharedElementEnterTransition(new ChangeBounds());


        getWindow().getSharedElementEnterTransition().addListener(new Transition.TransitionListener() {
            @Override
            public void onTransitionStart(Transition transition) {

            }

            /**
             * 当Toobar那个点到达Toolbar的指定个位置后,隐藏Toolbar的点并且在点的的位置产生水波纹动画
             * 同时触发底部ImageView的动画效果
             * @param transition
             */
            @Override
            public void onTransitionEnd(Transition transition) {
                int cx = imageView.getLeft() + imageView.getWidth() / 2;
                int cy = imageView.getTop() + imageView.getHeight() / 2;
                int startR = imageView.getWidth() / 2;
                int endR = Math.max(mToolbar.getWidth() / 2, mToolbar.getHeight() / 2);
                startCircularAnimation(mToolbar, cx, cy, startR, endR, Color.parseColor("#ffffe600"));
                imageView.setVisibility(View.GONE);

                //下面的方式是使每个View的动画产生顺序,时差200ms
                int delay = 200;
                for (int i = 0; i < imageViewList.size(); i++) {
                    View v = imageViewList.get(i);
                    v.animate()
                            .setStartDelay(delay * i)
                            .scaleX(1)
                            .scaleY(1)
                            .start();
                }
            }

            @Override
            public void onTransitionCancel(Transition transition) {

            }

            @Override
            public void onTransitionPause(Transition transition) {

            }

            @Override
            public void onTransitionResume(Transition transition) {

            }
        });
    }

    @Override
    protected int getContentViewID() {
        return R.layout.activity_circular_animations;
    }

    @Override
    protected boolean canBack() {
        return true;
    }

    /**
     * orange   red yellow的原理一样,只是产生动画的坐标XY不一样
     *
     * @param v
     */
    public void orange(View v) {
        int cx = target.getWidth() / 2;
        int cy = target.getHeight() / 2;
        int startR = v.getWidth() / 2;
        int endR = Math.max(target.getWidth() / 2, target.getHeight() / 2);
        startCircularAnimation(target, cx, cy, startR, endR, Color.parseColor("#ffffae00"));
    }

    public void red(View v) {
        int cx = target.getWidth() / 2;
        int cy = mToolbar.getBottom();
        int startR = v.getWidth() / 2;
        int endR = Math.max(target.getWidth() / 2, target.getHeight() / 2);
        startCircularAnimation(target, cx, cy, startR, endR, Color.parseColor("#ffff3d00"));
    }

    public void yellow(View v) {
        int cx = v.getLeft() + v.getWidth() / 2;
        int cy = v.getTop() + v.getHeight() / 2;
        int startR = v.getWidth() / 2;
        int endR = Math.max(target.getWidth() / 2, target.getHeight() / 2);
        startCircularAnimation(target, cx, cy, startR, endR, Color.parseColor("#ffffe600"));
    }

    /**
     * 此处跟上面的区别仅仅是先进行元素动画改变元素的位置
     * 然后再开启水波纹动画
     * 最后位置设置回原来位置
     *
     * @param v
     */
    public void blue(final View v) {
        Transition transition = TransitionInflater.from(CircularAnimationsActivity.this).inflateTransition(R.transition.changebounds_with_arcmotion);

        transition.addListener(new Transition.TransitionListener() {
            @Override
            public void onTransitionStart(Transition transition) {

            }

            @Override
            public void onTransitionEnd(Transition transition) {
                int cx = target.getWidth() / 2;
                int cy = target.getHeight() / 2;
                int startR = v.getWidth() / 2;
                int endR = Math.max(target.getWidth() / 2, target.getHeight() / 2);
                Animator animator = startCircularAnimation(target, cx, cy, startR, endR, Color.parseColor("#ff0095ff"));
                animator.addListener(new Animator.AnimatorListener() {
                    @Override
                    public void onAnimationStart(Animator animator) {

                    }

                    @Override
                    public void onAnimationEnd(Animator animator) {
                        v.setLayoutParams(originlParams);
                    }

                    @Override
                    public void onAnimationCancel(Animator animator) {

                    }

                    @Override
                    public void onAnimationRepeat(Animator animator) {

                    }
                });
            }

            @Override
            public void onTransitionCancel(Transition transition) {

            }

            @Override
            public void onTransitionPause(Transition transition) {

            }

            @Override
            public void onTransitionResume(Transition transition) {

            }
        });
        if (originlParams == null) {
            originlParams = (RelativeLayout.LayoutParams) v.getLayoutParams();
        }
        TransitionManager.beginDelayedTransition(container, transition);
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(v.getWidth(), v.getHeight());
        params.addRule(RelativeLayout.CENTER_IN_PARENT);
        v.setLayoutParams(params);

    }

    /**
     * 开启一个水波纹动画
     *
     * @param target 开启的View
     * @param cx     产生动画的X坐标
     * @param cy     产生动画的Y坐标
     * @param startR 水波纹起始半径
     * @param endR   水波纹扩散半径
     * @param color  水波纹颜色
     * @return
     */
    private Animator startCircularAnimation(final View target, int cx, int cy, int startR, int endR, final int color) {
        Animator circularReveal = ViewAnimationUtils.createCircularReveal(target, cx, cy, startR, endR);
        circularReveal.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {
                target.setBackgroundColor(color);
            }

            @Override
            public void onAnimationEnd(Animator animator) {

            }

            @Override
            public void onAnimationCancel(Animator animator) {

            }

            @Override
            public void onAnimationRepeat(Animator animator) {

            }
        });
        circularReveal.start();
        return circularReveal;
    }
}

我们的效果图

我们的效果图
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,302评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,232评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,337评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,977评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,920评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,194评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,638评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,319评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,455评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,379评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,426评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,106评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,696评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,786评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,996评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,467评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,043评论 2 341

推荐阅读更多精彩内容