Android布局动画之animateLayoutChanges与LayoutTransition

关于布局动画是针对ViewGroup而言的,意指ViewGroup在增加子View或者删除子View时其子View的过渡动画,在Android官网有这么一个简单的例子,其效果如下,接下来我们就通过这个例子来入门

Android布局动画之animateLayoutChanges与LayoutTransition_第1张图片

最简单的布局动画实现

事实上,实现上面ViewGroup的布局动画非常简单,我们只要给子View所在的ViewGroup的xml中添加下面的属性即可:
android:animateLayoutChanges="true"
1

1

通过设置以上代码,当ViewGroup在添加View时,子View会呈现出过渡的动画效果,这个动画效果是android默认的显示效果,而且无法使用自定义的动画来替换这个效果,不过还是有其他方式可以实现自定义的过渡动画滴,这个我们后面会分析,下面看看android官方给的demo的代码实现: activity_layout_changes.xml布局文件

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

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

布局代码比较简单,使用了一个ScrollView包裹了LinearLayout布局并在LinearLayout中添加了属性android:animateLayoutChanges="true"
,启动了android自带的布局动画,之所以使用ScrollView,是为了在添加子View多时可以进行滑动,而TextView只不过在没有子view时一个提示语。接着看看子View的布局文件list_item_example.xml

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

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

主要控件有用于显示每个子View内容的TextView和用于响应删除子View事件的ImageButton,最后就是Activity的实现: LayoutChangesActivity.Java
package com.example.android.animationsdemo;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.support.v4.app.NavUtils;import android.view.LayoutInflater;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;/** * This sample demonstrates how to use system-provided, automatic layout transitions. Layout * transitions are animations that occur when views are added to, removed from, or changed within * a {@link ViewGroup}. * *

In this sample, the user can add rows to and remove rows from a vertical * {@link android.widget.LinearLayout}.

/public class LayoutChangesActivity extends Activity { private ViewGroup mContainerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_layout_changes); mContainerView = (ViewGroup) findViewById(R.id.container); } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); //响应添加事件的menu getMenuInflater().inflate(R.menu.activity_layout_changes, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: NavUtils.navigateUpTo(this, new Intent(this, MainActivity.class)); return true; case R.id.action_add_item: //添加子View findViewById(android.R.id.empty).setVisibility(View.GONE); addItem(); return true; } return super.onOptionsItemSelected(item); } private void addItem() { //实例化一个子View final ViewGroup newView = (ViewGroup) LayoutInflater.from(this).inflate( R.layout.list_item_example, mContainerView, false); // 随机设置子View的内容 ((TextView) newView.findViewById(android.R.id.text1)).setText( COUNTRIES[(int) (Math.random() * COUNTRIES.length)]); //设置删除按钮的监听 newView.findViewById(R.id.delete_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mContainerView.removeView(newView); // If there are no rows remaining, show the empty view. if (mContainerView.getChildCount() == 0) { findViewById(android.R.id.empty).setVisibility(View.VISIBLE); } } }); //添加子View mContainerView.addView(newView, 0); } /* * A static list of country names. */ private static final String[] COUNTRIES = new String[]{ "Belgium", "France", "Italy", "Germany", "Spain", "Austria", "Russia", "Poland", "Croatia", "Greece", "Ukraine", };}
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

代码比较简单,mContainerView作为子View的承载容器,我们可以不断添加子View,也可以移除子View,由于我们在布局文件中启动了android自带的布局动画,所以在添加子View或移除子View都会有过度动画,现在运行程序,效果如下:
Android布局动画之animateLayoutChanges与LayoutTransition_第2张图片

这就是android中最简单的布局动画
布局动画实之layoutAnimation

除了上面的布局动画外,有时我们可能需要第一次加载ListView或者GridView的时候能有个动画的过度效果,以便达到更好的体验,如下ListView加载子View的效果:
Android布局动画之animateLayoutChanges与LayoutTransition_第3张图片

  事实上实现这种效果也比较简单,我们只需要在ListView的布局文件中添加android:layoutAnimation=”@anim/layout”属性即可。接下来给出实现步骤: 实现动画效果 left_into.xml

1
2
3
4
5
6
7
8
9
10
11
12
13

1
2
3
4
5
6
7
8
9
10
11
12
13

这个比较简单,就一个平移和透明度的效果,接着创建layout_animation.xml

1
2
3
4
5

1
2
3
4
5

这里简单介绍一下layoutAnimation标签属性:
属性名
含义

android:delay
delay的单位为秒,表示子View进入的延长时间

android:animationOrder
子类的进入方式 ,其取值有,normal 0 默认 ,reverse 1 倒序 ,random 2 随机

android:animation
子view要执行的具体动画的文件,自定义即可

然后设置给listView控件即可,activity_listview.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

1
2
3
4
5
6
7
8
9
10
11
12
13
14

ListViewActivity.java代码如下:
package com.example.android.animationsdemo;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ListView;import android.widget.TextView;import java.util.ArrayList;import java.util.List;/** * Created by zejian * Time 16/9/17. * Description: */public class ListViewActivity extends Activity { private ListView listView; private List list; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_listview); listView= (ListView) findViewById(R.id.listView); initData(); listView.setAdapter(new Myadpter()); } public void initData(){ list = new ArrayList<>(); for(int i=1;i<30;i++){ list.add("布局动画listView测试_"+i); } } private class Myadpter extends BaseAdapter{ @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { TextView tv= new TextView(ListViewActivity.this); tv.setTextSize(20); tv.setHeight(100); tv.setText(list.get(position)); return tv; } }}
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

执行以上代码,效果就是前面我们给出listView进入的动态效果,这里特别注意的是,动画只在listView子View第一次进入时有效,如果后面动态给listView添加子View时,此动画效果无效,当然除了通过xml设置外,我们还可以通过代码动态设置,代码范例如下,这里就不演示了。
//通过加载XML动画设置文件来创建一个Animation对象,子View进入的动画Animation animation=AnimationUtils.loadAnimation(this, R.anim.left_into);//得到一个LayoutAnimationController对象;LayoutAnimationController lac=new LayoutAnimationController(animation);//设置控件显示的顺序;lac.setOrder(LayoutAnimationController.ORDER_REVERSE);//设置控件显示间隔时间;lac.setDelay(0.5f);//为ListView设置LayoutAnimationController属性;listView.setLayoutAnimation(lac);
1
2
3
4
5
6
7
8
9
10

1
2
3
4
5
6
7
8
9
10

通过AnimationUtils.loadAnimation加载子View的动画来并返回一个Animation对象,然后将Animation对象设置到LayoutAnimationController中并返回LayoutAnimationController对象,配置LayoutAnimationController对象的一些属性,最后设置到ListView中,其中LayoutAnimationController对应layoutAnimation标签,这里需要注意的是layoutAnimation动画不仅仅限于ListView,GridView中,也可用于一切ViewGroup中。
布局动画实之LayoutTransition

前面我们说过ViewGroup在设置android:animateLayoutChanges="true"
后在添加或者删除子view时可以启用系统带着的动画效果,但这种效果无法通过自定义动画去替换。不过还好android官方为我们提供了LayoutTransition类,通过LayoutTransition就可以很容易为ViewGroup在添加或者删除子view设置自定义动画的过渡效果了。   LayoutTransition类用于当前布局容器中需要View添加,删除,隐藏,显示时设置布局容器子View的过渡动画。也就是说利用LayoutTransition,可以分别为需添加或删除的View对象在移动到新的位置的过程添加过渡的动画效果。我们可以通过setLayoutTransition()方法为布局容器ViewGroup设置LayoutTransition对象,代码如下:
//初始化容器动画LayoutTransition mTransitioner = new LayoutTransition();container.setLayoutTransition(mTransitioner);
1
2
3

1
2
3

一般地,Layout中的子View对象有四种动画变化的形式,如下:
属性值
含义

LayoutTransition.APPEARING
子View添加到容器中时的过渡动画效果。

LayoutTransition.CHANGE_APPEARING
子View添加到容器中时,其他子View位置改变的过渡动画

LayoutTransition.DISAPPEARING
子View从容器中移除时的过渡动画效果。

LayoutTransition.CHANGE_DISAPPEARING
子View从容器中移除时,其它子view位置改变的过渡动画

LayoutTransition.CHANGING
子View在容器中位置改变时的过渡动画,不涉及删除或者添加操作

下面给出一个例子,先看布局文件activity_layout_animation.xml

你可能感兴趣的:(Android布局动画之animateLayoutChanges与LayoutTransition)