• Android L动画入门


    Android L带来了许多新特性,其中就包括了大量的动画效果,你可以在自己的应用中使用。本文中我将详解这些动画和如何在应用中使用。本文中的所有代码可以在github上找到。

    波纹和强调

    现在安卓支持少量的预定义样式属性,不过只限于应用特定部分例如状态栏、导航栏。新系统允许我们采用简单的方式即可获得两种非常简洁、有用的动画:波纹和被强调的UI组件。波纹是一种给予用户在UI上动作极好的回应效果,并且可以自定义波纹的颜色,只需要给colorControlHighlight 属性设置色值。

    1
    <item name="android:colorControlHighlight">#0000AA</item>
    ripples

    Ripples

    一样简单,很多UI组件像复选框都可以使用styles文件夹中的colorAccent 属性来设置符合你应用主题的颜色,而不必使用不同的图片和状态选择器。

    1
    <item name="android:colorAccent">#00FF00</item>

    Checks

    圆形显示

    安卓中一件常见工作就是改变屏幕上某一元素的可见性。现在开发者又多了一个选择可以让这项工作完成的更加漂亮:圆形显示。使用ViewAnimationUtil.createCircularReveal方法然后通过动画监听在合适的时间改变View的可见性。这有两个相似的方法用来让View可见或者消失。注意显示方法有一个持续时间的设置,以便完成动画的显示,隐藏动画执行的更快一点。getX()和getY()方法返回图片所在X、Y轴的中心点的坐标,getRadius()方法就是返回View的宽度。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    private void hideImageCircular() {
        int x = getX();
        int y = getY();
        int radius = getRadius();
     
        ValueAnimator anim =
                ViewAnimationUtils.createCircularReveal(mImageView, x, y, radius, 0);
     
        anim.addListener(new AnimatorListenerAdapter() {
     
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                mImageView.setVisibility( View.INVISIBLE );
            }
        });
     
        anim.start();
    }
     
    private void revealImageCircular() {
        int x = getX();
        int y = getY();
        int radius = getRadius();
     
        ValueAnimator anim =
                ViewAnimationUtils.createCircularReveal(mImageView, x, y, 0, radius);
     
        anim.setDuration( 1000 );
        anim.addListener( new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                mImageView.setVisibility( View.VISIBLE );
            }
        });
     
        anim.start();
    }
    circular_reveal

    Circular Reveal

    Activity转场动画

    除了前述几种动画,android L还增加了一些activity的过渡动画——爆炸、滑动、淡入淡出,让应用更加平滑。使用这些动画,你必须在进入和退出activity都要求使用这些内容转场特效,并且在setOncontent()方法之前。

    1
    getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

    也支持通过样式设置转换动画,我将详解如何在activity中通过样式设置专场效果。使用getWindow().setExitTransition( Transition ) 和getWindow().setEnterTransition( Transition ) 方法告诉activity当打开和关闭时如何执行。使用迸发动画,从MainActivity和ListFragment 到第二个activity的代码可以这样写:

    1
    2
    3
    4
    ListFragment:
    getActivity().getWindow().setExitTransition( new Explode() );
    intent = new Intent( getActivity(), ExplodeAnimationActivity.class );
    startActivity( intent );
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    ExplodeAnimationActivity:
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        getWindow().setEnterTransition( new Explode() );
        getWindow().setExitTransition( new Explode() );
        setContentView(R.layout.activity_explode_animation);
    }
     
    @Override
    public void onBackPressed() {
        super.onBackPressed();
        finishAfterTransition();
    }

    注意onBackPressed()方法——这很重要。因为它让操作系统知道在关闭第二个activity之前要完成动画的执行。使用这些简单的代码,我们就拥有了三种activity专场动画。

    explosion_transition

    Explosion Transition

    slide_transition

    Slide Transition

    fade_transition

    Fade Transition

    虽然我没有用到这个非常有用的工具,但是应当引起注意的是专场动画监听——Transition.TransitionListener。使用监听可以在进入和退出动画生命周期中的特定点执行一些操作,给你更多让应用如何表现的控制权。为了防止内容泄漏,需要在Ondestory()方法中移除监听。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    getWindow().getEnterTransition().addListener( new Transition.TransitionListener {
        @Override
        public void onTransitionStart(Transition transition) {
     
        }
     
        @Override
        public void onTransitionEnd(Transition transition) {
     
        }
     
        @Override
        public void onTransitionCancel(Transition transition) {
     
        }
     
        @Override
        public void onTransitionPause(Transition transition) {
     
        }
     
        @Override
        public void onTransitionResume(Transition transition) {
     
        }
    });

    Activity专场动画之元素共享

    除了标准的过渡动画,现在支持在两个activity过渡动画过程中共享元素。第一件要做的就是设置activity,使用内容转场动画并且允许覆盖转场动画。可以通过样式来设置:

    1
    2
    3
    <item name="android:windowContentTransitions">true</item>
    <item name="android:windowAllowEnterTransitionOverlap">true</item>
    <item name="android:windowAllowExitTransitionOverlap">true</item>

    元素共享动画也可以在代码中设置,此例中,我将使用样式来完成:

    1
    2
    <item name="android:windowSharedElementEnterTransition">@transition/changebounds</item>
    <item name="android:windowSharedElementExitTransition">@transition/changebounds</item>

    Changebounds转场动画被定义以xml文件的形式存放在资源文件中。注意,我增加了两位两个属性:时长和插值器,让动画更有趣。

    1
    2
    3
    4
    5
    changebounds.xml:
    <changeBounds
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="1000"
        android:interpolator="@android:interpolator/bounce" />

    下一步就是,确定在两个activity的布局文件中都使用实现Comparable接口的View类型(此例中使用ImageView),并且他们的viewName 属性值必须相同。在第一个activity中具有共享元素的View是这样的:

    1
    2
    3
    4
    5
    <ImageView
        android:id="@+id/image"
        android:viewName="image"
        android:layout_width="match_parent"
        android:layout_height="250dp" />

    第二个activity中的是这样的:

    1
    2
    3
    4
    5
    6
    <ImageView
        android:id="@+id/image"
        android:layout_alignParentBottom="true"
        android:viewName="image"
        android:layout_width="match_parent"
        android:layout_height="250dp" />

    既然所有的xml设置都准备好了,我们可以开始在执行动画的activity中写代码了。在第一个activity中我们设置父类容器视图setTransitionGroup为false,然后获取我们想要共享元素的ImageView的drawable,把它转变为字节流对象放到intent的bundle中。然后,为ImageView使用场景动画转换创建ActivityOptions 对象,开启下一个activity。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    Intent intent = new Intent( this, SharedElementSecondAnimationActivity.class );
     
    ((ViewGroup) mImageView.getParent()).setTransitionGroup( false );
     
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    ( (BitmapDrawable) mImageView.getDrawable() ).getBitmap().compress(Bitmap.CompressFormat.PNG, 100, stream);
    intent.putExtra( "image", stream.toByteArray() );
     
    ActivityOptions options;
     
    try {
        options = ActivityOptions.makeSceneTransitionAnimation( this, mImageView, "image" );
    } catch( NullPointerException e ) {
        Log.e( "SharedElementAnimationChangeBoundsActivity", "Did you set your ViewNames in the layout file?" );
        return;
    }
     
    if( options == null ) {
        Log.e("sharedelementanimation", "Options is null. Something broke. Good luck!");
    } else {
        startActivity(intent, options.toBundle());
    }

    在第二个activity中,从Intent的bundle中读取字节流并解码为bitmap对象,然后把它设置到Imageview上。第二个activity也重写了onBackPressed()方法,为了当返回键按下的时候执行退出动画。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_shared_element_second_animation);
        mImageView = (ImageView) findViewById( R.id.image );
     
        byte[] byteArray = getIntent().getByteArrayExtra("image");
        Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
        mImageView.setImageBitmap(bitmap);
    }
     
    @Override
    public void onBackPressed() {
        super.onBackPressed();
        finishAfterTransition();
    }

    基于以上这些我们完成了共享元素转换动画,在第二个activity中共享元素被移动到新的位置,并且有一个回弹效果。

    Shared Element

    这几个动画的例子仅是android L的冰山一角,而且没有涉及Kit Kat中引入的场景动画。我希望这篇教程帮助其他开发者学习到新的东西,使用动画让应用不但好看而且有趣。

  • 相关阅读:
    SpringBoot系列之缓存使用教程
    Dubbo系列之常用配置用法简介
    SpringBoot系列之集成Dubbo的方式
    JavaScript系列之回调函数callback
    JavaScript系列之事件冒泡机制简介
    Oracle基础之保留字和关键字
    Oracle调优之no_unnest和unnest用法简介
    InnoSetup 以命令行自动编译打包
    InnoSetup 脚本打包及管理员权限设置
    C# 获取系统当前IE版本号
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4802842.html
Copyright © 2020-2023  润新知