44

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

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

}   
4

17 回答 17

92

这对我有用。

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

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

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

    @Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() == 0) {
        this.finish();
    } else {
        getFragmentManager().popBackStack();
    }
}
于 2014-02-07T18:53:00.733 回答
61

最简单的方法:

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 , 它将起作用。

完毕

于 2014-11-26T09:04:43.680 回答
9

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

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()为片段。

于 2014-10-05T22:44:50.713 回答
9

Try this simple solution:

In your activity implement onBackPressed

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

This will work if you want to pop the top fragment on each back press. Note:- While adding fragment to activity always do add the transaction to back stack for this to work

于 2017-08-06T14:35:58.947 回答
8

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

当按下返回时,似乎片段 [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);
}
于 2013-09-12T05:05:47.363 回答
5

在您的活动中的 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)
    }

}

我可以确认这种方法对我有用。

更新:科特林

override fun onBackPressed() {

    when(supportFragmentManager.fragments[0].javaClass.simpleName){
        "FragmentOne" -> doActionOne()
        "FragmentTwo" -> doActionTwo()
        else -> supportFragmentManager.popBackStack()
    }
}
于 2018-07-08T02:43:11.190 回答
5

在 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):-) ;-)

于 2016-09-04T18:31:01.300 回答
4

更好的解决方案可能是遵循设计模式,以便后退按钮按下事件从活动片段向下传播到主机 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;
   }
}

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

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

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

于 2014-10-01T14:20:18.677 回答
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
   }
}

这也对你有用。

于 2015-02-06T23:40:09.093 回答
4

如果您在片段中使用 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;
于 2018-02-12T14:27:37.650 回答
3

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

于 2013-09-12T05:09:17.240 回答
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;
            }
        });

对我来说工作得很好。

于 2014-07-22T07:22:07.087 回答
2

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

 OnBackPressedCallback callback = new OnBackPressedCallback(true) {
                @Override
                public void handleOnBackPressed() {
                    //what you want to do 
                }
            };
    requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
于 2020-01-22T11:20:03.050 回答
1

确保添加以下内容:

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

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

于 2015-12-24T21:27:01.577 回答
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();

对于后退按钮 this 。

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

于 2017-06-30T23:42:55.077 回答
0

使用这个(在 kotlin 中)

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

我认为这是最优雅的方式

于 2020-09-22T09:25:30.077 回答
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;
            }
        });
    }

于 2021-03-05T12:51:59.683 回答