我有使用以下xml实现Navigation Drawer的MainActivity:
<android.support.v4.widget.DrawerLayout
xmlns:android ="http://schemas.android.com/apk/res/android"
android:id ="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/container_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<include
android:id="@+id/toolbar"
layout="@layout/toolbar" />
</LinearLayout>
<FrameLayout
android:id="@+id/content"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#FFFFFF"/>
</LinearLayout>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity ="start"
>
<ListView
android:id="@+id/drawerList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="5dp"
android:divider="@color/material_blue_grey_800"
android:dividerHeight="1dp"
android:background="#FFFFFF"
/>
</RelativeLayout>
</android.support.v4.widget.DrawerLayout>
现在我的listview中有3个项目,点击其中任意一项,我的代码将Framelayout替换为如下特定片段:
Fragment f1 = new Fragment()
FragmentTransaction ft = getSupportFragmentManager().beginTransaction()
ft.setCustomAnimations(R.anim.slide_in,R.anim.hyper_out,R.anim.hyper_in,R.anim.slide_out)
ft.replace(R.id.content, f1).addToBackStack(null).commit();
上面的代码可以很好地根据需要用自定义动画替换片段。但是,我的问题是如何在片段事务期间为工具栏和片段设置动画。
所有片段都有各自的工具栏标题,这些标题在每个片段类的onActivityCreated()方法中通过以下代码进行更改:
((AppCompatActivity)getActivity()).getSupportActionBar().setTitle("Title");
我应该将动画应用到我的布局来掩盖工具栏吗?
答案 0 :(得分:1)
我也有同样的问题-它似乎在每个应用程序的开发过程中都会弹出,而我从来没有解决过,而是恢复到一些低于标准的解决方案。现在我有了解决方案!
在Kotlin中回答,但是在Java中适用相同的原理。
要为Toolbar
动画和FragmentTransaction
动画制作动画,首先需要一种方法通知Activity/Fragment
的{{1}}动画正在开始/结束。我称Toolbar
为Activity/Fragment
的{{1}}
首先,定义Toolbar
可以实现的接口以接收回调:
ToolbarHost
我还添加了一个扩展方法,以帮助子ToolbarHost
找到对接收回调感兴趣的父interface FragmentAnimationListener {
fun onAnimationStart(fragment: Fragment, animation: Animation, enter: Boolean)
fun onAnimationEnd(fragment: Fragment, animation: Animation, enter: Boolean)
}
:
Fragment
现在,我们将以下内容添加到要在屏幕上进行动画处理的子级ToolbarHost
中。我建议将以下内容添加到基fun Fragment.findParentAnimationListener(): FragmentAnimationListener? {
return when (parentFragment) {
is FragmentAnimationListener -> parentFragment as FragmentAnimationListener
null -> return activity as? FragmentAnimationListener
else -> parentFragment?.findParentAnimationListener()
}
}
类中。这将从Fragment
*截取给子Fragment
的动画中截取,添加一个侦听器,找到Fragment
,并通知我们动画的开始/结束。
FragmentTransaction
*这适用于通过ToolbarHost
提供的动画。我没有用不同类型的override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
var animation = super.onCreateAnimation(transit, enter, nextAnim)
if (animation == null && nextAnim != 0) {
animation = AnimationUtils.loadAnimation(activity!!, nextAnim)
}
val parentAnimationListener = findParentAnimationListener()
if (animation != null) {
animation.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {
parentAnimationListener?.onAnimationStart(this@BaseFragment, animation, enter)
}
override fun onAnimationEnd(animation: Animation) {
parentAnimationListener?.onAnimationEnd(this@BaseFragment, animation, enter)
}
override fun onAnimationRepeat(animation: Animation?) {
}
})
}
return animation
}
动画或没有FragmentTransaction.setCustomAnimation(int, int, ..)
动画进行过测试。
现在我们的FragmentTransaction
知道孩子FragmentTransaction
何时执行其动画,我们可以考虑对工具栏进行动画处理。
假设您的ToolbarHost
是一个片段,我们首先实现Fragment
:
ToolbarHost
现在,我们要解决的一个问题是,由于我们将FragmentAnimationListener
添加到了基础class ParentFragment : Fragment(), FragmentAnimationListener {
override fun onAnimationStart(fragment: Fragment, animation: Animation, enter: Boolean) {
...
}
override fun onAnimationEnd(fragment: Fragment, animation: Animation, enter: Boolean) {
...
}
}
类中,因此我们的AnimationListener
和Fragment
将会是从正在退出的片段和正在进入的片段中调用(假设您的onAnimationStart
将一个片段替换为另一个片段)。因此,在尝试使用onAnimationEnd
进行任何操作之前,我们只需要过滤掉我们感兴趣的片段。
我将使用“输入” FragmentTransaction
作为工具栏动画的触发器-当我们弹出堆栈时,我将使用相同的Toolbar
(现在是“退出” )。因此,我唯一感兴趣的Fragment
是正在过渡的到:
Fragment
最后一步是实际执行工具栏动画。您可以使用自己的时间,内插器等来创建自己的Fragment
-但我更喜欢使用为孩子class ParentFragment : Fragment(), FragmentAnimationListener {
var newFragment: Fragment? = null
fun replaceFragment(newFragment: Fragment) {
// Store a reference to the fragment we're transitioning to
this.newFragment = newFragment
childFragmentManager.beginTransaction()
.setCustomAnimations(..)
.replace(container, newFragment, tag)
.commit()
}
override fun onAnimationStart(fragment: Fragment, animation: Animation, enter: Boolean) {
if (fragment == newFragment) {
if (enter) {
// Animate our Toolbar in
} else {
// Animate our Toolbar out
}
}
}
}
制作动画的同一Animation
。这样,如果我们渐入渐出,Animator
将渐渐消失。如果我们渐出渐出,Fragment
将渐渐消失。通过使用相同的Toolbar
,我们可以确定我们具有正确的持续时间和内插器,因此我们的Toolbar
将同时运行。
Animation