美文网首页
Android动画 2:LayoutAnimation、ripp

Android动画 2:LayoutAnimation、ripp

作者: i冰点 | 来源:发表于2016-12-29 23:18 被阅读250次

    1、布局动画LayoutAnimation

    作用在ViewGroup上,当ViewGroup增加view时,为其添加动画过度效果,
    控制一组控件的动画

    在XML中定义

    <layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
        android:delay="50%"
        android:animationOrder="normal"
        android:animation="@anim/top_anim"
        />
    
    ---
    @anim/top_anim
    
    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate android:duration="400"
            android:fromYDelta="100%p"
            android:toXDelta="0%p"/>
    
        <alpha android:duration="300"
            android:fromAlpha="0"
            android:toAlpha="1"/>
    </set>
    
    

    其中

    • android:delay:动画播放的延时,第二个执行的控件,比第一个控件延迟多久执行
    • android:animationOrder:子控件动画的播放顺序,有三个取值normal(顺序)、reverse(反序)、random(随机)。
    • android:animation:子控件所要播放的动画,每个子空间都要执行一遍

    可以在需要应用该动画的ViewGroup中使用

    android:layoutAnimation="@anim/layout_animation"
    
    布局动画 布局动画

    也可以使用代码实现

        RelativeLayout container= (RelativeLayout) findViewById(R.id.container);
        ScaleAnimation scaleAnimation=new ScaleAnimation(0,4,0,4,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
        //每一个都是1s
        scaleAnimation.setDuration(1000);
        LayoutAnimationController layoutAnimationController=new LayoutAnimationController(scaleAnimation,0.8f);
        layoutAnimationController.setOrder(LayoutAnimationController.ORDER_REVERSE);
        container.setLayoutAnimation(layoutAnimationController);
    
    
    布局动画.gif

    参考:
    Android LayoutAnimation使用及扩展

    2、触摸反馈ripple
    • 可以为View设置有波纹的background:
    • selectableItemBackground:波纹被限制在控件的边界中
    • selectableItemBackgroundBorderless:波纹会呈圆形发散出去,不会被限制
       <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            ...
            android:background="?attr/selectableItemBackground" />
    
    • 可以使用android:colorControlHighlight属性,改变触摸反馈的颜色
    ?android:attr/selectableItemBackground ?android:attr/selectableItemBackgroundBorderless

    也可以自定义ripple

    • 可以为ripple设置子item,这样反馈就会被限制在控件的范围内;可以为item添加id(id=mask),就不会把该item层绘制在屏幕上了,同时又定义了边界
    <?xml version="1.0" encoding="utf-8"?>
    <ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="#4d000000">
         <!--1-->
        <item android:id="@android:id/mask">
            <shape >
                <solid android:color="@android:color/white"/>
            </shape>
        </item>
        <item >
            <shape >
                <stroke android:color="@color/colorAccent" android:width="1dp"/>
            </shape>
        </item>
    </ripple>
    
    
    触摸反馈,有mask,feedback的边界是stroke+solid 触摸反馈,没有mask,feedback的边界仅仅是stroke
    <?xml version="1.0" encoding="utf-8"?>
    <ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/colorPrimary">
    </ripple>
    
    触摸反馈,没有定义item,没有边界
    <?xml version="1.0" encoding="utf-8"?>
    <ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/colorPrimary">
        <item android:drawable="@color/colorAccent"/>
    </ripple>
    
    触摸动画有边界

    参考:
    触摸反馈1
    RippleDrawable

    3、揭露效果Circular Reveal

    当显示或隐藏一组 UI 元素时,揭露动画可为用户提供视觉连续性。
    可以使用ViewAnimationUtils.createCircularReveal()简单实现:

    Animator createCircularReveal (View view,  int centerX,  int centerY,  float startRadius,  float endRadius )
    

    view是执行circular reveal动画的控件

    属性动画 + 揭露动画

    关键代码如下:
    MainActivity 退出

    fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startX=(fab.getLeft()+app_bar.getRight())/2;
                startY=(fab.getTop()+app_bar.getBottom())/2;
                endX=(app_bar.getLeft()+app_bar.getRight())/2;
                endY=(app_bar.getTop()+app_bar.getBottom())/2;
                Path path=new Path();
                path.moveTo(0,0);
                path.lineTo(endX-startX,endY-startY);
                ObjectAnimator objectAnimator= ObjectAnimator.ofFloat(fab,"translationX","translationY",path);
                objectAnimator.start();
                objectAnimator.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        Intent intent=new Intent(MainActivity.this,SecondActivity.class);
                        intent.putExtra("cx",endX);
                        intent.putExtra("cy",endY);
                        //startActivity(intent);
                        ActivityOptionsCompat optionsCompat= ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this);
                        ActivityCompat.startActivity(MainActivity.this,intent,optionsCompat.toBundle());
                    }
                });
            }
        });
    

    MainActivity 重新进入

        @Override
        public void onActivityReenter(int resultCode, Intent data) {
            super.onActivityReenter(resultCode, data);
            Path path=new Path();
            path.moveTo(endX-startX,endY-startY);
            path.lineTo(0,0);
            ObjectAnimator objectAnimator=new ObjectAnimator().ofFloat(fab,"translationX","translationY",path);
            objectAnimator.start();
        }
    

    SecondActivity进入

        radius= (float) Math.hypot(widthPixels,heightPixels);
        root.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            root.getViewTreeObserver().removeOnPreDrawListener(this);
            Animator animator=ViewAnimationUtils.createCircularReveal(root,cx,cy,getResources().getDisplayMetrics().density*28,radius);
            animator.setDuration(1500);
            animator.start();
            return true;
        }
    });
    

    在view树,完成测量、分配空间,但绘制过程还没开始的时候播放动画

    SecondActivity退出

        @Override
        public void onBackPressed() {
            Animator animator=ViewAnimationUtils.createCircularReveal(root,cx,cy,radius,getResources().getDisplayMetrics().density*28);
            animator.setDuration(1000);
            animator.start();
            animator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    root.setBackgroundColor(Color.TRANSPARENT);
                    setResult(RESULT_OK);
                    ActivityCompat.finishAfterTransition(SecondActivity.this);
                }
            });
    
    

    SecondActivity的主题

        <style name="AppTheme.NoActionBar.CircuralRevealTheme">
            <item name="android:windowAnimationStyle">@null</item>
            <item name="android:windowBackground">@android:color/transparent</item>
            <item name="android:windowIsTranslucent">true</item>
        </style>
    

    因为默认情况下,SecondActivity窗口是有背景颜色的,如果不设置为透明(如上),扩展动画将显示在这个默认的窗口背景之上,而不是mainactivity的view之上。

    4、为视图状态改变添加动画

    可以在需要应用该动画的View中添加stateListAnimator

    android:stateListAnimator="@drawable/select_card_animator"
    

    或者使用代码设置

    StateListAnimator stateListAnimator=AnimatorInflater.loadStateListAnimator(context,R.drawable.select_card_animator);
    view.setStateListAnimator(stateListAnimator);
    

    select_card_animator如下:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    
        <item android:state_pressed="true">
            <set>
                <objectAnimator
                    android:duration="@android:integer/config_shortAnimTime"
                    android:propertyName="translationZ"
                    android:valueTo="10dp"
                    android:valueType="floatType" />
    
            </set>
        </item>
    
        <item>
            <set>
                <objectAnimator
                    android:duration="@android:integer/config_shortAnimTime"
                    android:propertyName="translationZ"
                    android:valueTo="0dp"
                    android:valueType="floatType" />
    
            </set>
        </item>
    </selector>
    
    StateListAnimator
    • animated-selector

    参考:
    https://developer.android.com/training/material/animations.html#Reveal
    </br>
    代码:
    https://coding.net/u/hongji/p/MyScrollViewDemo/git/blob/master/app/src/main/java/com/mojo/myscrollviewdemo/Main2Activity.java

    相关文章

      网友评论

          本文标题:Android动画 2:LayoutAnimation、ripp

          本文链接:https://www.haomeiwen.com/subject/mfddvttx.html