Android 在不播放Pop动画的情况下将片段向后弹出

Android 在不播放Pop动画的情况下将片段向后弹出,android,android-fragments,android-animation,Android,Android Fragments,Android Animation,我使用以下代码将片段推送到片段堆栈上: FragmentManager fragmentManager = getActivity().getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide

我使用以下代码将片段推送到片段堆栈上:

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();
这样,当片段堆栈弹出时(例如,按下后退按钮),将播放片段弹出动画。但是,在某些情况下,我希望在不显示此动画的情况下弹出片段backbackback,例如,因为我刚从另一个活动返回,并且希望在不显示动画的情况下立即显示上一个片段

FragmentManager fm = getSupportFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
    fm.popBackStack();
    overridePendingTransition(0, 0);
}
导航示例如下所示:

  • 用户在开始屏幕上显示根片段
  • 他在根片段上选择一个项目,然后显示一个新片段以显示该项目的详细信息。它使用一个片段事务来实现这一点,该事务为push和pop case设置动画(因此,当用户按下back按钮时,转换被设置为动画)
  • 他从这个片段开始一个活动,该活动(出于任何原因)删除刚才显示的项目
  • 当这个活动结束时,我想返回到根片段,而不显示“细节片段”的“弹出动画”

有没有办法在不播放指定的pop动画的情况下弹出片段回退?

只需使用另一种重载方法
setCustomAnimation()
,其中不设置R.anim.slide\u 这会解决你的问题

干杯:)

用户在开始屏幕上显示根片段

假设根片段包含在活动A中

他在根片段上选择一个项目,然后显示一个新片段以显示该项目的详细信息。它使用一个片段事务来实现这一点,该事务为push和pop case设置动画(因此,当用户按下back按钮时,转换被设置为动画)

事务被添加到后堆栈中。这意味着当从细节片段中按下后退按钮时,弹出过程将设置动画

他从这个片段开始一个活动,该活动(出于任何原因)删除刚才显示的项目

假设是活动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,并根据将其重置为其根状态。(检查本节最后一段,其中说明“此启动模式也可与FLAG_Activity_NEW_TASK一起使用,以获得良好效果:……)

使用此配置,动画将在默认情况下显示,而在特殊情况下,可以使用以下方式控制动画:

intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);

在没有任何动画的情况下启动新活动。如果您确实需要任何动画,可以使用
重写PendingTransition
方法来执行。

因此,对于支持库,请执行以下操作:

在应该具有自定义pop动画的片段中,您可以使用自己的自定义动画覆盖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 {

}

Warpzit走的是对的,他只是没有很好地解决你的具体问题。我遇到了完全相同的问题,下面是我如何解决它的

首先,我创建了一个静态布尔变量(为了简单起见,让我们把它放在FragmentUtils类中)

然后,在您拥有的每个片段中,您需要重写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将来会增加一种不那么愚蠢的方式来做这件事。

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

在第二个活动的onBackPressed()方法中,可以访问第一个活动的backbackback吗

如果是,那么您可以调用popBackStackImmediate(字符串trnaisiotName,包含int),它将从backstack中删除片段转换,您不需要担心动画


我假设您可以访问上一个活动的后台,否则这将不起作用

请回复Geoff和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);
    }
int size=fragmentsList.size()-1;
FragmentTransaction=fragmentManager.beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_无);
片段;
对于(int i=size;i>0;i--)
{
fragment=fragmentsList.get(i);
if(片段!=null)
{
View viewContainer=fragment.getView();
如果(viewContainer!=null)
{
((ViewGroup)viewContainer);
}
transaction.remove(片段);
}
}
size=fragmentManager.getBackStackEntryCount();
对于(int i=0;i

对不起,我的英语是这很容易通过
覆盖transition(int-enterAnim,int-exitAnim)
0来实现,因为没有动画

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

所以,我想建议对@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;
    }
然后,当你想禁用trans
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();
    }
}
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
    }
}
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 );
                 }
             });
    }
}
@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);
}
for (fragment in supportFragmentManager.fragments) {
    removeFragment(fragment)
}
if (supportFragmentManager.backStackEntryCount > 0) {
    supportFragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
}
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()