【问题标题】:Fragment transaction animation: slide in and slide out片段交易动画:滑入滑出
【发布时间】:2014-01-28 08:51:34
【问题描述】:

我查看了一些关于片段之间的动画交易的教程。我已经将这种方法用于动画并且它有效:

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

但我想反转这个动画:旧片段向左滑出,新片段向右滑入,但 R.anim 文件的值似乎对我的范围没有用。

我该怎么做?

【问题讨论】:

  • 在我看来,您可以尝试在第二个片段中使用 override key_code==back_key_press
  • 也许我没有很好地解释自己。我希望当片段交换时,旧片段在左侧滑动,新片段从右侧进入。使用该代码,行为是相反的

标签: android animation android-fragments


【解决方案1】:

更新For Android v19+ see this link通过@Sandra

您可以创建自己的动画。将动画XML文件放在res > anim

enter_from_left.xml

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

enter_from_right.xml

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

exit_to_left.xml

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

exit_to_right.xml

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

您可以将持续时间更改为较短的动画时间

android:duration="@android:integer/config_shortAnimTime"

或较长的动画时间

android:duration="@android:integer/config_longAnimTime" 

用法 (注意在事务中调用方法的顺序很重要。在调用 .replace、.commit 之前添加动画):

FragmentTransaction transaction = supportFragmentManager.beginTransaction();
transaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right);
transaction.replace(R.id.content_frame, fragment);
transaction.addToBackStack(null);
transaction.commit();

【讨论】:

  • 替换片段时只需使用这些xml动画,即:fragmentTransaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right); fragmentTransaction.replace(R.id.content_frame, fragDettRisorsa); fragmentTransaction.addToBackStack(null); fragmentTransaction.commit();
  • 它说未知的动画师名字:翻译
  • 它不起作用...导致“java.lang.RuntimeException: Unknown animator name: translate”。这个解决方案对我有用。 trickyandroid.com/fragments-translate-animation
  • 在我看来,Duration 700 对于这样的动画来说有点多。 Android框架有3个定时预设:android:duration="@android:integer/config_longAnimTime"android:duration="@android:integer/config_mediumAnimTime"android:duration="@android:integer/config_shortAnimTime",分别对应500、400和200。我猜单位是毫秒,但我不确定。
  • 仅在使用支持片段 (android.support.v4.app.Fragment) 时有效
【解决方案2】:

片段中的动画交易有三种方式。

过渡

所以需要使用内置的Transitions之一,使用setTranstion() 方法:

getSupportFragmentManager()
        .beginTransaction()
        .setTransition( FragmentTransaction.TRANSIT_FRAGMENT_OPEN )
        .show( m_topFragment )
        .commit()

自定义动画

您还可以使用 setCustomAnimations() 方法自定义动画:

getSupportFragmentManager()
        .beginTransaction()
        .setCustomAnimations( R.anim.slide_up, 0, 0, R.anim.slide_down)
        .show( m_topFragment )
        .commit()

slide_up.xml

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:propertyName="translationY"
        android:valueType="floatType"
        android:valueFrom="1280"
        android:valueTo="0"
        android:duration="@android:integer/config_mediumAnimTime"/>

slide_down.xml

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:propertyName="translationY"
        android:valueType="floatType"
        android:valueFrom="0"
        android:valueTo="1280"
        android:duration="@android:integer/config_mediumAnimTime"/>

多个动画

最后,还可以启动多个片段动画 在单笔交易中。这允许一个非常酷的效果,其中 一个片段向上滑动,另一个片段同时向下滑动:

getSupportFragmentManager()
        .beginTransaction()
        .setCustomAnimations( R.anim.abc_slide_in_top, R.anim.abc_slide_out_top ) // Top Fragment Animation
        .show( m_topFragment )
        .setCustomAnimations( R.anim.abc_slide_in_bottom, R.anim.abc_slide_out_bottom ) // Bottom Fragment Animation
        .show( m_bottomFragment )
        .commit()

To more detail you can visit URL

注意:-您可以根据您的要求检查动画,因为上面可能有问题。

【讨论】:

  • 您使用的是绝对硬编码值。上一个片段将在屏幕中间消失,以获得更高分辨率的显示。
  • @TheLibrarianCz 这只是示例
  • 是,不是。
  • 这取决于有人想从上面的例子中用勺子喂食,或者从例子中吸取教训。
  • m_topFragment 变量中有什么
【解决方案3】:

slide_in_down.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="@android:integer/config_longAnimTime"
        android:fromYDelta="0%p"
        android:toYDelta="100%p" />
</set>

slide_in_up.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="@android:integer/config_longAnimTime"
        android:fromYDelta="100%p"
        android:toYDelta="0%p" />
</set>

slide_out_down.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="@android:integer/config_longAnimTime"
        android:fromYDelta="-100%"
        android:toYDelta="0"
        />
</set>

slide_out_up.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="@android:integer/config_longAnimTime"
        android:fromYDelta="0%p"
        android:toYDelta="-100%p"
        />
</set>

方向 = 向下

            activity.getSupportFragmentManager()
                    .beginTransaction()
                    .setCustomAnimations(R.anim.slide_out_down, R.anim.slide_in_down)
                    .replace(R.id.container, new CardFrontFragment())
                    .commit();

方向=向上

           activity.getSupportFragmentManager()
                    .beginTransaction()
                    .setCustomAnimations(R.anim.slide_in_up, R.anim.slide_out_up)
                    .replace(R.id.container, new CardFrontFragment())
                    .commit();

【讨论】:

    【解决方案4】:

    我有同样的问题,我使用了简单的解决方案

    1)在anim文件夹中创建sliding_out_right.xml

      <?xml version="1.0" encoding="utf-8"?>
        <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>
    

    2) 在anim文件夹中创建sliding_in_left.xml

    <?xml version="1.0" encoding="utf-8"?>
    <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>
    

    3) 只需将片段事务 setCustomeAnimations() 与两个自定义 xml 和两个默认 xml 用于动画如下:-

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

    【讨论】:

      【解决方案5】:

      这是我使用的另一种解决方案:

      public class CustomAnimator {
          private static final String TAG = "com.example.CustomAnimator";
      
          private static Stack<AnimationEntry> animation_stack    = new Stack<>();
      
          public static final int                 DIRECTION_LEFT  = 1;
          public static final int                 DIRECTION_RIGHT = -1;
          public static final int                 DIRECTION_UP    = 2;
          public static final int                 DIRECTION_DOWN  = -2;
      
          static class AnimationEntry {
              View in;
              View    out;
              int     direction;
              long    duration;
          }
      
          public static boolean hasHistory() {
              return !animation_stack.empty();
          }
      
          public static void reversePrevious() {
              if (!animation_stack.empty()) {
                  AnimationEntry entry = animation_stack.pop();
                  slide(entry.out, entry.in, -entry.direction, entry.duration, false);
              }
          }
      
          public static void clearHistory() {
              animation_stack.clear();
          }
      
          public static void slide(final View in, View out, final int direction, long duration) {
              slide(in, out, direction, duration, true);
          }
      
          private static void slide(final View in, final View out, final int direction, final long duration, final boolean save) {
      
              ViewGroup in_parent = (ViewGroup) in.getParent();
              ViewGroup out_parent = (ViewGroup) out.getParent();
      
              if (!in_parent.equals(out_parent)) {
                  return;
              }
      
              int parent_width = in_parent.getWidth();
              int parent_height = in_parent.getHeight();
      
              ObjectAnimator slide_out;
              ObjectAnimator slide_in;
      
              switch (direction) {
                  case DIRECTION_LEFT:
                  default:
                      slide_in = ObjectAnimator.ofFloat(in, "translationX", parent_width, 0);
                      slide_out = ObjectAnimator.ofFloat(out, "translationX", 0, -out.getWidth());
                      break;
                  case DIRECTION_RIGHT:
                      slide_in = ObjectAnimator.ofFloat(in, "translationX", -out.getWidth(), 0);
                      slide_out = ObjectAnimator.ofFloat(out, "translationX", 0, parent_width);
                      break;
                  case DIRECTION_UP:
                      slide_in = ObjectAnimator.ofFloat(in, "translationY", parent_height, 0);
                      slide_out = ObjectAnimator.ofFloat(out, "translationY", 0, -out.getHeight());
                      break;
                  case DIRECTION_DOWN:
                      slide_in = ObjectAnimator.ofFloat(in, "translationY", -out.getHeight(), 0);
                      slide_out = ObjectAnimator.ofFloat(out, "translationY", 0, parent_height);
                      break;
              }
      
              AnimatorSet animations = new AnimatorSet();
              animations.setDuration(duration);
              animations.playTogether(slide_in, slide_out);
              animations.addListener(new Animator.AnimatorListener() {
      
                  @Override
                  public void onAnimationCancel(Animator arg0) {
                  }
      
                  @Override
                  public void onAnimationEnd(Animator arg0) {
                      out.setVisibility(View.INVISIBLE);
                      if (save) {
                          AnimationEntry ae = new AnimationEntry();
                          ae.in = in;
                          ae.out = out;
                          ae.direction = direction;
                          ae.duration = duration;
                          animation_stack.push(ae);
                      }
                  }
      
                  @Override
                  public void onAnimationRepeat(Animator arg0) {
                  }
      
                  @Override
                  public void onAnimationStart(Animator arg0) {
                      in.setVisibility(View.VISIBLE);
                  }
              });
              animations.start();
          }
      }
      

      类的用法。假设您有两个片段(列表和详细信息片段),如下所示

      <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/ui_container"
          android:layout_width="match_parent"
          android:layout_height="match_parent" >
      
          <FrameLayout
              android:id="@+id/list_container"
              android:layout_width="match_parent"
              android:layout_height="match_parent" />
      
          <FrameLayout
              android:id="@+id/details_container"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:visibility="gone" />
      </FrameLayout>
      

      用法

      View details_container = findViewById(R.id.details_container);
      View list_container = findViewById(R.id.list_container);
      // You can select the direction left/right/up/down and the duration
      CustomAnimator.slide(list_container, details_container,CustomAnimator.DIRECTION_LEFT, 400);
      

      您可以使用函数CustomAnimator.reversePrevious();在用户按下返回时获取上一个视图。

      【讨论】:

      • 你确定你使用的是android的片段吗? =) 似乎使用自定义片段管理基于视图的系统)
      【解决方案6】:

      在从一个片段过渡到另一个片段时出现白屏问题。在 navigation.xml 中设置导航和动画。

      所有片段的背景相同,但为白色空白屏幕。所以我在执行过渡期间在片段中设置了 navOptions

                //Transition options
              val options = navOptions {
                  anim {
                      enter = R.anim.slide_in_right
                      exit = R.anim.slide_out_left
                      popEnter = R.anim.slide_in_left
                      popExit = R.anim.slide_out_right
                  }
              }
      
      .......................
      
        this.findNavController().navigate(SampleFragmentDirections.actionSampleFragmentToChartFragment(it),
                          options)
      

      它对我有用。过渡之间没有白屏。魔法)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-02-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多