【问题标题】:Android Fragments and animationAndroid 片段和动画
【发布时间】:2011-06-16 14:48:18
【问题描述】:

您应该如何实现例如 Honeycomb Gmail 客户端使用的那种滑动?

TransactionManager 可以通过添加和删除 Fragments 来自动处理这个问题,由于模拟器是幻灯片,所以测试起来有点困难 :)

【问题讨论】:

    标签: android android-fragments android-3.0-honeycomb


    【解决方案1】:

    要动画片段之间的过渡,或动画显示或隐藏片段的过程,请使用Fragment Manager 创建Fragment Transaction

    在每个片段事务中,您可以指定将分别用于显示和隐藏的进出动画(或在使用替换时同时使用两者)。

    以下代码显示了如何通过滑出一个片段并将另一个片段滑入原位来替换片段。

    FragmentTransaction ft = getFragmentManager().beginTransaction();
    ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);
    
    DetailsFragment newFragment = DetailsFragment.newInstance();
    
    ft.replace(R.id.details_fragment_container, newFragment, "detailFragment");
    
    // Start the animated transition.
    ft.commit();
    

    要通过隐藏或显示片段来实现相同的目的,您只需调用ft.showft.hide,分别传入您希望显示或隐藏的片段。

    作为参考,XML 动画定义将使用objectAnimator 标记。 slide_in_left 的示例可能如下所示:

    <?xml version="1.0" encoding="utf-8"?>
    <set>
      <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:propertyName="x" 
        android:valueType="floatType"
        android:valueFrom="-1280"
        android:valueTo="0" 
        android:duration="500"/>
    </set>
    

    【讨论】:

    • 当我尝试这个时它显示 RuntimeException: Unknown animator name: translate.
    • 确保在 slide_in_left 和 right 中定义的动画是使用一组 objectAnimator 定义而不是旧的动画定义来构造的。
    • 这很有帮助。我走在正确的轨道上,但只是没有一路走到那里。对于其他读者,您也可以将 android:interpolator 作为属性,指定您最喜欢的属性(例如“@android:interpolator/linear”)。默认为“@android:interpolator/accelerate_decelerate”。
    • 我的目标是使用兼容性 API 的 API 级别 7。有没有办法让我为片段设置动画?
    • @JarrodSmith,您可以尝试使用像 NineOldAndroids 这样的兼容性库来将 Honeycomb API 降低到 Eclair。
    【解决方案2】:

    如果您不必使用支持库,请查看Roman's 答案。

    但如果你想使用支持库,你必须使用如下所述的旧动画框架。

    在咨询了Reto'sblindstuff's 的答案后,我得到了以下代码。

    当按下返回时,片段会出现从右侧滑入向左滑出

    FragmentManager fragmentManager = getSupportFragmentManager();
    
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    transaction.setCustomAnimations(R.anim.enter, R.anim.exit, R.anim.pop_enter, R.anim.pop_exit);
    
    CustomFragment newCustomFragment = CustomFragment.newInstance();
    transaction.replace(R.id.fragment_container, newCustomFragment );
    transaction.addToBackStack(null);
    transaction.commit();
    

    顺序很重要。 这意味着你必须在replace()之前调用setCustomAnimations(),否则动画不会生效!

    接下来这些文件必须放在 res/anim 文件夹中。

    进入.xml

    <?xml version="1.0" encoding="utf-8"?>
    <set>
        <translate xmlns:android="http://schemas.android.com/apk/res/android"
                   android:fromXDelta="100%"
                   android:toXDelta="0"
                   android:interpolator="@android:anim/decelerate_interpolator"
                   android:duration="@android:integer/config_mediumAnimTime"/>
    </set>
    

    exit.xml

    <set>
        <translate xmlns:android="http://schemas.android.com/apk/res/android"
                   android:fromXDelta="0"
                   android:toXDelta="-100%"
                   android:interpolator="@android:anim/accelerate_interpolator"
                   android:duration="@android:integer/config_mediumAnimTime"/>
    </set>
    

    pop_enter.xml

    <set>
        <translate xmlns:android="http://schemas.android.com/apk/res/android"
                   android:fromXDelta="-100%"
                   android:toXDelta="0"
                   android:interpolator="@android:anim/decelerate_interpolator"
                   android:duration="@android:integer/config_mediumAnimTime"/>
    </set>
    

    pop_exit.xml

    <?xml version="1.0" encoding="utf-8"?>
    <set>
        <translate xmlns:android="http://schemas.android.com/apk/res/android"
                   android:fromXDelta="0"
                   android:toXDelta="100%"
                   android:interpolator="@android:anim/accelerate_interpolator"
                   android:duration="@android:integer/config_mediumAnimTime"/>
    </set>
    

    动画的持续时间可以更改为任何默认值,例如@android:integer/config_shortAnimTime 或任何其他数字。

    请注意,如果在片段替换之间发生配置更改(例如旋转),则后退动作不会动画。这是一个documented bug,它仍然存在于支持库的第 20 版中。

    【讨论】:

    • 这只是救了我。注意,注意顺序很重要,很自然,我第一次错过了。这意味着您必须在 replace() 之前调用 setCustomAnimations()。
    • 我试图在我的片段上实现。我写了你提到的所有内容,但 logcat 说:unknow animator name translate 我怎样才能克服这个问题?顺便说一句,我在导航抽屉(滑动菜单)上调用我的片段
    • 效果很好,但事实证明,使用构建工具 21.1 构建它会产生错误,提示“文件名无效:必须仅包含小写字母和数字 ([a-z0-9_.])”。我建议在 pop_enter.xml 和 pop_exit.xml 的答案中编辑文件名。
    • 很好的解决方案,当我按下后退按钮时效果很好。我只有一个问题:如果我想创建一个自定义后退按钮,我应该调用什么代码来复制后退按钮的行为?
    • Thomas 如果你想返回,你应该实现这个表单:.setCustomAnimations(R.anim.pop_enter, R.anim.pop_exit, R.anim.enter, R.anim.exit)跨度>
    【解决方案3】:

    我强烈建议您使用它而不是创建动画文件,因为它是一个更好的解决方案。 Android Studio 已经提供了 default animation,您无需创建任何新的 XML 文件即可使用。动画的名称是 android.R.anim.slide_in_leftandroid.R.anim.slide_out_right,您可以按如下方式使用它们:

    fragmentTransaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);

    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();              
    fragmentTransaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
    fragmentManager.addOnBackStackChangedListener(this);
    fragmentTransaction.replace(R.id.frame, firstFragment, "h");
    fragmentTransaction.addToBackStack("h");
    fragmentTransaction.commit();
    

    输出:

    【讨论】:

    • android.R...“Android Studio 提供默认动画”,这不适用于 android studio 它也可以在 eclipse 中工作,android.R 是 android 特定的。顺便说一下,你没有分享什么api有这个信息。因为android.R上的东西在不同的api上是不同的。
    • @stevemoretz thaxs bro 我同意你的观点。我会更正并更新我的答案...
    【解决方案4】:

    我修改后的support library 支持将视图动画(即&lt;translate&gt;, &lt;rotate&gt;)和对象动画器(即&lt;objectAnimator&gt;)用于片段过渡。它是用NineOldAndroids 实现的。详情参考我在github上的文档。

    【讨论】:

      【解决方案5】:

      至于我,我需要视图方向:

      in -> 从右侧滑动

      out -> 向左滑动

      这里适用于我的代码:

      slide_in_right.xml

      <set xmlns:android="http://schemas.android.com/apk/res/android">
          <translate android:fromXDelta="50%p" android:toXDelta="0"
                  android:duration="@android:integer/config_mediumAnimTime"/>
          <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
                  android:duration="@android:integer/config_mediumAnimTime" />
      </set>
      

      slide_out_left.xml

       <set xmlns:android="http://schemas.android.com/apk/res/android">
              <translate android:fromXDelta="0" android:toXDelta="-50%p"
                      android:duration="@android:integer/config_mediumAnimTime"/>
              <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
                      android:duration="@android:integer/config_mediumAnimTime" />
          </set>
      

      交易代码:

      inline fun FragmentActivity.setContentFragment(
              containerViewId: Int,
              backStack: Boolean = false,
              isAnimate: Boolean = false,
              f: () -> Fragment
      
      ): Fragment? {
          val manager = supportFragmentManager
          return f().apply {
              manager.beginTransaction().let {
                  if (isAnimate)
                      it.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left)
      
                  if (backStack) {
                      it.replace(containerViewId, this, "Fr").addToBackStack("Fr").commit()
                  } else {
                      it.replace(containerViewId, this, "Fr").commit()
                  }
              }
          }
      }
      

      【讨论】:

      • Android 似乎在用那些动画(特别是翻译动画)闪烁过渡
      • @GabrielDeOliveiraRohden 对我来说并非在所有情况下
      【解决方案6】:

      我用下面的方法解决这个问题

      Animation anim = AnimationUtils.loadAnimation(this, R.anim.slide);
      fg.startAnimation(anim);
      this.fg.setVisibility(View.VISIBLE); //fg is a View object indicate fragment
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-26
        • 2012-06-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多