android fragment返回按钮,Android Fragment处理后退按钮按下

Android Fragment处理后退按钮按下

这个问题在这里已有答案:

如何在Fragments中实现onBackPressed()?                                     40个答案

我的活动中有一些片段

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

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

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

编辑:申请不得从[3] ...... [6]返回[2]

25个解决方案

351 votes

当您在片段之间转换时,请致电OnKeyListener作为FragmentTransaction的一部分:

FragmentTransaction tx = fragmentManager.beginTransation();

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

如果您需要更详细的控制(即当某些片段可见时,您想要取消后退键),您可以在片段的父视图上设置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;

}

} );

Mark Allison answered 2019-02-08T22:06:53Z

247 votes

我宁愿做这样的事情:

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

}

}

saulobrito answered 2019-02-08T22:07:18Z

96 votes

如果你覆盖片段视图的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;

}

});

ANemati answered 2019-02-08T22:07:44Z

65 votes

将一个片段替换为另一个片段时使用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();

}

}

shimatai answered 2019-02-08T22:08:17Z

42 votes

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

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

此外,如果您的rootview(getView())不包含焦点,那么它将无法工作。 如果您再次单击任何控件,则需要使用getView()将焦点放在rootview上.requestFocus(); 在此之后只有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;

}

});

为我工作得很好。

Tejas Mehta answered 2019-02-08T22:09:00Z

23 votes

这里可以找到最理想的方法:片段:按下按钮时调用的回调& 定制它

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

}

}

kakoma answered 2019-02-08T22:09:24Z

16 votes

创建接口:

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> backClickListenersList = new ArrayList<>();

@Override

public void addBackClickListener(OnBackClickListener onBackClickListener) {

backClickListenersList.add(new WeakReference<>(onBackClickListener));

}

@Override

public void removeBackClickListener(OnBackClickListener onBackClickListener) {

for (Iterator> iterator = backClickListenersList.iterator();

iterator.hasNext();){

WeakReference 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 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;

}

}

krawa answered 2019-02-08T22:10:11Z

8 votes

@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 Kathiriya answered 2019-02-08T22:10:29Z

5 votes

或者你可以使用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();

}

}

Robert answered 2019-02-08T22:10:53Z

5 votes

我们创建了一个小型库,用于处理跨多个片段和/或活动的背压。 用法就像在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;

}

}

关于背压通知你的碎片:

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]

gingo answered 2019-02-08T22:11:43Z

4 votes

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

@Override

public void onBackPressed() {

if (getFragmentManager().getBackStackEntryCount() > 0)

getFragmentManager().popBackStack();

else

super.onBackPressed();

}

Joaquin Iurchuk answered 2019-02-08T22:12:07Z

3 votes

我正在使用SlidingMenu和Fragment,在这里介绍我的案例并希望帮助某人。

按[Back]键时的逻辑:

当SlidingMenu显示时,关闭它,没有更多的事情要做。

或者当第二个(或更多)片段显示时,滑回到上一个片段,并且没有其他事情要做。

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

}

}

}

RRTW answered 2019-02-08T22:13:06Z

3 votes

这是一个非常好的和可靠的解决方案:[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;

}

}

zatziky answered 2019-02-08T22:13:56Z

3 votes

工作守则:

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;

}

}

Android answered 2019-02-08T22:14:16Z

3 votes

我认为最简单的方法是创建一个接口,并在Activity中检查片段是否属于接口类型,如果是,则调用其方法来处理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中,当您处理pop(可能在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();

}

Matt Koala answered 2019-02-08T22:14:54Z

3 votes

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;

Ashish Soni answered 2019-02-08T22:15:11Z

2 votes

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

@Override

public void onBackStackChanged() {

int backStackEntryCount = getFragmentManager().getBackStackEntryCount();

if(backStackEntryCount > 0){

getActionBar().setDisplayHomeAsUpEnabled(true);

}else{

getActionBar().setDisplayHomeAsUpEnabled(false);

}

}

answered 2019-02-08T22:15:36Z

2 votes

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

在托管所有片段的活动的onBackPressed()中,找到要阻止的片段。 然后,如果找到,只需返回。 然后popBackStack永远不会发生这个片段。

@Override

public void onBackPressed() {

Fragment1 fragment1 = (Fragment1) getFragmentManager().findFragmentByTag(“Fragment1”);

if (fragment1 != null)

return;

if (getFragmentManager().getBackStackEntryCount() > 0){

getFragmentManager().popBackStack();

}

}

Harry Aung answered 2019-02-08T22:16:07Z

1 votes

将addToBackStack()添加到片段事务,然后使用下面的代码实现片段的反向导航

getSupportFragmentManager().addOnBackStackChangedListener(

new FragmentManager.OnBackStackChangedListener() {

public void onBackStackChanged() {

// Update your UI here.

}

});

Lalit Sharma answered 2019-02-08T22:16:31Z

1 votes

如果您正在使用FragmentActivity。 然后这样做

第一次调用你的片段里面。

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

...

}

sam answered 2019-02-08T22:17:09Z

1 votes

在您的活动中添加此代码

@覆盖

public void onBackPressed() {

if (getFragmentManager().getBackStackEntryCount() == 0) {

super.onBackPressed();

} else {

getFragmentManager().popBackStack();

}

}

并在commit()之前在Fragment中添加此行

ft.addToBackStack(“任何名字”);

Ravi answered 2019-02-08T22:17:53Z

1 votes

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

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

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

}

}

Muhammad Adil answered 2019-02-08T22:18:50Z

1 votes

在fragment类中将此代码放入后台事件:

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;

}

} );

tej shah answered 2019-02-08T22:19:15Z

0 votes

检查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);

}

Devrath answered 2019-02-08T22:19:41Z

-2 votes

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

}

});

Raj Kumar answered 2019-02-08T22:20:06Z

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值