片段按下后退按钮

时间:2013-09-12 04:47:56

标签: android android-fragments back

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

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

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

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

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

当按下[3]时,返回[2]

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

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

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

    if( keyCode==KeyEvent.KEYCODE_BACK) 
    {   

        finish();
    }       

        return super.onKeyDown(keyCode, event); 

}   

17 个答案:

答案 0 :(得分:87)

这对我有用。

- 从活动中调用新片段时添加.addToBackStack(null)。

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

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

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

答案 1 :(得分:50)

最简单的方式:

<强>的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 ,它将会有效。

完成

答案 2 :(得分:8)

这对我来说是一个有效的解决方案:

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()的对话框替换为片段。

答案 3 :(得分:7)

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

当按下后退时,似乎没有从视图中删除片段[3],所以你必须手动完成!

首先,不要使用replace(),而是使用remove并单独添加。似乎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);
}

答案 4 :(得分:5)

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

在你的活动中实现onBackPressed

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

如果您想在每次背面按下弹出顶部片段,这将有效。 注意: - 向活动添加片段时,请务必将事务添加到后台,以便工作

答案 5 :(得分:4)

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

一种方法是让你的所有片段扩展一个基本片段,该片段具有抽象的布尔值onBackPressed()&#39;方法

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

跟踪活动内部的活动片段,并在其内部的onBackPressed回调中写下这样的内容

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

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

答案 6 :(得分:4)

在这种情况下我做的是从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
   }
}

这对你有用。

答案 7 :(得分:4)

在片段中按下或处理后退按钮的解决方案。

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

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的片段并且它有Edit文本框,那么你就可以这样做。

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 :(得分:3)

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

答案 9 :(得分:2)

您还需要检查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;
            }
        });

为我工作得非常好。

答案 10 :(得分:2)

您可以在onCreateView中使用它,可以使用事务或替换

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

答案 11 :(得分:2)

如果您在片段中使用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;

答案 12 :(得分:1)

请务必添加以下内容:

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

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

答案 13 :(得分:1)

好吧,我终于找到了一个好的解决方案。

在容纳片段的活动的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();
        }
    });

(还添加了我的fragmenManager声明为全局) 现在,每次更改片段时,当前片段字符串将成为当前片段的名称。然后,在活动onBackPressed()中,您可以这样控制后退按钮的操作:

    @Override
    public void onBackPressed() {

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

}

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

答案 14 :(得分:0)

我使用一种方法来改变代码后面的片段

 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,则用户看不到最后一个后退按钮。

答案 15 :(得分:0)

(在Kotlin中)使用此

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

我认为这是最优雅的方式

答案 16 :(得分:0)

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

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