这个demo演示了如何利用setcustomAnimation实现Fragment的切换动画
* 实现自定义动画的类是ObjectAnimator,不仅用于fragment,也可用于view。
* 注意定义动画一定要replace方法之前执行.
* 动画资源文件需要放在res\animator\目录下,且根标签是set, objectAnimator, or valueAnimator三者之一。
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:layout_marginBottom="5dp">
<Button
android:id="@+id/push"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Push"/>
<Button
android:id="@+id/pop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Pop"/>
</LinearLayout>
</LinearLayout>
res目录下新建animator目录,定义动画效果
push_enter.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<objectAnimator
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:valueFrom="300"
android:valueTo="0"
android:duration="3000"
android:propertyName="X">
</objectAnimator>
<objectAnimator
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:valueFrom="0.0"
android:valueTo="1.0"
android:valueType="floatType"
android:duration="3000"
android:propertyName="alpha">
</objectAnimator>
</set>
push_exit.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<objectAnimator
android:duration="3000"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:propertyName="X"
android:valueFrom="0"
android:valueTo="300" >
</objectAnimator>
<objectAnimator
android:duration="3000"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:propertyName="alpha"
android:valueFrom="1.0"
android:valueTo="0.0"
android:valueType="floatType" >
</objectAnimator>
</set>
pop_enter.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<objectAnimator
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:valueFrom="-300"
android:valueTo="0"
android:duration="3000"
android:propertyName="X">
</objectAnimator>
<objectAnimator
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:valueFrom="0.0"
android:valueTo="1.0"
android:valueType="floatType"
android:duration="3000"
android:propertyName="alpha">
</objectAnimator>
</set>
pop_exit.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<objectAnimator
android:duration="3000"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:propertyName="X"
android:valueFrom="0"
android:valueTo="-300" >
</objectAnimator>
<objectAnimator
android:duration="3000"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:propertyName="alpha"
android:valueFrom="1.0"
android:valueTo="0.0"
android:valueType="floatType" >
</objectAnimator>
</set>
MainActivity
public class MainActivity extends Activity {
private int mStackLevel = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button push=(Button) findViewById(R.id.push);
Button pop=(Button) findViewById(R.id.pop);
push.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
addFragmentToStack();
}
});
pop.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
if(savedInstanceState==null){
FragmentTransaction ft=getFragmentManager().beginTransaction();
CountingFragment cf=CountingFragment.getInstance(mStackLevel);
ft.add(R.id.frameLayout, cf,"currentfragment");
ft.commit();
}else{
mStackLevel=savedInstanceState.getInt("stacklevel", 1);
}
}
@Override
public void onBackPressed() {
super.onBackPressed();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("stacklevel", mStackLevel);
}
protected void addFragmentToStack() {
mStackLevel++;
CountingFragment newFragment = CountingFragment
.getInstance(mStackLevel);
// 开启push事务则向activity中添加新的fragment
FragmentTransaction ft = getFragmentManager().beginTransaction();
// 设置自定义动画,前两个参数表示Fragment被推进任务栈时的动画效果
// 被两个参数表示Fragment被从任务栈推出时的动画效果
ft.setCustomAnimations(R.animator.push_enter, R.animator.push_exit,
R.animator.pop_enter, R.animator.pop_exit);
ft.replace(R.id.frameLayout, newFragment, "currentfragment");
/*
* 将事务添加到后台堆栈,当事务被提交后将执行事务,当从按返回键从堆栈中推出时则事务执行相反 的操作
*/
ft.addToBackStack(null);
ft.commit();
}
public static class CountingFragment extends Fragment {
private int mNum;
public static CountingFragment getInstance(int num) {
CountingFragment cf = new CountingFragment();
Bundle args = new Bundle();
args.putInt("level", num);
cf.setArguments(args);
return cf;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 将传递进来的数据取出
Bundle args = getArguments();
mNum = args != null ? args.getInt("level") : 1;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// 使用取出的数据
View v = inflater.inflate(R.layout.hello, container, false);
TextView tv = (TextView) v.findViewById(R.id.text);
tv.setText("Fragment #:" + mNum);
tv.setBackground(getResources().getDrawable(
android.R.drawable.gallery_thumb));
return v;
}
}
}