【问题标题】:Fragment pressing back button片段按下后退按钮
【发布时间】:2013-09-12 04:47:56
【问题描述】:

我现在有一个包含片段的活动

[1] , [2] , [3] , [4]

如果按下按钮,[3],可以重定向到[4]

我想实现如下所示的后退按钮..

在 [4] 按下返回时,返回到 [3]

在 [3] 按下返回时,返回到 [2]

当按下 [1] 时,活动结束();

当涉及到当前实现时,它会完成活动而不是弹出片段。你能告诉我我应该做什么或记住什么吗?

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {

    if( keyCode==KeyEvent.KEYCODE_BACK) 
    {   

        finish();
    }       

        return super.onKeyDown(keyCode, event); 

}   

【问题讨论】:

    标签: android android-fragments back


    【解决方案1】:

    这对我有用。

    -当你从activity调用新的fragment时添加.addToBackStack(null)。

        FragmentTransaction mFragmentTransaction = getFragmentManager()
                    .beginTransaction();
        ....
        mFragmentTransaction.addToBackStack(null);
    

    -将 onBackPressed() 添加到您的活动中

        @Override
    public void onBackPressed() {
        if (getFragmentManager().getBackStackEntryCount() == 0) {
            this.finish();
        } else {
            getFragmentManager().popBackStack();
        }
    }
    

    【讨论】:

    • 这是来自 SO 的最佳和最简单的解决方案,恕我直言
    • 这是在没有方向改变的情况下工作,但是在方向改变之后,如果我按下返回按钮,我会得到黑屏
    • 这是完美的解决方案。
    • 这可行,但我想知道是否有人可以向我解释为什么这不是 Activity 的默认行为?
    • 我更愿意调用 super.onBackPressed();
    【解决方案2】:

    最简单的方法:

    onResume()

    @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) {
                    // handle back button's click listener
                    Toast.makeText(getActivity(), "Back press", Toast.LENGTH_SHORT).show();
                    return true;
                }
                return false;
            }
        });
    
    }
    

    编辑1:如果片段有EditText

    private EditText editText;
    

    onCreateView()

    editText = (EditText) rootView.findViewById(R.id.editText);
    

    onResume()

    @Override
    public void onResume() {
        super.onResume();
    
        editText.setOnKeyListener(new View.OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (keyCode == KeyEvent.KEYCODE_BACK) {
                    editText.clearFocus();
                }
                return false;
            }
        });
    
        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
                    Toast.makeText(getActivity(), "Back press", Toast.LENGTH_SHORT).show();
                    return true;
                }
                return false;
            }
        });
    
    }
    

    注意:如果您在片段中有 EditText,它将起作用。

    完成

    【讨论】:

    • 但是如果你的片段视图中有一个 EditText。所以这不会一直有效。例如:如果显示键盘并且 editext 请求焦点。
    • @david 我遇到了这个问题!
    • @david,我已经编辑了我的答案,它现在可以工作了。谢谢。
    • @ritmatter,我已经编辑了我的答案,它现在可以工作了。谢谢
    • @Jacky,我已经编辑了我的答案,它现在可以工作了。谢谢
    【解决方案3】:

    这对我来说是一个可行的解决方案:

    dialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
                        @Override
                        public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                            if (keyCode == KeyEvent.KEYCODE_BACK) {
                                // DO WHAT YOU WANT ON BACK PRESSED
                                return true;
                            }
                            return false;
                        }
                    });
    

    编辑:您可以将对话框替换为getView() 以获取片段。

    【讨论】:

    • 什么是对话框?它与片段有什么关系?
    • 这是一个警告对话框或对话框片段。我不确定我需要检查代码。
    【解决方案4】:

    试试这个简单的解决方案:

    在你的活动中实现 onBackPressed

     @Override
        public void onBackPressed() {
           if (getSupportFragmentManager().getBackStackEntryCount() > 1) {
                getSupportFragmentManager().popBackStack();
            } else {
                finish();
            }
        }
    

    如果您想在每次后按时弹出顶部片段,这将起作用。 注意:- 在向活动添加片段时,请务必将事务添加到后台堆栈以使其正常工作

    【讨论】:

      【解决方案5】:

      你可以用这个..为我工作..

      似乎片段 [3] 在按下返回时并未从视图中移除,因此您必须手动操作!

      首先,不要使用replace(),而是分别使用remove和add。好像 replace() 不能正常工作。

      接下来的部分是重写 onKeyDown 方法并在每次按下后退按钮时删除当前片段。

       @Override
       public boolean onKeyDown(int keyCode, KeyEvent event)
       {
       if (keyCode == KeyEvent.KEYCODE_BACK)
       {
          if (getSupportFragmentManager().getBackStackEntryCount() == 0)
          {
              this.finish();
              return false;
          }
          else
          {
              getSupportFragmentManager().popBackStack();
              removeCurrentFragment();
      
              return false;
          }
      
      
      
       }
      
        return super.onKeyDown(keyCode, event);
       }
      
      
      public void removeCurrentFragment()
      {
      FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
      
      Fragment currentFrag =  getSupportFragmentManager().findFragmentById(R.id.f_id);
      }
      

      【讨论】:

      • 你能告诉我 R.id.f_id 实际上是什么吗?
      • 你能告诉我 R.id.f_id 实际上是什么吗?
      • f_id 是您要删除的片段 id
      • 是自动生成的吗?
      • 否,如果您已获取片段并在 xml 文件中提供 id,则为其提供 id,否则默认情况下您可以使用 android.R.id.content 作为 id
      【解决方案6】:

      在包含片段的活动中的 onCreate() 中,添加一个 backstack 更改侦听器,如下所示:

          fragmentManager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
              @Override
              public void onBackStackChanged() {
                  List<Fragment> f = fragmentManager.getFragments();
                  Fragment frag = f.get(0);
                  currentFragment = frag.getClass().getSimpleName();
              }
          });
      

      (注意,我的 fragmentManager 被声明为全局的) 现在每次更改片段时,currentFragment 字符串都会成为当前片段的名称。然后在 onBackPressed() 活动中,您可以控制后退按钮的操作,如下所示:

          @Override
          public void onBackPressed() {
      
          switch (currentFragment) {
              case "FragmentOne":
                  // your code here 
                  return;
              case "FragmentTwo":
                  // your code here
                  return;
              default:
                  fragmentManager.popBackStack();
                  // default action for any other fragment (return to previous)
          }
      
      }
      

      我可以确认此方法对我有效。

      更新:Kotlin

      override fun onBackPressed() {
      
          when(supportFragmentManager.fragments[0].javaClass.simpleName){
              "FragmentOne" -> doActionOne()
              "FragmentTwo" -> doActionTwo()
              else -> supportFragmentManager.popBackStack()
          }
      }
      

      【讨论】:

      • 哇,太棒了,非常感谢。但是当我们有嵌套的片段时呢?例如我们在另一个片段中有子片段?
      • @parsadadras 嵌套片段不会受到影响,因为这取决于应用于主片段管理器而不是子片段管理器的片段侦听器。
      【解决方案7】:

      在 Fragment 中按下或处理返回按钮的解决方案。

      我解决问题的方式我相信它也会对你有所帮助:

      1.如果您的片段中没有任何编辑文本框,您可以使用以下代码

      这里 MainHomeFragment 是主要片段(当我从第二个片段按下返回按钮时,它也会带我进入 MainHomeFragment)

          @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){
      
                      MainHomeFragment mainHomeFragment = new SupplierHomeFragment();
                      android.support.v4.app.FragmentTransaction fragmentTransaction =
                              getActivity().getSupportFragmentManager().beginTransaction();
                      fragmentTransaction.replace(R.id.fragment_container, mainHomeFragment);
                      fragmentTransaction.commit();
      
                      return true;    
                  }    
                  return false;
              }
          }); }
      

      2.如果您有另一个名为 Somefragment 的片段并且它具有编辑文本框,那么您可以通过这种方式进行。

      private EditText editText;
      

      然后在,

      onCreateView():    
      editText = (EditText) view.findViewById(R.id.editText);
      

      然后覆盖 OnResume,

      @Override
      public void onResume() {
          super.onResume();
      
          editText.setOnKeyListener(new View.OnKeyListener() {
              @Override
              public boolean onKey(View v, int keyCode, KeyEvent event) {
                  if (keyCode == KeyEvent.KEYCODE_BACK) {
                      editTextOFS.clearFocus();
                      getView().requestFocus();
                  }
                  return false;
              }
          });
      
          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){
      
                      MainHomeFragment mainHomeFragment = new SupplierHomeFragment();
                      android.support.v4.app.FragmentTransaction fragmentTransaction =
                              getActivity().getSupportFragmentManager().beginTransaction();
                      fragmentTransaction.replace(R.id.fragment_container, mainHomeFragment);
                      fragmentTransaction.commit();
      
                      return true;
      
                  }
      
                  return false;
              }
          });
      
      }
      

      就是这样 (amitamie.com) :-) ;-)

      【讨论】:

        【解决方案8】:

        更好的解决方案可能是遵循一种设计模式,使后退按钮按下事件从活动片段向下传播到宿主 Activity。所以,这就像.. 如果活动片段之一消耗了后按,则 Activity 不会对其采取行动,反之亦然。

        一种方法是让您的所有片段扩展一个具有抽象“布尔 onBackPressed()”方法的基本片段。

        @Override
        public boolean onBackPressed() {
           if(some_condition)
              // Do something
              return true; //Back press consumed.
           } else {
              // Back-press not consumed. Let Activity handle it
              return false;
           }
        }
        

        跟踪 Activity 中的活动片段,并在它的 onBackPressed 回调中编写类似这样的内容

        @Override
        public void onBackPressed() {
           if(!activeFragment.onBackPressed())
              super.onBackPressed();
           }
        }
        

        这篇文章详细描述了这种模式

        【讨论】:

        • 完美解决方案。我总是更喜欢干净的解决方案而不是快速肮脏的解决方案。
        【解决方案9】:

        在这种情况下,我要做的是从 Activity 中实现 onBackPressed() 函数:

        @Override
        public void onBackPressed() {
           super.onBackPressed();
           FragmentManager fm = getSupportFragmentManager();
           MyFragment myFragment = (MyFragment) fm.findFragmentById(R.id.my_fragment);
        
           if((myFragmen.isVisible()){
              //Do what you want to do
           }
        }
        

        这也适用于您。

        【讨论】:

          【解决方案10】:

          如果你在片段中使用 webview,而不是在你的 onCreateView 方法中使用它

          webView.setOnKeyListener(new View.OnKeyListener(){
          
                  @Override
                  public boolean onKey(View view, int i, KeyEvent keyEvent) {
                      if((i==KeyEvent.KEYCODE_BACK)&& webView.canGoBack()){
                          webView.goBack();
                          return true;
                      }
                      return false;
                  }
              });
          

          并导入这个类

          import android.view.KeyEvent;
          

          【讨论】:

          • 这种回答已经有好几个人给出了。请删除你的。
          • 但是当我尝试其他答案时,他们没有给出我想要的结果。
          【解决方案11】:

          您可以在基本Fragment 中使用getFragmentManager().popBackStack() 返回。

          【讨论】:

            【解决方案12】:

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

            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;
                        }
                    });
            

            对我来说工作得很好。

            【讨论】:

            • 但如果片段视图中有 EditText。所以这不会一直有效。例如:如果显示键盘并且 editext 请求焦点。
            【解决方案13】:

            你可以在onCreateView中使用这个,你可以使用事务或者替换

             OnBackPressedCallback callback = new OnBackPressedCallback(true) {
                            @Override
                            public void handleOnBackPressed() {
                                //what you want to do 
                            }
                        };
                requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
            

            【讨论】:

              【解决方案14】:

              确保添加以下内容:

              if (event.getAction()!=KeyEvent.ACTION_DOWN)
                              return true;
              

              在onKey代码块中避免事件调用两次。

              【讨论】:

                【解决方案15】:

                我使用一种方法来更改它具有以下代码的片段

                 getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.enter, R.anim.exit, R.anim.pop_enter, R.anim.pop_exit).replace(R.id.content_frame, mContent, mContent.getClass().getSimpleName()).addToBackStack(null)
                                .commit();
                

                返回按钮是这个。

                @Override
                    public void onBackPressed() {
                        // note: you can also use 'getSupportFragmentManager()'
                        FragmentManager mgr = getSupportFragmentManager();
                        if (mgr.getBackStackEntryCount() == 1) {
                            // No backstack to pop, so calling super
                            finish();
                        } else {
                            mgr.popBackStack();
                        }
                    }
                

                需要注意的重要一点是我使用 1 来检查 getBackStackEntryCount 这是因为如果您不使用它而使用 0 用户将看不到最后一个后退按钮。

                【讨论】:

                  【解决方案16】:

                  使用这个(在 kotlin 中)

                   activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) {
                          override fun handleOnBackPressed() {
                              // in here you can do logic when backPress is clicked
                          }
                      })
                  

                  我认为这是最优雅的方式

                  【讨论】:

                    【解决方案17】:

                    试试这个,它对我有帮助:)

                     @Override  
                        public void onResume() { //Pressed return button - returns to the results menu
                            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) {
                                        /*Here your code*/
                                        return true;
                                    }
                                    return false;
                                }
                            });
                        }

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多