【问题标题】:Fragment hardware back button event called twice片段硬件后退按钮事件被调用两次
【发布时间】:2017-03-15 08:36:29
【问题描述】:

我正在尝试通过按特定顺序调用的片段实现后退导航:A->B->C 并通过硬件按钮返回,我希望它们保持有序。

我使用fragmenttransaction.replace 来切换没有addToBackStack 的片段,因为它使我的ActionBarMenu 行为不端。

问题是当我在片段C 上时,后退按钮会直接返回到A。我发现这是因为click事件被执行了两次我要去B和直接去A

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    setOnBackButtonPresed();
}

private void setOnBackButtonPresed() {
    getView().setFocusableInTouchMode(true);
    getView().requestFocus();
    getView().setOnKeyListener( new View.OnKeyListener()
    {
        @Override
        public boolean onKey( View v, int keyCode, KeyEvent event )
        {
            if( keyCode == KeyEvent.KEYCODE_BACK )
            {
                goBackToDays();
                return false;
            }
            return false;
        }
    } );
}

private void goBackToDays() {
    Log.e("fragmentC", "executing on back action")
}

logcat 结果:

03-15 08:37:17.353 21245-21245/com.test E/fragmentC: executing on back action
03-15 08:37:17.390 21245-21245/com.test E/fragmentC: executing on back action

谁能告诉我如何避免两次按钮事件?

【问题讨论】:

  • 你能在github上发布一个项目的基本设置吗?

标签: android android-fragments


【解决方案1】:

我认为“单击事件执行了两次”,因为您同时调用了事件 ACTION_DOWN 和 ACTION_UP。试试这个

@Override
    public boolean onKey( View v, int keyCode, KeyEvent event )
    {
        if( keyCode == KeyEvent.KEYCODE_BACK && event.getAction()== KeyEvent.ACTION_DOWN)
        {
            goBackToDays();
            return false;
        }
        return false;
    }

【讨论】:

  • 语法错误:Operator '==' cannot be applied to 'android.view.KeyEvent','int'
  • 对不起,我很困惑。已编辑!谢谢
【解决方案2】:

两件事:

  1. 即使你是replacing 的碎片,旧的OnKeyListener 仍然存在(稍后会被激发)。尝试在切换片段时删除旧的OnKeyListener
  2. 正如S-lightning 指出的那样,您需要记住有两个与关键事件相关的操作(KeyEvent.ACTION_DOWNKeyEvent.ACTION_UP)。

【讨论】:

    【解决方案3】:

    你可以做两件事

    1. “它使我的 ActionBarMenu 行为不端。”修复此问题。
    2. 在您的 Activity 上覆盖 onBackPressed() 并找出您当前加载的片段并替换为您想要的任何片段。

      Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.your_view_container);
      if (fragment instanceof FragmentThree) {
            //replace with your fragment ie. FragmentTwo
      } else if (fragment instanceof FragmentTwo) {
            //replace with your fragment ie. FragmentOne
      }
      

    【讨论】:

      【解决方案4】:

      如果您想“吸收”关键事件并阻止它传播到具有自己的 onBackPressed() 实现的 Activity,请返回 true

      if( keyCode == KeyEvent.KEYCODE_BACK )
      {
          goBackToDays();
          return true; // <-- should be TRUE, not FALSE
      }
      return false;
      

      【讨论】:

        【解决方案5】:

        在托管活动中覆盖onBackPressed() 方法。 这样做。

        private void replaceFragment (Fragment fragment){
          String backStateName = fragment.getClass().getName();
        
          FragmentManager manager = getSupportFragmentManager();
          boolean fragmentPopped = manager.popBackStackImmediate(backStateName, 0);
        
          if (!fragmentPopped){ //fragment not in back stack, create it.
             FragmentTransaction ft = manager.beginTransaction();
             ft.replace(R.id.content_frame, fragment);
             ft.addToBackStack(backStateName);
             ft.commit();
          }
        }
        .
        
        .
        
        @Override
        public void onBackPressed(){
          if (getSupportFragmentManager().getBackStackEntryCount() == 1){
            finish();
          }
          else {
            super.onBackPressed();
          }
        }
        

        这是解释清楚的答案。 link

        【讨论】:

          猜你喜欢
          • 2021-12-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多