美文网首页
动画之ViewGroup

动画之ViewGroup

作者: zhaoyubetter | 来源:发表于2018-03-24 15:35 被阅读70次

    参考:

    1. https://blog.csdn.net/harvic880925/article/details/50785786
      非常感谢,
      没有自己的内容,基本上转自上面的博客,非常感谢!

    LayoutAnimation

    layoutAnimation和gridLayoutAnimation在API 1中就有的函数。所以他们也只能使用animtion来做动画,而不能使用animator。

    layoutAnimation的xml实现

    步骤:

    1. anim文件夹下,定义layout_animation文件:
    <layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
        android:animation="@android:anim/slide_in_left"
        android:animationOrder="normal"
        android:delay="20" />
    
    1. 在ViewGroup类型控件中,配置android:layoutAnimation,如:

    你妹RecylcerView测试,设置标签无效;通过代码并且要在设置后,马上加载数据才有效果,这是什么鬼,真是太坑了;

    <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:layoutAnimation="@anim/tween_layout"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    

    或通过代码(设置后马上加载数据)设置

        recycler.apply {
                layoutManager = LinearLayoutManager(context)
                addItemDecoration(DividerItemDecoration(context, LinearLayoutManager.VERTICAL))
                // 設置無效
                // layoutAnimation = AnimationUtils.loadLayoutAnimation(applicationContext, R.anim.tween_layout)
            }
    
            btn_start.setOnClickListener {
                // 有效,设置后马上加载数据
                recycler.layoutAnimation = AnimationUtils.loadLayoutAnimation(applicationContext, R.anim.tween_layout)
                adapter = Adapter(mutableListOf("java", "Android", "Python", "javascript"))
                recycler.adapter = adapter
            }
    

    注意:

    1. RecyclerView设置layoutanimation时机;
    2. android:layoutAnimation只在viewGroup创建的时候,才会对其中的item添加动画。在创建成功以后,再向其中添加item将不会再有动画。

    如:

    operator fun plus(item: String) {
              data += item
              notifyItemInserted(data.size - 1)
     }
    // 调用
    adapter + "Better${Random().nextInt(10)}"
    

    layoutAnimation字段说明

    1. delay:指每个Item的动画开始延时,取值是android:animation所指定动画时长的倍数,默认为0.5
    2. animationOrder: 指viewGroup中的控件动画开始顺序,取值有normal(正序)、reverse(倒序)、random(随机)
    3. animation:指定每个item入场所要应用的动画;(只能是anim资源文件夹下的动画资源)

    layoutAnimation的代码实现

    xml中layoutAnimation标签所对应的类为LayoutAnimationController,构造如下:

    public LayoutAnimationController(Animation animation)
    public LayoutAnimationController(Animation animation, float delay)
    

    animation对应xml中的android:animation属性,delay 为 android:delay属性;

    API方法,参考原博客:

    具体例子:

    btn_bycode.setOnClickListener {
        val anim = AnimationUtils.loadAnimation(baseContext, android.R.anim.slide_in_left)
        recycler.layoutAnimation = LayoutAnimationController(anim).apply {
            delay = 0.3f
            order = LayoutAnimationController.ORDER_REVERSE
        }
        adapter = Adapter(mutableListOf("java", "Android", "Python", "javascript"))
        recycler.adapter = adapter
    }
    

    GridLayoutAnimation

    android gridview 首次加载数据时,各子控件item的过渡动画;GridlayoutAnimation,仅能用于 android 原生控件 GridView;

    略,后门专门来弄一个RecyclerView;

    animateLayoutChanges与LayoutTransition

    在API 11之后,Android为了支持ViewGroup类控件,在添加和移除其中控件时自动添加动画,为我们提供了一个非常简单的属性:android:animateLayoutChanges=[true/false],所有派生自ViewGroup的控件都具有此属性,只要在XML中添加上这个属性,就能实现添加/删除其中控件时,带有默认动画了。

    注意:默认 layoutAnimation动画只是对首次加载数据有效;

    android:animateLayoutChanges属性

    通过给容器添加 android:animateLayoutChanges 并设置为true, 在添加或删除控件时,就有了自带动画效果了,默认是一个渐变的动画;

    <LinearLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="56dp"
            android:orientation="horizontal"
            android:animateLayoutChanges="true"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent">
    </LinearLayout>
    

    LayoutTransition

    android:animateLayoutChanges默认是一个渐变动画,无法自定义;如果我们想改变这个默认动画效果,需要使用到 LayoutTransition,这也是从API 11 开始支持的;

    使用LayoutTransition步骤:

    1. 创建实例;
    2. 创建动画并设置:
    3. 将LayoutTransaction设置进ViewGroup

    不知道怎么回事,使用kotlin来编写时,总是报错,Java代码正常:

    btn_layout_transition.setOnClickListener {
                val transition = LayoutTransition()
                val objAnimator = ObjectAnimator.ofFloat(container, "rotation", 0f, -90f, 90f, 0f)
                transition.setAnimator(LayoutTransition.APPEARING, objAnimator)
                container.layoutTransition = transition
    }
    

    报错为:
    layoutTransition 为 Unresolved reference: setLayoutTransition
    以后解决了,再来更新;

    Java 代码实现:

    // 1.创建实例
    LayoutTransition transition = new LayoutTransition();
    // 2. 创建动画并设置, 这里为添加子view时,动画
    transition.setAnimator(LayoutTransition.APPEARING,
                            ObjectAnimator.ofFloat(null, "rotation", 0f, -90f, 90f, 0f));
    // 3. 将LayoutTransaction设置进ViewGroup
    container.setLayoutTransition(transition);
    // 这样添加时,子 view 会有动画了
    container.addView(getCustomView());
    

    LayoutTransition.setAnimator 函数

    public void setAnimator(int transitionType, Animator animator)  
    

    参数说明:

    • transitionType 表示当前应用动画的对象范围,取值有:
      1. APPEARING —— 元素在容器中出现时所定义的动画。
      2. DISAPPEARING —— 元素在容器中消失时所定义的动画。
      3. CHANGE_APPEARING —— 由于容器中要显现一个新的元素,其它需要变化的元素所应用的动画
      4. CHANGE_DISAPPEARING —— 当容器中某个元素消失,其它需要变化的元素所应用的动画
    • animator 即响应的属性动画;

    LayoutTransition.APPEARING与LayoutTransition.DISAPPEARING
    表示入场动画,与出场动画

    // LayoutTransition.APPEARING,入场
    LayoutTransition transition = new LayoutTransition();
        transition.setAnimator(LayoutTransition.APPEARING,
                ObjectAnimator.ofFloat(null, "alpha", 0.5f, 1.0f, 0.8f, 1.0f));
    
    // LayoutTransition.DISAPPEARING,出场
    transition.setAnimator(LayoutTransition.DISAPPEARING,
                ObjectAnimator.ofFloat(null, "rotationX", 0f, 90f));
    
    // 设置给ViewGroup
    container.setLayoutTransition(transition);
    

    CHANGE_APPEARING与CHANGE_DISAPPEARING

    CHANGE_APPEARING的使用

    在添加控件时,除了被添加控件本身的入场动画以外,其它需要移动位置的控件,在移动位置时,也被添加上了动画(left点位移动画),这些除了被添加控件以外的其它需要移动位置的控件组合,所对应的动画就是LayoutTransition.CHANGE_APPEARING

    // 添加元素调用addView()方法时,index之后的元素才有动画
    // 必须的left,top
    PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 100, 0);
    PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 1, 1);
                    transition.setAnimator(LayoutTransition.CHANGE_APPEARING,
                            ObjectAnimator.ofPropertyValuesHolder(container, pvhLeft,pvhTop));
    container.setLayoutTransition(transition);
    container.addView(getCustomView(), 0);  // 0 之后的所有元素都有动画
    

    注意的地方:

    1. LayoutTransition.CHANGE_APPEARING和LayoutTransition.CHANGE_DISAPPEARING必须使用PropertyValuesHolder所构造的动画才会有效果,不然无效!
    2. 在构造PropertyValuesHolder动画时,”left”、”top”属性的变动是必写的。如果不需要变动,则直接写为:
    PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left",0,0);  
    PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top",0,0);  
    
    1. 在构造PropertyValuesHolder时,所使用的ofInt,ofFloat中的参数值,第一个值和最后一个值必须相同,不然此属性所对应的的动画将被放弃,在此属性值上将不会有效果;
    // 第一个value与最后一个value必须相等
    PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left",0,100,0);  
    

    4.在构造PropertyValuesHolder时,所使用的ofInt,ofFloat中,如果所有参数值都相同,也将不会有动画效果;

    // 动画无效
    PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left",100,100);  
    

    CHANGE_DISAPPEARING的使用

    PropertyValuesHolder outLeft = PropertyValuesHolder.ofInt("left", 0, 0);
    PropertyValuesHolder outTop = PropertyValuesHolder.ofInt("top", 0, 0);
    PropertyValuesHolder rotation = PropertyValuesHolder.ofFloat("rotationY", 0f, 90f, 0f);
    
    transition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING,
                        ObjectAnimator.ofPropertyValuesHolder(container, outLeft, outTop, rotation));
    if(container.getChildCount() > 0) {
        container.removeViewAt(0);
    }
    

    坑真多,不用为妙

    LayoutTransition其他函数

    /** 
     * 设置所有动画完成所需要的时长 
     */  
    public void setDuration(long duration)  
    /** 
     * 针对单个type,设置动画时长; 
     * transitionType取值为:APPEARING、DISAPPEARING、CHANGE_APPEARING、CHANGE_DISAPPEARING 
     */  
    public void setDuration(int transitionType, long duration)   
    /** 
     * 针对单个type设置插值器 
     * transitionType取值为:APPEARING、DISAPPEARING、CHANGE_APPEARING、CHANGE_DISAPPEARING 
     */  
    public void setInterpolator(int transitionType, TimeInterpolator interpolator)  
    /** 
     * 针对单个type设置动画延时 
     * transitionType取值为:APPEARING、DISAPPEARING、CHANGE_APPEARING、CHANGE_DISAPPEARING 
     */  
    public void setStartDelay(int transitionType, long delay)  
    /** 
     * 针对单个type设置,每个子item动画的时间间隔 
     */  
    public void setStagger(int transitionType, long duration)  
    

    setStagger

    //设置单个item间的动画间隔
    transition.setStagger(LayoutTransition.CHANGE_APPEARING, 100);
    

    监听函数
    在任何类型的LayoutTransition开始和结束时,都会调用TransitionListener的startTransition和endTransition方法。

    transition.addTransitionListener(new LayoutTransition.TransitionListener() {
        public void startTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType) {}
        public void endTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType) {}
    });
    

    参数说明:

    • LayoutTransition transition:当前的LayoutTransition实例
    • ViewGroup container:当前应用LayoutTransition的container
    • View view:当前在做动画的View对象
    • int transitionType:当前的LayoutTransition类型,取值有:APPEARING、DISAPPEARING、CHANGE_APPEARING、CHANGE_DISAPPEARING

    相关文章

      网友评论

          本文标题:动画之ViewGroup

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