动画工具栏和片段交易

时间:2015-06-13 06:53:26

标签: android animation android-fragments

我有使用以下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");

我应该将动画应用到我的布局来掩盖工具栏吗?

1 个答案:

答案 0 :(得分:1)

我也有同样的问题-它似乎在每个应用程序的开发过程中都会弹出,而我从来没有解决过,而是恢复到一些低于标准的解决方案。现在我有了解决方案!

在Kotlin中回答,但是在Java中适用相同的原理。

要为Toolbar动画和FragmentTransaction动画制作动画,首先需要一种方法通知Activity/Fragment的{​​{1}}动画正在开始/结束。我称ToolbarActivity/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) { ... } } 类中,因此我们的AnimationListenerFragment将会是从正在退出的片段和正在进入的片段中调用(假设您的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