fragment 动画
使用 setcustomanimations 绘制转场动画
概述
在 android 中,可以使用 setcustomanimations()
方法来绘制自定义的 fragment 转场动画。该方法接受四个参数,分别对应四种类型的动画:
- enter: 新 fragment 进入时的动画
- exit: 旧 fragment 离开时的动画
- popenter: 从 back stack 中弹出 fragment 时的动画
- popexit: 将 fragment 添加到 back stack 时的动画
步骤
1.创建动画资源文件。
转场动画可以使用 xml 动画资源文件来定义。每个动画资源文件定义一种类型的动画,例如 enter.xml
、exit.xml
、pop_enter.xml
和 pop_exit.xml
。
动画资源文件的格式与其他动画资源文件相同,可以使用各种动画属性来定义动画效果。例如,可以使用 alpha
属性来定义透明度变化,使用 translate
属性来定义位移变化,使用 scale
属性来定义缩放变化等等。
2.在 fragment 中设置自定义动画。
在 fragment 中,可以使用 setcustomanimations()
方法来设置自定义的转场动画。该方法接受四个参数,分别对应四个类型的动画资源文件的 id。
例如,以下代码设置了 fragment 进入和离开时的自定义动画:
fragment.setcustomanimations(r.anim.enter, r.anim.exit);
示例
以下是一个示例,演示如何使用 setcustomanimations()
方法来绘制自定义的 fragment 转场动画。
1. 创建动画资源文件
2. 在 fragment 中设置自定义动画
public class myfragment extends fragment { @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { // inflate the layout for this fragment view view = inflater.inflate(r.layout.fragment_my, container, false); // set custom animations setcustomanimations(r.anim.enter, r.anim.exit); return view; } }
效果
运行该示例后,可以看到 fragment 进入和离开时都会播放自定义的动画效果。
注意事项
- 使用
setcustomanimations()
方法设置自定义动画时,必须在 fragment 添加到 activity 之前调用该方法。 - 如果不设置自定义动画,则 fragment 会使用系统默认的转场动画。
进阶
除了使用 xml 动画资源文件来定义动画效果之外,还可以使用代码来定义动画效果。例如,可以使用 objectanimator
类来创建更加复杂的动画效果。
使用共享元素的动画
在 firstfragment
中:
public class firstfragment extends fragment { @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { return inflater.inflate(r.layout.fragment_first, container, false); } @override public void onviewcreated(view view, bundle savedinstancestate) { super.onviewcreated(view, savedinstancestate); imageview sharedimageview = view.findviewbyid(r.id.shared_image); sharedimageview.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { navigatetosecondfragment(sharedimageview); } }); } private void navigatetosecondfragment(view sharedelement) { secondfragment newfragment = new secondfragment(); fragmenttransaction transaction = getparentfragmentmanager().begintransaction(); // 设置退出动画 transitionset exittransition = new transitionset(); exittransition.addtransition(new fade()); exittransition.addtransition(new slide(gravity.start)); newfragment.setexittransition(exittransition); // 设置共享元素退出动画 transitionset sharedelementexittransition = new transitionset(); sharedelementexittransition.addtransition(new changebounds()); sharedelementexittransition.addtransition(new changetransform()); sharedelementexittransition.addtransition(new changeimagetransform()); newfragment.setsharedelementexittransition(sharedelementexittransition); // 设置进入动画 transitionset entertransition = new transitionset(); entertransition.addtransition(new fade()); entertransition.addtransition(new slide(gravity.end)); newfragment.setentertransition(entertransition); // 设置共享元素进入动画 transitionset sharedelemententertransition = new transitionset(); sharedelemententertransition.addtransition(new changebounds()); sharedelemententertransition.addtransition(new changetransform()); sharedelemententertransition.addtransition(new changeimagetransform()); newfragment.setsharedelemententertransition(sharedelemententertransition); // 添加共享元素 可以添加多个共享元素 transaction.addsharedelement(sharedelement, sharedelement.gettransitionname()); // 替换当前 fragment transaction.replace(r.id.fragment_container_view, newfragment); transaction.addtobackstack(tag); transaction.commit(); } }
在 secondfragment
中:
public class secondfragment extends fragment { @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); } @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { return inflater.inflate(r.layout.fragment_second, container, false); } }
recyclerview in
对于在 recyclerview 或 listview 中使用共享元素的情况,你可以在适配器的 onbindviewholder()
方法中为每个共享元素设置 transitionname
属性。
假设你有一个 recyclerview,其中的每个项目包含一个 imageview,并且你想要在这些 imageview 之间应用共享元素动画。在 recyclerview 的适配器中,你可以这样设置 transitionname
:
public class myadapter extends recyclerview.adapter{ private list datalist; public myadapter(list datalist) { this.datalist = datalist; } @nonnull @override public viewholder oncreateviewholder(@nonnull viewgroup parent, int viewtype) { view view = layoutinflater.from(parent.getcontext()).inflate(r.layout.item_layout, parent, false); return new viewholder(view); } @override public void onbindviewholder(@nonnull viewholder holder, int position) { mydata data = datalist.get(position); // 设置 transitionname holder.imageview.settransitionname("shared_image_" position); // 加载图片或其他数据 // glide.with(holder.imageview.getcontext()).load(data.getimage).into(holder.imageview); } @override public int getitemcount() { return datalist.size(); } public static class viewholder extends recyclerview.viewholder { imageview imageview; public viewholder(@nonnull view itemview) { super(itemview); imageview = itemview.findviewbyid(r.id.imageview); } } }
在这个示例中,我们在适配器的 onbindviewholder()
方法中为每个 imageview 设置了唯一的 transitionname
属性,例如 "shared_image_" position
。这样做可以确保 recyclerview 中的每个共享元素都具有唯一的 transitionname
,以便在共享元素动画中正确识别和匹配它们。
参考地址
chatgpt