popup片段叠加而不popupPop-Animation

我使用以下代码在片段堆栈上推送一个片段:

FragmentManager fragmentManager = getActivity().getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_right, R.anim.slide_in_left, R.anim.slide_out_left); fragmentTransaction.replace(getId(), newFragment); fragmentTransaction.addToBackStack(null); fragmentTransaction.commit(); 

这样,当片段堆栈popup时,例如通过按下后退button,播放片段popupanimation。 但是,在某些情况下,我想popup片段叠加而不显示该animation,例如,因为我刚刚从另一个活动返回,并希望一次显示前一个片段,而没有animation。

示例导航可能如下所示:

  • 用户在开始屏幕上的根片段
  • 他在根片段上select一个项目,然后显示一个新的片段来显示该项目的细节。 它使用一个片段事务来为推送和stream行案例设置animation(所以当用户按下后退button时,过渡是animation的)
  • 从这个片段他开始了一个活动(不pipe什么原因)删除刚才显示的项目
  • 当这个活动结束时,我想返回到根片段而不显示“细节片段”的“stream行animation”

有没有方法来popup片段的堆栈,而不玩指定的stream行animation?

所以Warpzit是在正确的轨道上,他只是没有解决你的具体问题。 我遇到了完全相同的问题,这是我如何解决它。

首先我创build了一个静态布尔variables(为了简单起见,我们把它放在FragmentUtils类中)…

 public class FragmentUtils { public static boolean sDisableFragmentAnimations = false; } 

然后,在每个片段中,您都需要重写onCreateAnimation方法…

 @Override public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { if (FragmentUtils.sDisableFragmentAnimations) { Animation a = new Animation() {}; a.setDuration(0); return a; } return super.onCreateAnimation(transit, enter, nextAnim); } 

然后,当您需要清除您的活动中的后台时,只需执行以下操作…

 public void clearBackStack() { FragmentUtils.sDisableFragmentAnimations = true; getSupportFragmentManager().popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); FragmentUtils.sDisableFragmentAnimations = false; } 

而且,对clearBackStack()的调用将会让你回到没有任何转换animation的根片段中。

希望大G能够在未来增加一个不那么愚蠢的做法。

所以对于支持库下面的工作:

在应该有自定义stream行animation的片段中,您可以用自己的自定义属性覆盖onCreateAnimation。 你可以得到它,并根据你想要的设置某种参数。 可能需要做一些额外的工作才能使它与常规片段一起工作。

这里是我重写它并更改设置持续时间的示例:

 @Override public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { Animation anim = (Animation) super.onCreateAnimation(transit, enter, nextAnim); if(!enter) { if(anim != null) { anim.setDuration(0); // This doesn't seem to be called. return anim; } else { Animation test = new TestAnimation(); test.setDuration(0); return test; } } return anim; } private class TestAnimation extends Animation { } 

用户在开始屏幕上的根片段

可以说,根分片包含在Activity A中

他在根片段上select一个项目,然后显示一个新的片段来显示该项目的细节。 它使用一个片段事务来为推送和stream行案例设置animation(所以当用户按下后退button时,过渡是animation的)

该事务被添加到后退堆栈。 这意味着当从详细片段按下后退button时,popup过程被激活。

从这个片段他开始了一个活动(不pipe什么原因)删除刚才显示的项目。

让我们说这是活动乙

当这个活动结束时,我想返回到根片段而不显示“细节片段”的“stream行animation”

获取此行为的一种方法是在活动B中执行此操作:

 Intent intent = new Intent(this, A.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); finish(); 

这将启动活动A,根据文档将其重置为根状态(查看“这个启动模式也可以与FLAG_ACTIVITY_NEW_TASK一起使用效果良好:……”一节中的最后一段) )

使用此configuration,animation将以默认情况下呈现,而在特殊情况下,您可以使用以下方式控制animation:

 intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); 

没有任何animation就开始新的活动。 如果你想要任何animation,你可以使用overridePendingTransition方法。

所以,我想build议对@Geoff的答案做个小小的改动。

而不是有一个全局的静态布尔,我宁愿有一个本地非静态的。 这是我想出来的。

创build一个界面

 public interface TransitionAnimator { void disableTransitionAnimation(); void enableTransitionAnimation(); } 

制作界面的片段工具。

 public class MyFragment extends Fragment implements TransitionAnimator { private boolean mTransitionAnimation; @Override public void disableTransitionAnimation() { mTransitionAnimation = false; } @Override public void enableTransitionAnimation() { mTransitionAnimation = true; } @Override public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { Animation result; if (!mTransitionAnimation) { Animation dummyAnimation = new Animation() { }; dummyAnimation.setDuration(0); result = dummyAnimation; } else { result = super.onCreateAnimation(transit, enter, nextAnim); } return result; } 

然后,当你想禁用一个片段的过渡animation,就这样做

 if (fragment instanceof TransitionAnimator) { ((TransitionAnimator) fragment).disableTransitionAnimation(); } 

为了使他们,只是做

 if (fragment instanceof TransitionAnimator) { ((TransitionAnimator) fragment).enableTransitionAnimation(); } 

如果你想对片段pipe理器中的所有片段做同样的事情,那就做吧

 List<Fragment> fragments = getSupportFragmentManager().getFragments(); for (Fragment fragment : fragments) { if (fragment instanceof TransitionAnimator) { // disable animations ((TransitionAnimator) fragment).disableTransitionAnimation(); } } 

非常相似,但没有静态字段。

只需使用setCustomAnimation()另一个重载方法,并在其中不设置R.anim.slide_out ,这将解决您的问题

干杯:)

在回答你的问题之前,我需要自己提出一个问题。

在第二个activity的onBackPressed()方法中,你可以访问第一个activity的backstack吗?

如果是的话,那么你可以调用popBackStackImmediate(String trnaisiotnName,int inclusive),它将从堆栈中删除片段的过渡,你不需要担心animation。

我假设你可以访问以前的活动的后台,否则这将无法正常工作

这通过overridePendingTransition(int enterAnim, int exitAnim)可以非常容易的实现overridePendingTransition(int enterAnim, int exitAnim)对于没有animation的情况都是0

 FragmentManager fm = getSupportFragmentManager(); if (fm.getBackStackEntryCount() > 0) { fm.popBackStack(); overridePendingTransition(0, 0); } 

这是@ Geoff的出色答案的后续,但适合更具活力和真实生活的情况。

我想这是一个不错的小贴子,但是现在我意识到它有点失控了。 然而,代码是在那里,我觉得它真的很有用,但它不仅涵盖了如何禁用过渡animation。

通常,当我使用片段时,我喜欢将BaseFragment连接到BaseActivityCallback。 这个BaseActivityCallback可以被我的Fragments用来在它自己之上添加一个新的Fragment,或者甚至popup它下面的Fragment,因此可以禁用popanimation – 或者默默地popup:

 interface BaseActivityCallback { void addFragment ( BaseFragment f, int containerResId ); void popFragment ( boolean silently ); } class BaseActivity extends android.support.v4.app.FragmentActivity implements BaseActivityCallback { public void addFragment ( BaseFragment f, int containerResId ) { FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.setCustomAnimations(R.anim.enter, R.anim.exit, R.anim.enter, R.anim.pop_exit); // http://stackoverflow.com/a/17488542/2412477 ft.addToBackStack(DEFAULT_FRAGMENT_STACK_NAME); ft.replace(containerResId, fragment); ft.commitAllowingStateLoss(); } public void popFragment ( boolean silently ) { FragmentManager fm = getSupportFragmentManager(); if ( silently ) { int count = fm.getFragments().size(); BaseFragment f = (BaseFragment)fm.getFragments().get(count-1); f.setDisableTransitionAnimations(true); } fm.popBackStackImmediate(); } } public abstract class BaseFragment extends android.support.v4.app.Fragment { private static final String TAG = "BaseFragment"; private final String STATE_DISABLE_TRANSITION_ANIMATIONS = TAG+".stateDisableTransitionAnimations"; protected BaseActivityCallback baseActivityCallback; private boolean disableTransitionAnimations; @Override public void onCreate ( @Nullable Bundle savedInstanceState ) { super.onCreate(savedInstanceState); disableTransitionAnimations = (savedInstanceState==null ? false : savedInstanceState.getBoolean(STATE_DISABLE_TRANSITION_ANIMATIONS, false)); } @Override public void onAttach ( Context context ) { super.onAttach(context); baseActivityCallback = (BaseActivityCallback)context; } @Override public void onSaveInstanceState ( Bundle outState ) { super.onSaveInstanceState(outState); outState.putBoolean(STATE_DISABLE_TRANSITION_ANIMATIONS, disableTransitionAnimations); } @Override public Animation onCreateAnimation ( int transit, boolean enter, int nextAnim ) { if ( disableTransitionAnimations ) { Animation nop = new Animation(){}; nop.setDuration(0); return nop; } return super.onCreateAnimation(transit, enter, nextAnim); } public void setDisableTransitionAnimations ( boolean disableTransitionAnimations ) { this.disableTransitionAnimations = disableTransitionAnimations; // http://stackoverflow.com/a/11253987/2412477 } } 

现在你可以创build你的MainActivity ,并显示一个Fragment1 ,它可以添加另一个Fragment2 ,然后默认popupFragment1

 public class MainActivity extends BaseActivity { protected void onCreate ( Bundle savedInstanceState ) { setContentView(R.layout.main_activity); ... if ( getSupportFragmentManager().getFragments() != null && !getSupportFragmentManager().getFragments().isEmpty() ) { addFragment( FragmentA.newInstance(), R.id.main_activity_fragment_container ); } } ... } public class FragmentA extends BaseFragment { public View onCreateView ( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) { ViewGroup root = (ViewGroup)inflater.inflate(R.layout.fragment_a, container, false); ... root.findViewById(R.id.fragment_a_next_button) .setOnClickListener( new View.OnClickListener() { public void onClick ( View v ) { baseActivityCallback.addFragment( FragmentB.newInstance(), R.id.main_activity_fragment_container ); } }); } } public class FragmentB extends BaseFragment { public View onCreateView ( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) { ViewGroup root = (ViewGroup)inflater.inflate(R.layout.fragment_b, container, false); ... root.findViewById(R.id.fragment_b_pop_silently_button) .setOnClickListener( new View.OnClickListener() { public void onClick ( View v ) { baseActivityCallback.popFragment( true ); } }); } } 

在您想要popup的片段中覆盖此选项,而不inputanimation,并在input时仍保留animation

 @Override public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { if(!enter){ Animation a = new Animation() {}; a.setDuration(0); return a; } return super.onCreateAnimation(transit, enter, nextAnim); } 

回复杰夫和普莱克马赫的评论。

你可以尝试删除这个片段的所有视图。 然后片段将显示,但它应该是透明的。

删除所有-1(我使用导航抽屉,所以抽屉碎片应停留)片段:

  int size = fragmentsList.size ()-1; FragmentTransaction transaction = fragmentManager.beginTransaction (); transaction.setTransition (FragmentTransaction.TRANSIT_NONE); Fragment fragment; for (int i = size ; i > 0 ; i--) { fragment = fragmentsList.get (i); if(fragment != null) { View viewContainer = fragment.getView (); if (viewContainer != null) { ((ViewGroup) viewContainer).removeAllViews (); } transaction.remove (fragment); } } size = fragmentManager.getBackStackEntryCount (); for (int i = 0; i < size ; i++) { fragmentManager.popBackStack (null, FragmentManager.POP_BACK_STACK_INCLUSIVE); } 

对不起我的英语不好