在 Android 片段中使用 onBackPressed()

Posted

技术标签:

【中文标题】在 Android 片段中使用 onBackPressed()【英文标题】:Using onBackPressed() in Android Fragments 【发布时间】:2013-08-13 22:40:48 【问题描述】:

我正在做一个项目,我需要能够使用每个片段中的后退按钮在之前的片段之间导航,我已经编写了通过在操作栏中使用后退箭头来实现此目的的方法,但是,我想要能够在按下的后退按钮上使用相同的功能。我不想使用后台堆栈。有没有办法做到这一点?

编辑

我希望能够在用户单击后退按钮时调用下面的返回上一个方法,而不是使用后退堆栈。我需要在片段中使用 gobackpressed 方法。这可能吗?我希望这是清晰和简洁的。对于上述造成的任何混淆,我们深表歉意。

返回上一页

public void gobackToPreviousFragment(String preFragmentTag, Fragment preFragment)

    FragmentManager  fm = getSupportFragmentManager();

    FragmentTransaction ft = fm.beginTransaction();
    ft.setCustomAnimations(R.animator.close_slide_in,R.animator.close_slide_out);

    ft.show(preFragment);

    //**BY REMOVING FRAGMENT, WHEN USER TRIES TO REVISIT, FRAGMENT IS BLACK**

    ft.remove(fm.findFragmentByTag(Misc.currentContentFragmentTag));
    ft.addToBackStack(null);
    ft.commit();

    Misc.currentContentFragmentTag = preFragmentTag;

    createBar(preFragment);

前进

public void gotoNextFragment(String nextTag, Fragment nextFragment)

    FragmentManager  fm = getSupportFragmentManager();

    FragmentTransaction ft = fm.beginTransaction();
    ft.setCustomAnimations(R.animator.enter_slide_in, R.animator.enter_slide_out);

    boolean newlyCreated = false;
    if(nextFragment == null)
        nextFragment = Fragment.instantiate(this, nextTag);
        newlyCreated = true;
    

    //hide current fragment
    ft.hide(fm.findFragmentByTag(Misc.currentContentFragmentTag));

    if(newlyCreated)
        ft.add(R.id.content_frame, nextFragment, nextTag);
    
    else
        ft.show(nextFragment);
    

    ft.addToBackStack(null);
    ft.commit();
    Misc.currentContentFragmentTag = nextTag;

    createBar(nextFragment);

这些是我来回导航的方式,我希望能够在 onBackPressed() 上实现返回方法。这有意义吗?

【问题讨论】:

类似问题已解决here > 享受 【参考方案1】:

我没有找到关于这个问题的任何好的答案,所以这是我的解决方案。

如果您想在每个片段中获取 backPress,请执行以下操作。

创建接口OnBackPressedListener

public interface OnBackPressedListener 
    void onBackPressed();

每个想要被通知backPress的片段实现这个接口

在父活动中,你可以覆盖onBackPressed()

@Override
public void onBackPressed() 
    List<Fragment> fragmentList = getSupportFragmentManager().getFragments();
    if (fragmentList != null) 
        //TODO: Perform your logic to pass back press here
        for(Fragment fragment : fragmentList)
           if(fragment instanceof OnBackPressedListener)
               ((OnBackPressedListener)fragment).onBackPressed();
           
        
    

【讨论】:

其他解决方案也可以,但对我来说这看起来更好。 :) 如果我的片段有一些我也想处理 OnBackPressed 的子片段怎么办? @Micer 在这种情况下,您可以在片段中收听onBackPressed() 方法调用,在那里您可以调用getChildFragmentManager() 并遍历子片段并在需要时调用onBackPressed() :) 顺便说一句最好案例是将这个逻辑放入BaseFragmentBaseActivity【参考方案2】:

你为什么不想使用后台堆栈?如果存在潜在问题或困惑,也许我们可以为您解决。

如果您想坚持自己的要求,只需覆盖 Activity 的 onBackPressed() 方法,并在单击 ActionBar 中的后退箭头时调用您正在调用的任何方法。

编辑:如何解决“黑屏”片段回栈问题:

您可以通过向片段管理器添加一个 backstack 侦听器来解决该问题。该侦听器检查片段返回堆栈是否为空并相应地完成 Activity:

您可以在 Activity 的 onCreate 方法中设置该侦听器:

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    FragmentManager fm = getFragmentManager();
    fm.addOnBackStackChangedListener(new OnBackStackChangedListener() 
        @Override
        public void onBackStackChanged() 
            if(getFragmentManager().getBackStackEntryCount() == 0) finish();
        
    );

【讨论】:

感谢您的回复,我试图避免返回堆栈的原因是当我添加到返回堆栈并删除片段时,当我单击按钮再次打开该片段时,我是出现黑屏,在这种情况下我应该进行某种检索吗?我是 Fragment 的新手,我正在尝试接管以前编写的代码。 @DJ-DOO 我已经这么认为了,这就是问题所在。当我从片段开始时,我遇到了完全相同的问题。但是,有一个解决该问题的方法。让我挖掘一些代码并更新我的答案...... 太棒了..我现在卡住了,不知道下一步该做什么 我现在只是在测试这个,虽然我不确定它是否能解决那个特定的问题。如果我有例如片段 A、B、C ,问题就存在。我从 A -> B -> C 去,我点击返回 A @DJ-DOO 我隐约记得这些片段交易有时很奇怪。你究竟是如何从一个片段切换到另一个片段的?你能更新你的问题并给出一个代码示例吗?【参考方案3】:

在您想要处理后退按钮的片段中,您应该在 oncreateview 中将内容附加到您的视图

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    View v = inflater.inflate(R.layout.second_fragment, container, false);
    v.setOnKeyListener(pressed);
    return v;




@Override
public boolean onKey(View v, int keyCode, KeyEvent event) 
    // TODO Auto-generated method stub
    if( keyCode == KeyEvent.KEYCODE_BACK )
            // back to previous fragment by tag
            myfragmentclass fragment = (myfragmentclass) getActivity().getSupportFragmentManager().findFragmentByTag(TAG);
            if(fragment != null)
                (getActivity().getSupportFragmentManager().beginTransaction()).replace(R.id.cf_g1_mainframe_fm, fragment).commit();
            
            return true;
        
        return false;
    
;

【讨论】:

你在哪里定义了'pressed'变量? 您可以像这样定义“按下”: OnKeyListener pressed = new OnKeyListener() @Override public boolean onKey(View v, int keyCode, KeyEvent event) if( keyCode == KeyEvent.KEYCODE_BACK ) 返回真; 返回假; ; @user2886881 在片段中覆盖onKey()?我不这么认为。【参考方案4】:
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) 
            override fun handleOnBackPressed() 
                Log.w("a","")
            
        )

【讨论】:

【参考方案5】:

您可以尝试覆盖onCreateAnimation,参数并捕获enter==false。这将在每次后按之前触发。

@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim)             
        if(!enter)
            //leaving fragment
            Log.d(TAG,"leaving fragment");
        
        return super.onCreateAnimation(transit, enter, nextAnim);
    

【讨论】:

这个解决方案真的很管用,但我在想,这是 hack 还是处理背压的解决方案【参考方案6】:

对于片段,您可以简单地添加

  getActivity().onBackPressed();

到你的代码

【讨论】:

【参考方案7】:

这对我有用:D

    @Override
    public void onResume() 
    super.onResume();

    if(getView() == null)
        return;
    

    getView().setFocusableInTouchMode(true);
    getView().requestFocus();
    getView().setOnKeyListener(new View.OnKeyListener() 
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) 

            if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK)
                // handle back button's click listener
                return true;
            
            return false;
        
    );

【讨论】:

【参考方案8】:

我找到了一种无需接口的新方法。您只需将以下代码添加到Fragment的onCreate()方法

//overriding the fragment's oncreate 
override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)

        //calling onBackPressedDispatcher and adding call back

        requireActivity().onBackPressedDispatcher.addCallback(this) 

      //do stuff here
            
        
    

【讨论】:

【参考方案9】:

使用这个:

@Override
public void onBackPressed() 
    int fragments = getFragmentManager().getBackStackEntryCount();
    if (fragments == 1) 
        finish();
    
    super.onBackPressed();

【讨论】:

以上是关于在 Android 片段中使用 onBackPressed()的主要内容,如果未能解决你的问题,请参考以下文章

android super.onBackPressed()计时

在 Android 中使用片段时处理后按

在android中使用带有片段的roboguice的任何简单示例?

当我们在android中使用backstack返回上一个片段时,上一个片段正在重新启动

Android:使用支持片段管理器时复制片段

Android控制双击返回按钮退出程序的代码