Android几种动画的总结(MaterialAnimations)

触摸反馈

波纹效果(Ripple)

可以通过如下代码设置波纹的背景:
android:background="?android:attr/selectableItemBackground"波纹有边界

android:background="?android:attr/selectableItemBackgroundBorderless"波纹超出边界

效果如下:


Activity Transition

在Android 5.0 上 ,加入了对Activity的进入、退出的动画效果。

提供了三种Transition类型:

  1. 进入:一个进入的过渡(动画)决定activity中的所有的视图怎么进入屏幕。
  2. 退出:一个退出的过渡(动画)决定一个activity中的所有视图怎么退出屏幕。
  3. 共享元素:一个共享元素过渡(动画)决定两个activities之间的过渡,怎么共享(它们)的视图。

进入&退出

1、Enter(进入):进入一个Activity的效果

2、Exit(退出):退出一个Activity的效果

1. 设置Activity的动画

我们可以使用以下API进行设置:

Window.setEnterTransition():普通transition的进入效果

Window.setExitTransition():普通transition的退出效果

Window.setSharedElementEnterTransition():共享元素transition的进入效果

Window.setSharedElementExitTransition():共享元素transition的退出效果

可以为Activity设置下面三种进入的效果。

  1. explode:从场景的中心移入或移出

  2. slide:从场景的边缘移入或移出

  3. fade:调整透明度产生渐变效果

设置这几种效果可以使用代码实现,也可以使用xml文件实现。(两种选一种)

@Override
protected void onCreate(Bundle savedInstanceState) {
    
    ...

    Transition t;
        
    //代码实现
    t = buildEnterExplodeTransition();
    
    //读取xml实现
    t = TransitionInflater.from(this).inflateTransition(R.transition.explode);

    //设置进入动画
    getWindow().setEnterTransition(t);
    
    ...
}
    
    private Transition buildEnterExplodeTransition() {
        Explode enterTransition = new Explode();
        enterTransition.setDuration(500);
        enterTransition.setInterpolator(new LinearOutSlowInInterpolator());
        return enterTransition;
     }

explode.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<explode
    android:duration="500"
    android:interpolator="@android:interpolator/bounce" />
</transitionSet>

2. 要想看到启动Activity启动或者退出带有这种效果。那么启动的方式也要发生改变:

startActivity(intentExplodeCode, ActivityOptions.makeSceneTransitionAnimation(this).toBundle());

共享元素

共享元素的实现也是和设置Activity的进入或者退出的实现方式一样。

不一样的是启动Activity时,要注明共享元素的名字。

只共享一个元素时:

// ivShare: 需要共享的视图  
// "iv_share": 在布局文件上设置上android:transitionName="iv_share",名字随意命名。  
ActivityOptions activityOptions = ActivityOptions.makeSceneTransitionAnimation(
        StartTranstionActivity.this,
        ivShare, "iv_share");
startActivity(intentShare, activityOptions.toBundle());

共享多个元素时:使用Pair.create()来一一对应,然后传入makeSceneTransitionAnimation中。

ActivityOptions activityOptions = ActivityOptions.makeSceneTransitionAnimation(
        StartTranstionActivity.this,
        Pair.create((View) ivShare, "iv_share"),
        Pair.create((View)btnShare,"btn_share"));

和上面相比,只是ActivityOptions.makeSceneTransitionAnimation调用了另一个重载的方法,这个方法的第二个以后的参数就是共享元素的View和transitionName。

设置Fragment的进入与退出动画。

实现起来也十分简单,也是可以使用代码的形式实现,或者使用xml的形式来实现。
下面列子由代码来实现。

Slide slideTransition = new Slide(Gravity.LEFT);
slideTransition.setDuration(500);
//设置进入与退出效果
OneFragment oneFragment = new OneFragment();
oneFragment.setReenterTransition(slideTransition);
oneFragment.setEnterTransition(slideTransition);
oneFragment.setExitTransition(slideTransition);
oneFragment.setSharedElementEnterTransition(new ChangeBounds());

getSupportFragmentManager().beginTransaction()
        .replace(R.id.fl, oneFragment)
        .commit();

共享元素在 Activity 与 Fragment 之间使用

在这Activity 与 Fragment 之间使用,用法和在 Activity 与 Activity 之间使用是一样的。保证一点就是 Fragment 上要有 启动时 所要的共享元素。其他和上面没什么不同。

共享元素在 Fragment 与 Fragment 之间使用

 getFragmentManager().beginTransaction()
.replace(R.id.fl, twoFragment)
//增加共享元素
.addSharedElement(ivShare,"iv_share")
.commit();

这个addSharedElement(ivShare,"iv_share")就是添加了共享元素。其他都是一样的。

增加transition的监听。

使用就只是直接调用一个API就能实现了。

 getWindow().getEnterTransition().addListener(new Transition.TransitionListener() {
        @Override
        public void onTransitionStart(Transition transition) {
            System.out.println("开始进入");
        }

        @Override
        public void onTransitionEnd(Transition transition) {
            System.out.println("进入结束");
        }

        @Override
        public void onTransitionCancel(Transition transition) {

        }

        @Override
        public void onTransitionPause(Transition transition) {

        }

        @Override
        public void onTransitionResume(Transition transition) {

        }
    });

根据自己的所需的业务逻辑,就在上面添加逻辑就可以,通常我们可以用来制作一下动画效果。

View Animation

TransitionManager使得我们实现动画效果起来更加简单。

TransitionManager.beginDelayedTransition(llRoot);

TransitionManager.beginDelayedTransition(llRoot);这个方法,参数只要放入ViewGroup就可以了。当ViewGroup里面的元素的属性发生改变,那么就是自动补全中间的动画效果。

//改变图片的大小

TransitionManager.beginDelayedTransition(llRoot);
//取控件textView当前的布局参数
LinearLayout.LayoutParams params =(LinearLayout.LayoutParams) ivChange.getLayoutParams(); 
System.out.println(params.width);
params.width = 200+ivChange.getWidth();
params.height = 160+ivChange.getHeight();
ivChange.setLayoutParams(params);

//或者改变图片的位置
TransitionManager.beginDelayedTransition(llRoot);
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) ivChange.getLayoutParams();

if (positionChanged) {
    lp.gravity = Gravity.CENTER;
} else {
    lp.gravity = Gravity.LEFT;
}
positionChanged = !positionChanged ;
ivChange.setLayoutParams(lp);

中间并没有实现任何动画代码,运行效果如下:

我们也可以使用他的另一个重载方法: public static void beginDelayedTransition(final ViewGroup sceneRoot, Transition transition),为第二个参数加入transition。就可以变成自己的想要的效果了。

Scene

Scene可以把一个布局上控件全部同时改变并且加上动画效果。

使用方法:

  1. 创建Scene

使用 public static Scene getSceneForLayout(ViewGroup sceneRoot, int layoutId, Context context)这个方法。

  • sceneRoot指定一个ViewGroup,
  • layoutId给定一个布局ID
  • context....
sceneRoot = (FrameLayout) findViewById(R.id.scene_root);
scene1 = Scene.getSceneForLayout(sceneRoot, R.layout.activity_animations_scene1, this);
scene2 = Scene.getSceneForLayout(sceneRoot, R.layout.activity_animations_scene2, this);

开始动画:

TransitionManager.go(scene2, new ChangeBounds());

第二个参数就是Transition,设置自己想要的变化效果,如:

TransitionManager.go(scene2, TransitionInflater.from(ScenesActivity.this).
inflateTransition(R.transition.slide_and_changebounds_sequential));

上面设置两个Scene,注意的一点是布局上ID要有一样,否则系统不知道如何补充中间的动画。其实就是根据两个不同的布局下相同控件的位置进行计算并补全控件移动的动画。

同时我们也可以设置Scene动画监听:

//增加监听
scene2.setEnterAction(new Runnable() {
    @Override
    public void run() {
        System.out.println("scene1进入");
    }
});
scene2.setExitAction(new Runnable() {
    @Override
    public void run() {
        System.out.println("scene1退出");
    }
});

Circular Reveal

Circular Reveal是Android L新增的一个动画效果。

使用ViewAnimationUtils.createCircularReveal()方法可以去创建一个RevealAnimator动画

API如下:

 public static Animator createCircularReveal(View view,
        int centerX,  int centerY, float startRadius, float endRadius) {
    return new RevealAnimator(view, centerX, centerY, startRadius, endRadius);
}
  • middot;view 操作的视图

  • middot;centerX 动画开始的中心点X

  • middot;centerY 动画开始的中心点Y

  • middot;startRadius 动画开始半径

  • middot;startRadius 动画结束半径

因此可以实现下面的动画效果:

@Override
public void onClick(View v) {
    switch (v.getId()){
        case R.id.iv_green:
            revealGreen();
            break;
    }
}

private void revealGreen() {
    animateRevealColor(rlChange, R.color.sample_green);
}

private void animateRevealColor(ViewGroup viewRoot, @ColorRes int color) {
    int cx = (viewRoot.getLeft() + viewRoot.getRight()) / 2;
    int cy = (viewRoot.getTop() + viewRoot.getBottom()) / 2;
    animateRevealColorFromCoordinates(viewRoot, color, cx, cy);
}

private Animator animateRevealColorFromCoordinates(ViewGroup viewRoot, @ColorRes int color, int x, int y) {
    float finalRadius = (float) Math.hypot(viewRoot.getWidth(), viewRoot.getHeight());

    Animator anim = ViewAnimationUtils.createCircularReveal(viewRoot, x, y, 0, finalRadius);
    viewRoot.setBackgroundColor(ContextCompat.getColor(this, color));
    anim.setDuration(500);
    anim.setInterpolator(new AccelerateDecelerateInterpolator());
    anim.start();
    return anim;
}

效果如下:

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

推荐阅读更多精彩内容