【问题标题】:Android Fragment handle back button press [duplicate]Android Fragment句柄后退按钮按下[重复]
【发布时间】:2011-12-20 23:45:09
【问题描述】:

我的活动中有一些片段

[1], [2], [3], [4], [5], [6]

如果当前活动片段为 [2],则在返回按钮上按 I 必须从 [2] 返回到 [1],否则不执行任何操作。

这样做的最佳做法是什么?

编辑:应用程序不得从 [3]...[6] 返回到 [2]

【问题讨论】:

  • 换一种说法,你希望 Fragment [1] 成为 root 并且所有其他 Fragment ([2]...[6]) 处于下一个级别(即 root 的孩子)。这意味着,您可以从任何孩子导航回根(不是孩子)。这是正确的吗?
  • 首先了解 onBackPressed() 默认情况下对片段的工作方式非常重要...答案很简短:它首先通过 addToBackStack 搜索任何添加的片段,如果有,它确实与 popBackStack() 一样来弹出它,否则它会为活动执行默认的 onBackPressed()。因此,必须注意添加片段的方式。例如,如果您通过 add() 方法将 Fragment B 添加到现有的 Fragment A 但没有 addToBackStack(),则 onBackPressed() 将不会弹出 Fragment B 以返回到 Fragment A,但会在父活动上导致 onStop() .
  • 任何人都可以在这里给出答案:stackoverflow.com/questions/63760586/…

标签: android android-fragments


【解决方案1】:

当您在 Fragments 之间转换时,请在您的 FragmentTransaction 中调用 addToBackStack()

FragmentTransaction tx = fragmentManager.beginTransation();
tx.replace( R.id.fragment, new MyFragment() ).addToBackStack( "tag" ).commit();

如果您需要更详细的控制(即,当某些 Fragment 可见时,您想要抑制返回键),您可以在 Fragment 的父视图上设置 OnKeyListener

//You need to add the following line for this solution to work; thanks skayred
fragment.getView().setFocusableInTouchMode(true);
fragment.getView().requestFocus();
fragment.getView().setOnKeyListener( new OnKeyListener()
{
    @Override
    public boolean onKey( View v, int keyCode, KeyEvent event )
    {
        if( keyCode == KeyEvent.KEYCODE_BACK )
        {
            return true;
        }
        return false;
    }
} );

【讨论】:

  • 从视图中处理 OnKey 不起作用
  • 我确认 setOnKeyListener 对我不起作用,后退按钮仍然会导致转到旧片段。
  • 如果你想让它工作,你必须打电话给fragment.getView().setFocusableInTouchMode(true);
  • 工作正常,但还必须添加 getView().requestFocus()
  • 此解决方案仅在您的视图中没有任何 requestFoucus 项目时才有效。一旦您将请求从根视图更改为其他视图元素(例如编辑文本),它就根本不起作用。 ..
【解决方案2】:

我宁愿做这样的事情:

private final static String TAG_FRAGMENT = "TAG_FRAGMENT";

private void showFragment() {
    final Myfragment fragment = new MyFragment();
    final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.replace(R.id.fragment, fragment, TAG_FRAGMENT);
    transaction.addToBackStack(null);
    transaction.commit();
}

@Override
public void onBackPressed() {
    final Myfragment fragment = (Myfragment) getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT);

    if (fragment.allowBackPressed()) { // and then you define a method allowBackPressed with the logic to allow back pressed or not
        super.onBackPressed();
    }
}

【讨论】:

  • 使用片段实现的接口,可以在多个场景中复用相同的代码。
  • fragment类的allowBackPressed方法要写什么??
  • 如果您应该在Fragment 中抑制后退按钮,则可以正常工作,但如果您不想处理实际的按钮按下,则不能。
  • @DmitryZaitsev 为什么不呢?你想做什么,这不会让你做?
  • 好人,这应该是公认的答案。在每个片段中定义 OnKeyListener 是一种拖累
【解决方案3】:

我正在使用 SlidingMenu 和 Fragment,在这里展示我的案例并希望对某人有所帮助。

按下 [Back] 键时的逻辑:

  1. 当 SlidingMenu 显示时,关闭它,没有更多事情可做。
  2. 或者当第二个(或更多)片段显示时,滑回上一个片段,没有更多事情要做。
  3. SlidingMenu 不显示,当前 Fragment 为 #0,执行原 [Back] 键即可。

    public class Main extends SherlockFragmentActivity
    {
      private SlidingMenu menu=null;
      Constants.VP=new ViewPager(this);
    
      //Some stuff...
    
      @Override
      public void onBackPressed()
      {
        if(menu.isMenuShowing())
        {
          menu.showContent(true); //Close SlidingMenu when menu showing
          return;
        }
        else
        {
          int page=Constants.VP.getCurrentItem();
          if(page>0)
          {
            Constants.VP.setCurrentItem(page-1, true); //Show previous fragment until Fragment#0
            return;
          }
          else
          {super.onBackPressed();} //If SlidingMenu is not showing and current Fragment is #0, do the original [Back] key does. In my case is exit from APP
        }
      }
    }
    

【讨论】:

    【解决方案4】:

    在这里可以找到最理想的方法: Fragment: which callback invoked when press back button & customize it

    public class MyActivity extends Activity
    {
        //...
        //Defined in Activity class, so override
        @Override
        public void onBackPressed()
        {
            super.onBackPressed();
            myFragment.onBackPressed();
        }
    }
    
    public class MyFragment extends Fragment
    {
        //Your created method
        public static void onBackPressed()
        {
            //Pop Fragments off backstack and do your other checks
        }
    }
    

    【讨论】:

    • 但它说 The method onBackPressed() is undefined for the type Fragment
    • 你需要自己创建方法,你不要覆盖它。它也可以叫任何你喜欢的名字。
    • 这个方法看起来很干净,但是如果多个片段以不同方式处理后退按钮按下怎么办?例如,片段 A 对用户可见,并且他们点击了返回按钮。如果片段 B 也使用单独的 onBackPressed 方法,如何确保 Activity 正在调用正确的 onBackPressed() 方法?
    • 我解决了我上面的问题。在活动的 onBackPRessed 方法中,我在 ViewPager 的 getCurrentItem() 方法上执行了 java switch。这将返回一个整数值,表示用户当前正在查看的页面。这样做可以让我找出用户在按下后退按钮时所在的页面。
    • 我在没有使用静态修饰符的情况下对其进行了测试并且工作正常。
    【解决方案5】:

    或者您可以使用getSupportFragmentManager().getBackStackEntryCount() 来检查要做什么:

    @Override
        public void onBackPressed() {
    
            logger.d("@@@@@@ back stack entry count : " + getSupportFragmentManager().getBackStackEntryCount());
    
            if (getSupportFragmentManager().getBackStackEntryCount() != 0) {
    
                // only show dialog while there's back stack entry
                dialog.show(getSupportFragmentManager(), "ConfirmDialogFragment");
    
            } else if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
    
                // or just go back to main activity
                super.onBackPressed();
            }
        }
    

    【讨论】:

      【解决方案6】:

      如果你覆盖了你需要的片段视图的 onKey 方法:

          view.setFocusableInTouchMode(true);
          view.requestFocus();
          view.setOnKeyListener(new View.OnKeyListener() {
                  @Override
                  public boolean onKey(View v, int keyCode, KeyEvent event) {
                      Log.i(tag, "keyCode: " + keyCode);
                      if( keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
                          Log.i(tag, "onKey Back listener is working!!!");
                          getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
                          return true;
                      } 
                      return false;
                  }
              });
      

      【讨论】:

      • 通过我的应用设置,我意识到这需要在片段对象的 onStart() 方法被调用后调用。我正在使用这个解决方案 - 谢谢
      • 对我来说它调用了 2 次...
      • @AndroidDev 在这种情况下,视图是片段的 OnCreateView 返回的内容,它将在片段中。
      • @Pragna 将行 if(keyCode == KeyEvent.KEYCODE_BACK) 替换为 if(keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP)
      • 如果用户点击片段中的 EditText 将不起作用。
      【解决方案7】:

      将 addToBackStack() 添加到片段事务中,然后使用以下代码为片段实现返回导航

      getSupportFragmentManager().addOnBackStackChangedListener(
          new FragmentManager.OnBackStackChangedListener() {
              public void onBackStackChanged() {
                  // Update your UI here.
              }
          });
      

      【讨论】:

      • 它不会让你真正覆盖返回堆栈更改的行为。 Fragment 会从后栈中弹出,你无法阻止。
      【解决方案8】:

      如果您想处理硬件返回键事件,则必须在 Fragment 的 onActivityCreated() 方法中执行以下代码。

      您还需要检查 Action_Down 或 Action_UP 事件。如果不检查则 onKey() 方法会调用 2 次。

      另外,如果您的 rootview(getView()) 不包含焦点,那么它将无法工作。如果您单击了任何控件,那么您需要再次使用 getView().requestFocus(); 将焦点放在 rootview 上。在此之后只有 onKeydown() 会调用。

      getView().setFocusableInTouchMode(true);
      getView().requestFocus();
      
      getView().setOnKeyListener(new OnKeyListener() {
              @Override
              public boolean onKey(View v, int keyCode, KeyEvent event) {
                      if (event.getAction() == KeyEvent.ACTION_DOWN) {
                          if (keyCode == KeyEvent.KEYCODE_BACK) {
                              Toast.makeText(getActivity(), "Back Pressed", Toast.LENGTH_SHORT).show();
                          return true;
                          }
                      }
                      return false;
                  }
              });
      

      对我来说工作得很好。

      【讨论】:

      • 这行得通。我将 getView() 设置为我的 rootView 并且一切正常。
      • 这个@JonasB 是什么意思
      • 我使用rootView.requestFocus();而不是getView().requestFocus();
      • 不起作用 EditText 获得焦点。
      • @HiteshSahu 我也有同样的问题,你找到解决办法了吗?
      【解决方案9】:

      当用另一个片段替换一个片段时使用 addToBackStack 方法:

      getFragmentManager().beginTransaction().replace(R.id.content_frame, fragment).addToBackStack("my_fragment").commit();
      

      然后在您的活动中,使用以下代码从一个片段返回到另一个片段(前一个)。

      @Override
      public void onBackPressed() {
          if (getFragmentManager().getBackStackEntryCount() > 0) {
              getFragmentManager().popBackStack();
          } else {
              super.onBackPressed();
          }
      }
      

      【讨论】:

      • 这是处理返回键最优雅的方式。检查密钥代码是老派:)
      • 如果我想要自定义动画 onBackPressed 怎么办?@shimatai
      • @MaulikM.Dodia 你试过overridePendingTransition(R.anim.fadein, R.anim.fadeout);吗?
      • 太棒了:) +1 ...
      • 我在我的安卓应用中使用了这个方法。
      【解决方案10】:

      检查 backstack 效果很好


      @Override
      public boolean onKeyDown(int keyCode, KeyEvent event)
      {
          if (keyCode == KeyEvent.KEYCODE_BACK)
          {
              if (getFragmentManager().getBackStackEntryCount() == 1)
              {
                  // DO something here since there is only one fragment left
                  // Popping a dialog asking to quit the application
                  return false;
              }
          }
          return super.onKeyDown(keyCode, event);
      }
      

      【讨论】:

        【解决方案11】:

        如果您使用的是 FragmentActivity。然后这样做

        首先在你的 Fragment 中调用 This。

        public void callParentMethod(){
            getActivity().onBackPressed();
        }
        

        然后在您的父级 FragmentActivity 类中调用 onBackPressed 方法。

        @Override
        public void onBackPressed() {
          //super.onBackPressed();
          //create a dialog to ask yes no question whether or not the user wants to exit
          ...
        }
        

        【讨论】:

          【解决方案12】:

          这是一个非常好的和可靠的解决方案:http://vinsol.com/blog/2014/10/01/handling-back-button-press-inside-fragments/

          这家伙制作了一个抽象片段来处理 backPress 行为并使用策略模式在活动片段之间切换。

          对于你们中的一些人来说,抽象类可能有一点缺点......

          简而言之,链接中的解决方案如下所示:

          // Abstract Fragment handling the back presses
          
          public abstract class BackHandledFragment extends Fragment {
              protected BackHandlerInterface backHandlerInterface;
              public abstract String getTagText();
              public abstract boolean onBackPressed();
          
              @Override
              public void onCreate(Bundle savedInstanceState) {
                  super.onCreate(savedInstanceState);
                  if(!(getActivity()  instanceof BackHandlerInterface)) {
                      throw new ClassCastException("Hosting activity must implement BackHandlerInterface");
                  } else {
                      backHandlerInterface = (BackHandlerInterface) getActivity();
                  }
              }
          
              @Override
              public void onStart() {
                  super.onStart();
          
                  // Mark this fragment as the selected Fragment.
                  backHandlerInterface.setSelectedFragment(this);
              }
          
              public interface BackHandlerInterface {
                  public void setSelectedFragment(BackHandledFragment backHandledFragment);
              }
          }   
          

          以及在活动中的用法:

          // BASIC ACTIVITY CODE THAT LETS ITS FRAGMENT UTILIZE onBackPress EVENTS 
          // IN AN ADAPTIVE AND ORGANIZED PATTERN USING BackHandledFragment
          
          public class TheActivity extends FragmentActivity implements BackHandlerInterface {
              private BackHandledFragment selectedFragment;
          
              @Override
              public void onBackPressed() {
                  if(selectedFragment == null || !selectedFragment.onBackPressed()) {
                      // Selected fragment did not consume the back press event.
                      super.onBackPressed();
                  }
              }
          
              @Override
              public void setSelectedFragment(BackHandledFragment selectedFragment) {
                  this.selectedFragment = selectedFragment;
              }
          }
          

          【讨论】:

            【解决方案13】:

            在您的活动中添加此代码

            @Override

            public void onBackPressed() {
                if (getFragmentManager().getBackStackEntryCount() == 0) {
                    super.onBackPressed();
                } else {
                    getFragmentManager().popBackStack();
                }
            }
            

            并在你的 Fragment 之前的 commit() 之前添加这一行

            ft.addToBackStack("任何名字");

            【讨论】:

              【解决方案14】:

              您可以从getActionBar().setDisplayHomeAsUpEnabled() 使用:

              @Override
              public void onBackStackChanged() {
                  int backStackEntryCount = getFragmentManager().getBackStackEntryCount();
              
                  if(backStackEntryCount > 0){
                      getActionBar().setDisplayHomeAsUpEnabled(true);
                  }else{
                      getActionBar().setDisplayHomeAsUpEnabled(false);
                  }
              }
              

              【讨论】:

                【解决方案15】:

                如果您管理每个事务添加到后台堆栈的流程,那么您可以执行类似的操作,以便在用户按下返回按钮时显示前一个片段(您也可以映射主页按钮)。

                @Override
                public void onBackPressed() {
                    if (getFragmentManager().getBackStackEntryCount() > 0)
                        getFragmentManager().popBackStack();
                    else
                        super.onBackPressed();
                }
                

                【讨论】:

                  【解决方案16】:

                  对于那些使用静态片段的人

                  如果你有一个静态片段,那么它会更好。 制作片段的实例对象

                  private static MyFragment instance=null;
                  

                  在 MyFragment 的 onCreate() 中初始化该实例

                    instance=this;
                  

                  也做一个函数来获取实例

                   public static MyFragment getInstance(){
                     return instance;
                  }
                  

                  也做函数

                  public boolean allowBackPressed(){
                      if(allowBack==true){
                          return true;
                      }
                      return false;
                  }
                  
                  
                   //allowBack is a boolean variable that will be set to true at the action 
                   //where you want that your backButton should not close activity. In my case I open 
                   //Navigation Drawer then I set it to true. so when I press backbutton my 
                   //drawer should be get closed
                  
                  public void performSomeAction(){
                      //.. Your code
                      ///Here I have closed my drawer
                  }
                  

                  在你的活动中你可以做

                  @Override
                  public void onBackPressed() {
                  
                      if (MyFragment.getInstance().allowBackPressed()) { 
                          MyFragment.getInstance().performSomeAction();
                      }
                      else{
                          super.onBackPressed();
                      }
                  }
                  

                  【讨论】:

                  • 如果您有多个片段使用不同的返回行为怎么办?这行不通!
                  • 如果您说这些返回行为将添加到片段中,那么您可能希望在这些片段中添加不同的回调,这些回调会将按下按钮的信息发送回活动并从那里活动可以处理接下来应该做的事情。
                  • 您需要回调作为实现后压行为的片段数量,这将导致不必要的样板代码。这就是重点
                  【解决方案17】:

                  工作代码:

                  package com.example.keralapolice;
                  
                  import android.app.Fragment;
                  import android.app.FragmentManager;
                  import android.app.FragmentManager.OnBackStackChangedListener;
                  import android.content.Intent;
                  import android.os.Bundle;
                  import android.util.Log;
                  import android.view.Gravity;
                  import android.view.KeyEvent;
                  import android.view.LayoutInflater;
                  import android.view.View;
                  import android.view.ViewGroup;
                  import android.widget.Toast;
                  
                  public class ChiefFragment extends Fragment {
                      View view;
                  
                      // public OnBackPressedListener onBackPressedListener;
                  
                      @Override
                      public View onCreateView(LayoutInflater inflater,
                              ViewGroup container, Bundle args) {
                  
                          view = inflater.inflate(R.layout.activity_chief, container, false);
                          getActivity().getActionBar().hide();
                          view.setFocusableInTouchMode(true);
                          view.requestFocus();
                          view.setOnKeyListener(new View.OnKeyListener() {
                              @Override
                              public boolean onKey(View v, int keyCode, KeyEvent event) {
                                  Log.i(getTag(), "keyCode: " + keyCode);
                                  if (keyCode == KeyEvent.KEYCODE_BACK) {
                                      getActivity().getActionBar().show();
                                      Log.i(getTag(), "onKey Back listener is working!!!");
                                      getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
                                      // String cameback="CameBack";
                                      Intent i = new Intent(getActivity(), home.class);
                                      // i.putExtra("Comingback", cameback);
                                      startActivity(i);
                                      return true;
                                  } else {
                                      return false;
                                  }
                              }
                          });
                          return view;
                      }
                  }
                  

                  【讨论】:

                  • 工作代码的家伙
                  【解决方案18】:

                   @Override
                      public void onResume() {
                  
                          super.onResume();
                  
                          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){
                  
                                      if (mDrawerLayout.isDrawerOpen(GravityCompat.START)){
                                          mDrawerLayout.closeDrawer(GravityCompat.START);
                                      }
                                      return true;
                                  }
                  
                                  return false;
                              }
                          });
                      }
                  

                  【讨论】:

                  • 嗨@Ranjit,仅代码的答案通常不受欢迎。请提供支持性解释。
                  • 把这个 coad 放在你的 NavagationDrawerFragment 上,这里 mDrawerLayout 就是你的 DrawerLayout,它会工作的..
                  • 说明:如您所知,片段没有 onbackpress() 方法,但每次关闭或打开 navagationdrrawer 时都会检查 onResume 方法,因此它可以工作.. :-)
                  • 有用的答案 +1 好友
                  • 是的,它s right, but what happen when you focus to any edittext and after that pressed back button? after focus on any view how can i get back event of fragment? you can find best answer from below and its 完美运行:stackoverflow.com/questions/18755550/…
                  【解决方案19】:

                  在片段类中将此代码用于返回事件:

                   rootView.setFocusableInTouchMode(true);
                          rootView.requestFocus();
                          rootView.setOnKeyListener( new OnKeyListener()
                          {
                              @Override
                              public boolean onKey( View v, int keyCode, KeyEvent event )
                              {
                                  if( keyCode == KeyEvent.KEYCODE_BACK )
                                  {
                                      FragmentManager fragmentManager = getFragmentManager();
                                      fragmentManager.beginTransaction()
                                              .replace(R.id.frame_container, new Book_service_provider()).commit();
                  
                                      return true;
                                  }
                                  return false;
                              }
                          } );
                  

                  【讨论】:

                    【解决方案20】:

                    我认为最简单的方法是创建一个接口,在Activity中检查fragment是否属于接口类型,如果是,调用它的方法来处理pop。这是在片段中实现的接口。

                    public interface BackPressedFragment {
                    
                        // Note for this to work, name AND tag must be set anytime the fragment is added to back stack, e.g.
                        // getActivity().getSupportFragmentManager().beginTransaction()
                        //                .replace(R.id.fragment_container, MyFragment.newInstance(), "MY_FRAG_TAG")
                        //                .addToBackStack("MY_FRAG_TAG")
                        //                .commit();
                        // This is really an override. Should call popBackStack itself.
                        void onPopBackStack();
                    }
                    

                    这里是如何实现它。

                    public class MyFragment extends Fragment implements BackPressedFragment
                        @Override
                        public void onPopBackStack() {
                            /* Your code goes here, do anything you want. */
                            getActivity().getSupportFragmentManager().popBackStack();
                    }
                    

                    在你的 Activity 中,当你处理弹出时(可能在 onBackPressed 和 onOptionsItemSelected 中),使用这个方法弹出 backstack:

                    public void popBackStack() {
                        FragmentManager fm = getSupportFragmentManager();
                        // Call current fragment's onPopBackStack if it has one.
                        String fragmentTag = fm.getBackStackEntryAt(fm.getBackStackEntryCount() - 1).getName();
                        Fragment currentFragment = getSupportFragmentManager().findFragmentByTag(fragmentTag);
                        if (currentFragment instanceof BackPressedFragment)
                            ((BackPressedFragment)currentFragment).onPopBackStack();
                        else
                            fm.popBackStack();
                    }
                    

                    【讨论】:

                      【解决方案21】:

                      创建接口:

                      BackButtonHandlerInterface

                      public interface BackButtonHandlerInterface {
                          void addBackClickListener (OnBackClickListener onBackClickListener);
                          void removeBackClickListener (OnBackClickListener onBackClickListener);
                      }
                      

                      OnBackClickListener

                      public interface OnBackClickListener {
                           boolean onBackClick();
                      }
                      

                      活动中:

                      public class MainActivity extends AppCompatActivity implements BackButtonHandlerInterface {
                      
                          private ArrayList<WeakReference<OnBackClickListener>> backClickListenersList = new ArrayList<>();
                      
                          @Override
                          public void addBackClickListener(OnBackClickListener onBackClickListener) {
                              backClickListenersList.add(new WeakReference<>(onBackClickListener));
                          }
                      
                          @Override
                          public void removeBackClickListener(OnBackClickListener onBackClickListener) {
                              for (Iterator<WeakReference<OnBackClickListener>> iterator = backClickListenersList.iterator();
                               iterator.hasNext();){
                                  WeakReference<OnBackClickListener> weakRef = iterator.next();
                                  if (weakRef.get() == onBackClickListener){
                                      iterator.remove();
                                  }
                              }
                          }
                      
                          @Override
                          public void onBackPressed() {
                              if(!fragmentsBackKeyIntercept()){
                                  super.onBackPressed();
                              }
                          }
                      
                          private boolean fragmentsBackKeyIntercept() {
                              boolean isIntercept = false;
                              for (WeakReference<OnBackClickListener> weakRef : backClickListenersList) {
                                  OnBackClickListener onBackClickListener = weakRef.get();
                                  if (onBackClickListener != null) {
                                      boolean isFragmIntercept = onBackClickListener.onBackClick();
                                      if (!isIntercept) isIntercept = isFragmIntercept;
                                  }
                              }
                              return isIntercept;
                          }
                      }
                      

                      片段中:

                      public class MyFragment extends Fragment implements OnBackClickListener{
                      
                          private BackButtonHandlerInterface backButtonHandler;
                      
                          @Override
                          public void onAttach(Activity activity) {
                              super.onAttach(activity);
                              backButtonHandler = (BackButtonHandlerInterface) activity;
                              backButtonHandler.addBackClickListener(this);
                          }
                      
                          @Override
                          public void onDetach() {
                              super.onDetach();
                              backButtonHandler.removeBackClickListener(this);
                              backButtonHandler = null;
                          }
                      
                          @Override
                          public boolean onBackClick() {
                              //This method handle onBackPressed()! return true or false
                              return false;
                          }
                      
                      }
                      

                      更新

                      Provide custom back navigation

                      class MyFragment : Fragment() {
                      
                          override fun onCreate(savedInstanceState: Bundle?) {
                              super.onCreate(savedInstanceState)
                      
                              // This callback will only be called when MyFragment is at least Started.
                              val callback = requireActivity().onBackPressedDispatcher.addCallback(this) {
                                  // Handle the back button event
                              }
                      
                              // The callback can be enabled or disabled here or in the lambda
                          }
                      
                      }
                      

                      【讨论】:

                      • 虽然需要更多的编码...但是对于设备后退按钮按下手柄更好...+1
                      • 如果您在 Fragment 的 onDetach() 中删除侦听器,为什么还要使用 Wea​​kReference? :)
                      • 我认为这更复杂,需要编写更多代码,我不喜欢解决这种问题
                      • 上次更新非常有用且易于理解我真的建议任何使用导航组件并希望直接从片段中传递返回操作而无需将方法回调从活动传递到当前的麻烦显示的片段。
                      • 任何人都可以解决这个问题:stackoverflow.com/questions/63760586/…
                      【解决方案22】:

                      查看所有解决方案后,我意识到有一个更简单的解决方案。

                      在托管所有 Fragment 的 Activity 的 onBackPressed() 中,找到要防止后按的 Fragment。然后如果找到,就返回。那么 popBackStack 将永远不会发生在这个片段上。

                        @Override
                      public void onBackPressed() {
                      
                              Fragment1 fragment1 = (Fragment1) getFragmentManager().findFragmentByTag(“Fragment1”);
                              if (fragment1 != null)
                                  return;
                      
                              if (getFragmentManager().getBackStackEntryCount() > 0){
                                  getFragmentManager().popBackStack();
                      
                              }
                      }
                      

                      【讨论】:

                      • 谢谢,它有效..!
                      【解决方案23】:

                      在您的 oncreateView() 方法中,您需要编写此代码,在 KEYCODE_BACk 条件下,您可以编写任何您想要的功能

                      View v = inflater.inflate(R.layout.xyz, container, false);
                      //Back pressed Logic for fragment 
                      v.setFocusableInTouchMode(true); 
                      v.requestFocus(); 
                      v.setOnKeyListener(new View.OnKeyListener() { 
                          @Override 
                          public boolean onKey(View v, int keyCode, KeyEvent event) {
                              if (event.getAction() == KeyEvent.ACTION_DOWN) {
                                  if (keyCode == KeyEvent.KEYCODE_BACK) {
                                      getActivity().finish(); 
                                      Intent intent = new Intent(getActivity(), MainActivity.class);
                                      startActivity(intent);
                      
                                      return true; 
                                  } 
                              } 
                              return false; 
                          } 
                      }); 
                      

                      【讨论】:

                        【解决方案24】:
                                    rootView.setFocusableInTouchMode(true);
                                    rootView.requestFocus();
                                    rootView.setOnKeyListener(new View.OnKeyListener() {
                                    @Override
                                    public boolean onKey(View v, int keyCode, KeyEvent event)   {
                                    if (keyCode == KeyEvent.KEYCODE_BACK) {
                        
                        
                                        Fragment NameofFragment = new NameofFragment;
                        
                                        FragmentTransaction  transaction=getFragmentManager().beginTransaction();
                                        transaction.replace(R.id.frame_container,NameofFragment);
                        
                                        transaction.commit();
                        
                                        return true;
                                    }
                                    return false;
                                }
                            });
                        
                            return rootView;
                        

                        【讨论】:

                          【解决方案25】:

                          我们创建了一个小型库,用于处理跨多个片段和/或在 Activity 中的后按。使用就像在你的 gradle 文件中添加依赖一样简单:

                          compile 'net.skoumal.fragmentback:fragment-back:0.1.0'
                          

                          让你的片段实现BackFragment接口:

                          public abstract class MyFragment extends Fragment implements BackFragment {
                          
                              public boolean onBackPressed() {
                          
                                  // -- your code --
                          
                                  // return true if you want to consume back-pressed event
                                  return false;
                              }
                          
                              public int getBackPriority() {
                                  return NORMAL_BACK_PRIORITY;
                              }
                          }
                          

                          通知您的 Fragment 关于后按:

                          public class MainActivity extends AppCompatActivity {
                          
                              @Override
                              public void onBackPressed() {
                                  // first ask your fragments to handle back-pressed event
                                  if(!BackFragmentHelper.fireOnBackPressedEvent(this)) {
                                      // lets do the default back action if fragments don't consume it
                                      super.onBackPressed();
                                  }
                              }
                          }
                          

                          有关更多详细信息和其他用例,请访问 GitHub 页面:

                          https://github.com/skoumalcz/fragment-back

                          【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2018-03-29
                          • 2021-09-18
                          • 2012-05-24
                          • 1970-01-01
                          • 2019-02-03
                          • 1970-01-01
                          相关资源
                          最近更新 更多