视图动画介绍

视图动画(View animation)

视图动画(View animation)分为两类:补间动画(Tween animation)逐帧动画(Frame animation),两者都可以在XML中声明

一、帧动画

Frame animation

也叫Drawable动画,Android3.0之前版本只有帧动画

在 XML 中定义的按顺序显示一系列图片的动画(如电影)。

文件位置:res/drawable/filename.xml,编译后执指向AnimationDrawable

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot=["true" | "false"] >
    <item
        android:drawable="@[package:]drawable/drawable_resource_name"
        android:duration="integer" />
</animation-list>

<!--
animation-list:必需。必须是根元素,包含一个或多个<item>元素
item:单帧动画
 -->

使用如下,建议设置的图片不宜过多、过大,以防止因为内存不够出现OOM

val rocketImage: ImageView = findViewById(R.id.rocket_image)
rocketImage.setBackgroundResource(R.drawable.rocket_thrust)
// 设置Background和设置ImageResource是一样的效果:
rocketImage.setImageResource(R.drawable.rocket_thrust)
(rocketImage.background as AnimationDrawable).start()
// 或者这样也可以 (rocketImage.background as Animatable).start()

// 清除动画(android.view.View:clearAnimation())
rocketImage.clearAnimation()

二、补间动画

Tween animation

Android3.0之后增加了补间动画

民间有的也叫View动画,是指android.view.animation包下的类,只能被用来设置给 View,缺点是比如当控件移动之后,接收点击的控件的位置不会跟随移动

用于对图形执行 旋转`、淡出移动拉伸

文件位置:res/anim/filename.xml,编译后指向Animatioin

① 基础使用

  1. xml的方式:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@[package:]anim/interpolator_resource"
    android:shareInterpolator=["true" | "false"] >
    <alpha
        android:fromAlpha="float"
        android:toAlpha="float" />
    <scale
        android:fromXScale="float"
        android:toXScale="float"
        android:fromYScale="float"
        android:toYScale="float"
        android:pivotX="float"
        android:pivotY="float" />
    <translate
        android:fromXDelta="float"
        android:toXDelta="float"
        android:fromYDelta="float"
        android:toYDelta="float" />
    <rotate
        android:fromDegrees="float"
        android:toDegrees="float"
        android:pivotX="float"
        android:pivotY="float" />
    <set>
        ...
    </set>
</set>

使用:

val anim = AnimationUtils.loadAnimation(context, R.anim.traslate)
ivImage.startAnimation(anim)
  1. Java代码的方式:
// 单个使用
val alphaAnim = AlphaAnimation(0f, 1f)
alphaAnim.duration = 500
alphaAnim.fillAfter = true
alphaAnim.interpolator = AccelerateInterpolator()
ivImage.animation = alphaAnim
alphaAnim.start()

// 组合使用,true:共享插值器,false:不共享
val animationSet = AnimationSet(true)
animationSet.addAnimation(alphaAnim)
...
ivImage.startAnimation(animationSet)
Java类名描述
AnimationSet容纳其他动画元素(<alpha><scale><translate><rotate>)或其他 <set> 元素的容器
AlphaAnimation淡入或淡出动画
ScaleAnimation大小调整动画。您可以通过指定 pivotXpivotY,来指定图片向外(或向内)扩展的中心点。例如,如果这两个值为 0、0(左上角),则所有扩展均向右下方向进行
TranslateAnimation竖直和/或水平移动。支持采用以下三种格式之一的以下属性:从 -100 到 100 的以“%”结尾的值,表示相对于自身的百分比;从 -100 到 100 的以“%p”结尾的值,表示相对于其父项的百分比;不带后缀的浮点值,表示绝对值
RotateAnimation旋转动画

② 常规使用介绍

  1. Popwindow设置动画

    val popupWindow = PopupWindow(ivImage, ViewGroup.LayoutParams.WRAP_CONTENT, 													ViewGroup.LayoutParams.WRAP_CONTENT)
    popupWindow.animationStyle = R.style.pop_anim
    
    <!--pop_anim-->
    <style name="pop_anim">
        <item name="android:windowEnterAnimation">@anim/pop_in</item>
        <item name="android:windowExitAnimation">@anim/pop_out</item>
    </style>
    
    <!--anim/pop_in.xml-->
    <set>
       <alpha
            android:fromAlpha="0"
            android:toAlpha="1"
            android:duration="2000"
            />         
    </set>
    
    <!--anim/pop_out.xml-->
    <set>
       <alpha
            android:fromAlpha="1"
            android:toAlpha="0"
            android:duration="2000"
            />         
    </set>
    
  2. Activity设置页面跳转、退出动画效果

    方式一:借助overridePendingTransition(int entAnim, int exitAnim),在 startActivity 或 finish 后面。5.0以后用ActivityOptions来实现过渡动画

    startActivity(new Intent(MainActivity.this,SecondActivity.class));
    overridePendingTransition(R.anim.activity_in,R.anim.activity_out);
    

    方式二:style,5.0以后用ActivityOptions来实现过渡动画

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <style name="AppTheme" parent="Theme.AppCompat.Light" >
            <!--设置windowAnimationStyle属性-->
            <item name="android:windowAnimationStyle">@style/ActivityAnim</item>
        </style>
    
        <style name="ActivityAnim">
            <item name="android:activityOpenEnterAnimation">@anim/activity_in</item>
            <item name="android:activityOpenExitAnimation">@anim/activity_out</item>
            <item name="android:activityCloseEnterAnimation">@anim/activity_close_in</item>
            <item name="android:activityCloseExitAnimation">@anim/activity_close_out</item>
        </style>
    </resources>
    
  3. 给 ViewGroup 子控件添加动画

    给ViewGroup指定android:layoutAnimation属性加上动画资源

    <!-- anm/anim_layout.xml -->
    <layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
        android:delay="0.2"
        android:animationOrder="reverse"
        android:animation="@anim/act_in"/>
    
    <!-- layout/act_main.xml -->
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layoutAnimation="@anim/anim_layout">
    
        <include layout="@layout/appbar_toolbar" />
        ...
    </LinearLayout>
    
    

    还可以通过代码指定,LayoutAnimationController对应xml中的layoutAnimation

    val linearLayout = view.findViewById<LinearLayout>(R.id.id_item_btn)
    val anim = AnimationUtils.loadAnimation(context, R.anim.act_in)
    val controller = LayoutAnimationController(anim)
    controller.delay = 0.2f
    controller.order = LayoutAnimationController.ORDER_REVERSE
    linearLayout.layoutAnimation = controller
    

    ③ 补间动画原理

    当前动画开始后,View会周期性调用它的getTransformation方法不断获得动画结果,方法返回表示的是当前动画是否结束

    // Animation.java
    public boolean getTransformation(long currentTime, Transformation outTransformation){
        //...
         if ((normalizedTime >= 0.0f || mFillBefore) && (normalizedTime <= 1.0f || mFillAfter)) {
             //...
             // 插值器
             final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);
             // 子类完成实际的动画逻辑
             applyTransformation(interpolatedTime, outTransformation);
         }
    }
    

    Transformation:包含Matrix和Alpha字段,用来记录某次动画计算的变换结果

    // ViewGroup.java
    Transformation getChildTransformation() {
            if (mChildTransformation == null) {
                mChildTransformation = new Transformation();
            }
            return mChildTransformation;
        }
    

    调用栈追溯

    // View.java
    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
        //...
        final Animation a = getAnimation();
        if (a != null) {
            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
            //...
        }
    }
    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
                Animation a, boolean scalingRequired) {
        //...
        final Transformation t = parent.getChildTransformation();
      	boolean more = a.getTransformation(drawingTime, t, 1f);
        //...
    }
     
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值