Android 系列笔记 十一 - Fragment 与 动画

Fragment 生命周期

Fragment必须是依存与Activity而存在的,因此Activity的生命周期会直接影响到Fragment的生命周期。官网这张图很好的说明了两者生命周期的关系:

Fragment 生命周期

可以看到Fragment比Activity多了几个额外的生命周期回调方法:
onAttach(Activity)
当Fragment与Activity发生关联时调用。
onCreateView(LayoutInflater, ViewGroup,Bundle)
创建该Fragment的视图
onActivityCreated(Bundle)
当Activity的onCreate方法返回时调用
onDestoryView()
与onCreateView想对应,当该Fragment的视图被移除时调用
onDetach()
与onAttach相对应,当Fragment与Activity关联被取消时调用
注意:除了onCreateView,其他的所有方法如果你重写了,必须调用父类对于该方法的实现,

Fragment

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
public class Fragment1 extends Fragment{
TextView tv;
EditText et;
Button button;
//返回的View对象会作为fragment1的内容显示在屏幕上
@Override
public view onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState){
View view = inflater.inflate(R.layout.fragment1, null);
tv = (TextView)view.findViewById(R.id.textview);
et = (EditText)view.findViewById(R.id.edittext);
button = (Button)view.findViewById(R.id.button);

button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
String text = et.getText().toString();
((MainActivity)getActivity()).setText(text);
}
});
return view;
}

public void setText(String text){
tv.setText(text);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class MainActivity extends Activity{
TextView tv;

public void click(View v){
//把fragment界面显示在帧布局中
Fragment1 fg1 = new Fragment1();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
//资源id: 要显示布局的id
ft.replace(R.id.fl, fg1);
ft.commit();
}

public void setText(String text){
tv.setText(text);
}
}

帧动画

多张图片快速切换,形成动画效果

资源文件 frameanimation.xml

1
2
3
4
5
6
7
8
9
10
11
12
<!--false 表示会循环播放-->
<animation-list android:oneshot="false">
<item android:drawable="@drawable/pic1" android:duration="200" />
<item android:drawable="@drawable/pic2" android:duration="200" />
<item android:drawable="@drawable/pic3" android:duration="200" />
<item android:drawable="@drawable/pic4" android:duration="200" />
<item android:drawable="@drawable/pic5" android:duration="200" />
<item android:drawable="@drawable/pic6" android:duration="200" />
<item android:drawable="@drawable/pic7" android:duration="200" />
<item android:drawable="@drawable/pic8" android:duration="200" />
<item android:drawable="@drawable/pic9" android:duration="200" />
</animation-list>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MainActivity extends Activity{
ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

iv = (ImageView)findViewById(R.id.imageView);
//把帧动画的资源文件指定为iv的背景
iv.setBackgroundResource(R.drawable.frameanimation);
AnimationDrawable ad = (AnimationDrawable)iv.getBackground();
ad.start();
}
}

补间动画

组件由原始状态向终极状态转变时,为了让过渡更自然而自动生成的动画

平移动画

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
//平移
public void translate(View v){
//定义位移动画
/*
10: 表示 x 坐标起始位置
imageView 的真实 x 坐标 + 10
100: 表示 x 坐标的结束位置
20: 表示 y 坐标的起始位置
200: 表示 y 坐标的结束位置
*/
TranslateAnimation ta = new TranslateAnimation(
10, 100, 20, 200);

/*
Animation.RELATIVE_TO_SELF, 1: x 坐标的起始位置
imageView 的真实 x + 1 * imageView 的宽度
Animation.RELATIVE_TO_SELF, 0.5f: y 坐标的起始位置
imageView 的真实 y + 0.5 * imageView 的高度
*/
TranslateAnimation ta = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 1,
Animation.RELATIVE_TO_SELF, 3,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 2);
//设置播放时间
ta.setDuration(2000);
//会播放两次
ta.setRepeatCount(1);
//重复的那一次动画的模式
ta.setRepeatMode(Animation.REVERSE);
imageView.startAnimation(ta);
}

缩放

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//缩放
public void scale(View v){
/*
0.5f: 表示 x 坐标缩放的初始位置
0.5 * imageView 的宽度
2: 表示 x 坐标缩放的结束位置
2 * imageView 的宽度
*/
ScaleAnimation sa = new ScaleAnimation(0.5f, 2, 0.1f, 3);

//设置缩放的中心点
ScaleAnimation sa = new ScaleAnimation(0.5f, 2, 0.1f, 3,
imageView.getWidth() / 2, imageView.getHeight() / 2);
sa.setDuration(2000);
sa.setRepeatCount(1);
sa.setRepeatMode(Animation.REVERSE);
//填充动画的结束位置
sa.setFillAfter(true);
imageView.startAnimation(sa);
}

透明

1
2
3
4
5
public void alpha(View v){
AlphaAnimation aa = new AlphaAnimation(0, 0.5f);
aa.setDuration(2000);
imageView.startAnimation(aa);
}

旋转

1
2
3
4
5
6
7
public void rotate(View v){
//相对中心点,从20度转到180度
RotateAnimation ra = new RotateAnimation(20, 180,
imageView.getWidth() / 2, imageView.getHeight() / 2);
ra.setDuration(2000);
imageView.startAnimation(ra);
}

补间动画集合

1
2
3
4
5
6
7
8
9
10
11
12
13
public void fly(View v){
AlphaAnimation aa = new AlphaAnimation(0, 0.5f);
aa.setDuration(2000);
RotateAnimation ra = new RotateAnimation(20, 180,
imageView.getWidth() / 2, imageView.getHeight() / 2);
ra.setDuration(2000);

AnimationSet set = new AnimationSet(false);
set.add(aa);
set.add(ra);

imageView.startAnimation(set);
}

属性动画:3.0 之后新特性

补间动画并没有改变控件的真实位置,只是重新绘制了界面

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
public void translate(View v){
TranslateAnimation ta = new TranslateAnimation(0, 150, 0, 0);
ta.setDuration(2000);
ta.setFillAfter(true);
imageView.startAnimation(ta);

//target: 动画作用于哪一个组件
//改变的是控件的哪一个属性
//都是经过哪些 x 坐标点
ObjectAnimator oa = ObjectAnimator.ofFloat(imageView,
"translationX", 10, 50, 20, 100);
oa.setDuration(2000);
oa.setRepeatCount(1);
oa.setRepeatMode(ValueAnimator.REVERSE);
oa.start();
}

//缩放
public void scale(View v){
ObjectAnimator oa = ObjectAnimator.ofFloat(imageView, "scaleX", 1, 1.6f, 1.2f, 2);
oa.setDuration(2000);
oa.start();
}

//透明
public void alpha(View v){
ObjectAnimator oa = ObjectAnimator.ofFloat(imageView, "alpha", 0, 0.6f, 0.2f, 1);
oa.setDuration(2000);
oa.start();
}

//旋转
public void rotate(View v){
ObjectAnimator oa = ObjectAnimator.ofFloat(imageView, "rotation", 0, 90, 180, 90, 360);
oa.setDuration(2000);
oa.start();
}

//属性动画集合
public void fly(View v){
AnimatorSet set = new AnimatorSet();

ObjectAnimator oa1 = ObjectAnimator.ofFloat(imageView, "rotation", 0, 90, 180, 90, 360);
oa1.setDuration(2000);

ObjectAnimator oa2 = ObjectAnimator.ofFloat(imageView, "alpha", 0, 0.6f, 0.2f, 1);
oa2.setDuration(2000);

//按顺序执行
set.playSequentially(oa1, oa2);
//所有动画一起执行
//set.playTogether(oa1, oa2);
set.start();
}

使用xml定义属性动画

资源文件类型:Property Animation
资源文件名 objanimator.xml

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="utf-8"?>
<set>
<objectAnimator
android:propertyName="translationX"
android:duration="2000"
android:repeatCount="1"
android:repeatMode="reverse"
android:valueFrom="-100"
android:valueTo="100"/>
</set>

1
2
3
4
5
public void xml(View v){
Animator at = AnimatorInflater.loadAnimator(this, R.animator.objanimator);
at.setTarget(imageView);
at.start();
}