我使用以下代码在片段堆栈上推送片段:
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();
这样,当弹出片段堆栈时,例如,通过按后退按钮,播放片段弹出动画。但是,有些情况下我想弹出片段后台而不显示这个动画,例如因为我刚从另一个活动返回,想要一次显示前一个片段,没有动画。
示例导航可能如下所示:
有没有办法弹出片段后台而不播放指定的流行动画?
答案 0 :(得分:85)
所以Warpzit走在正确的轨道上,他只是没有很好地解决你的具体问题。我遇到了完全相同的问题,这就是我如何解决它。
首先我创建了一个静态布尔变量(为简单起见,让它放在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()会让你回到根片段而没有任何过渡动画。
希望G大将在未来添加一种不那么愚蠢的方式。
答案 1 :(得分:6)
所以对于以下工作的支持库:
在应具有自定义弹出动画的片段中,您可以使用自己的自定义动画覆盖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 {
}
答案 2 :(得分:5)
用户在开始屏幕上显示根片段
假设根片段包含在活动A中。
他选择根片段上的一个项目,然后显示一个新片段以显示该项目的详细信息。它使用片段事务来设置推送和弹出案例的动画(因此当用户按下后退按钮时,过渡动画)
事务被添加到后台堆栈。这意味着当从细节片段按下后退按钮时,弹出过程将被动画化。
从这个片段开始,他开始一个活动(无论出于何种原因)删除刚刚显示的项目。
让我们说它是活动B
当这个活动结束时,我想返回根片段,而不显示“细节片段”的“流行动画”
获得此行为的一种方法是在活动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根据documentation将其重置为其根状态。(查看该部分中的最后一段说明“此启动模式也可与FLAG_ACTIVITY_NEW_TASK一起使用,效果良好: ......“)
使用此配置,动画将以默认情况显示,而在特殊情况下,您可以使用以下方式控制动画:
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
在没有任何动画的情况下开始新活动。如果你想要任何动画,你可以使用overridePendingTransition
方法。
答案 3 :(得分:1)
所以,我想建议对@ Geoff的答案做一点改动。
我没有使用全局静态布尔值,而是使用本地非静态布尔值。这就是我想出来的。
创建界面
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;
}
然后,当您想要禁用片段的过渡动画时,只需执行
if (fragment instanceof TransitionAnimator) {
((TransitionAnimator) fragment).disableTransitionAnimation();
}
启用它们,只需执行
if (fragment instanceof TransitionAnimator) {
((TransitionAnimator) fragment).enableTransitionAnimation();
}
如果要对片段管理器中的所有片段执行相同操作,只需执行
List<Fragment> fragments = getSupportFragmentManager().getFragments();
for (Fragment fragment : fragments) {
if (fragment instanceof TransitionAnimator) {
// disable animations
((TransitionAnimator) fragment).disableTransitionAnimation();
}
}
非常相似,但没有静态字段。
答案 4 :(得分:0)
使用setCustomAnimation()
的另一种重载方法,其中不设置 R.anim.slide_out
这将解决您的问题
干杯:)
答案 5 :(得分:0)
在回答你的问题之前,我需要自己提问。
在第二个活动的onBackPressed()方法中,您可以访问第一个活动的backstack吗?
如果是,那么你可以调用popBackStackImmediate(String trnaisiotnName,int inclusive),它将从backstack中删除片段转换,你不必担心动画。
我假设你可以访问之前活动的后台,否则这不会起作用
答案 6 :(得分:0)
这很容易通过overridePendingTransition(int enterAnim, int exitAnim)
同时使用0
来实现无动画。
FragmentManager fm = getSupportFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
fm.popBackStack();
overridePendingTransition(0, 0);
}
答案 7 :(得分:0)
这是对@ Geoff的优秀答案的后续跟进,但适用于更具动态性和实时性的场景。
我想象这是一个不错的小帖子,但我现在意识到它有点失控。但是,代码就在那里,我觉得它非常有用,虽然它不仅仅涉及如何禁用转换动画。
通常,当我使用Fragments时,我喜欢将BaseFragment附加到BaseActivityCallback。我的片段可以使用这个BaseActivityCallback在其自身之上添加一个新的片段,甚至可以在其下面弹出片段,因此需要禁用流行动画 - 或者默认弹出 :
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
}
}
现在,您可以创建MainActivity
,并显示Fragment1
,可以添加另一个Fragment2
,然后可以依次弹出Fragment1
:
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 );
}
});
}
}
答案 8 :(得分:0)
在您想要在没有动画的情况下弹出的片段中覆盖它,并在输入
时保持动画@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);
}
答案 9 :(得分:0)
更简单的解决方案:
for (fragment in supportFragmentManager.fragments) {
removeFragment(fragment)
}
if (supportFragmentManager.backStackEntryCount > 0) {
supportFragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
}
答案 10 :(得分:0)
现在,Android实际上有一种方法可以解决@Geoff周围的问题。
为避免动画在popBackStack()
上运行,在给fragment
充气时,请将.setReorderingAllowed(true)
添加到fragmentTransaction
。
例如:
supportFragmentTransaction.beginTransaction()
.setReorderingAllowed(true)
.addToBackStack(null)
.setCustomAnimations(
android.R.anim.fade_in,
android.R.anim.fade_out,
android.R.anim.fade_in,
android.R.anim.fade_out
)
.replace(yourContainer.id, yourFragment)
.commit()
您会注意到,如果设置setReorderingAllowed(true)
,则将不再播放弹出动画。结果实际上类似于@Geoff的答案。
答案 11 :(得分:-1)
回复杰夫和plackemacher评论。
您可以尝试从此片段中删除所有视图。然后片段将显示但它应该是透明的。
删除all-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);
}
抱歉我的英文