动画之ViewGroup

参考:

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

LayoutAnimation

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

layoutAnimation的xml实现

步骤:

  1. anim文件夹下,定义layout_animation文件:

  1. 在ViewGroup类型控件中,配置android:layoutAnimation,如:

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


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

    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, 在添加或删除控件时,就有了自带动画效果了,默认是一个渐变的动画;



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)