如何在Fragments中实现onBackPressed()?

android android-fragments onbackpressed

390283 观看

30回复

4956 作者的声誉

有没有一种方法可以onBackPressed()在Android Fragment中实现类似于我们在Android Activity中实现的方式?

正如Fragment生命周期所没有的那样onBackPressed()。有没有其他替代方法来覆盖onBackPressed()Android 3.0碎片?

作者: Android_programmer_camera 的来源 发布者: 2011 年 3 月 27 日

回应 (30)


64

2144 作者的声誉

如果您想要这种功能,则需要在活动中覆盖它,然后YourBackPressed为所有片段添加一个接口,只要按下后退按钮,就会调用相关片段。

编辑:我想追加我之前的回答。

如果我今天要这样做,我会使用广播,或者如果我希望其他面板同时更新到主/主内容面板,则可以使用有序广播。

LocalBroadcastManager在支持库中可以提供帮助,您只需发送广播onBackPressed并订阅您关注的片段。我认为Messaging是一个更加分离的实现,并且可以更好地扩展,所以它现在是我的官方实现建议。只需使用该Intent操作作为邮件的过滤器即可。发送您新创建的ACTION_BACK_PRESSED,从您的活动中发送它并在相关片段中收听它。

作者: HaMMeReD 发布者: 10.08.2011 07:20

92

6977 作者的声誉

根据@HaMMeRed的回答,这里是伪代码应该如何工作。假设您的主要活动被调用BaseActivity,其中包含子片段(如SlidingMenu lib示例中所示)。以下是步骤:

首先我们需要创建接口和类来实现其接口以具有泛型方法

  1. 创建类接口 OnBackPressedListener

    public interface OnBackPressedListener {
        public void doBack();
    }
    
  2. 创建实现技能的类 OnBackPressedListener

    public class BaseBackPressedListener implements OnBackPressedListener {
        private final FragmentActivity activity;
    
        public BaseBackPressedListener(FragmentActivity activity) {
            this.activity = activity;
        }
    
        @Override
        public void doBack() {
            activity.getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        }
    }
    
  3. 从现在开始,我们将处理我们的代码BaseActivity及其片段

  4. 在班级上创建私人监听器 BaseActivity

    protected OnBackPressedListener onBackPressedListener;
    
  5. create方法来设置监听器 BaseActivity

    public void setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
        this.onBackPressedListener = onBackPressedListener;
    }
    
  6. 在覆盖中onBackPressed实现类似的东西

    @Override
    public void onBackPressed() {
        if (onBackPressedListener != null)
            onBackPressedListener.doBack();
        else
            super.onBackPressed();
    
  7. 在你的片段中onCreateView你应该添加我们的监听器

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        activity = getActivity();
    
        ((BaseActivity)activity).setOnBackPressedListener(new BaseBackPressedListener(activity));
    
        View view = ... ;
    //stuff with view
    
        return view;
    }
    

瞧,现在当你点击片段时,你应该抓住你的自定义背面方法。

作者: deadfish 发布者: 02.10.2013 09:09

24

3713 作者的声誉

只需addToBackStack在您的片段之间转换时添加,如下所示:

fragmentManager.beginTransaction().replace(R.id.content_frame,fragment).addToBackStack("tag").commit();

如果你写addToBackStack(null),它会自己处理,但如果你给一个标签,你应该手动处理它。

作者: Rudi 发布者: 20.10.2013 01:33

3

15329 作者的声誉

不要实现ft.addToBackStack()方法,以便当您按下后退按钮时,您的活动将完成。

proAddAccount = new ProfileAddAccount();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, proAddAccount);
//fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
作者: Muhammad Aamir Ali 发布者: 04.01.2014 03:25

46

2604 作者的声誉

这些都不容易实现,也不会以最佳方式运行。

片段有一个方法调用onDetach来完成这项工作。

@Override
    public void onDetach() {
        super.onDetach();
        PUT YOUR CODE HERE
    }

这将是工作。

作者: Sterling Diaz 发布者: 14.04.2014 04:38

14

2067 作者的声誉

The solution is simple:

1) If you have a base fragment class that all fragments extend, then add this code to it's class, otherwise create such a base fragment class

 /* 
 * called when on back pressed to the current fragment that is returned
 */
 public void onBackPressed()
 {
    // add code in super class when override
 }

2) In your Activity class, override onBackPressed as follows:

private BaseFragment _currentFragment;

@Override
public void onBackPressed()
{
      super.onBackPressed();
     _currentFragment.onBackPressed();
}

3) In Your Fragment class, add your desired code:

 @Override
 public void onBackPressed()
 {
    setUpTitle();
 }
作者: IdoT 发布者: 08.07.2014 10:59

277

3338 作者的声誉

我以这种方式解决onBackPressed了Activity中的覆盖问题。所有FragmentTransactionARE addToBackStack之前提交:

@Override
public void onBackPressed() {

    int count = getSupportFragmentManager().getBackStackEntryCount();

    if (count == 0) {
        super.onBackPressed();
        //additional code
    } else {
        getSupportFragmentManager().popBackStack();
    }

}
作者: Hw.Master 发布者: 22.07.2014 08:04

8

408 作者的声誉

onBackPressed() cause Fragment to be detach from Activity.

根据@Sterling Diaz的回答,我认为他是对的。但有些情况会出错。(例如旋转屏幕)

所以,我认为我们可以发现是否isRemoving()能实现目标。

你可以写onDetach()或者写onDestroyView()。这是工作。

@Override
public void onDetach() {
    super.onDetach();
    if(isRemoving()){
        // onBackPressed()
    }
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    if(isRemoving()){
        // onBackPressed()
    }
}
作者: 林奕忠 发布者: 24.11.2014 11:36

77

939 作者的声誉

这对我有用https//stackoverflow.com/a/27145007/3934111

@Override
public void onResume() {
    super.onResume();

    if(getView() == null){
        return;
    }

    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
                return true;
            }
            return false;
        }
    });
}
作者: Rodrigo Rodrigues 发布者: 20.03.2015 12:53

6

3329 作者的声誉

如果您使用EventBus,它可能是一个更简单的解决方案:

在你的片段中:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    EventBus.getDefault().register(this);
}

@Override
public void onDetach() {
    super.onDetach();
    EventBus.getDefault().unregister(this);
}


// This method will be called when a MessageEvent is posted
public void onEvent(BackPressedMessage type){
    getSupportFragmentManager().popBackStack();
}

在您的Activity类中,您可以定义:

@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
public void onStop() {
    EventBus.getDefault().unregister(this);
    super.onStop();
}

// This method will be called when a MessageEvent is posted
public void onEvent(BackPressedMessage type){
    super.onBackPressed();
}

@Override
public void onBackPressed() {
    EventBus.getDefault().post(new BackPressedMessage(true));
}

BackPressedMessage.java只是一个POJO对象

这是超级干净的,没有接口/实现麻烦。

作者: Akshat 发布者: 01.04.2015 06:54

1

19 作者的声誉

Its just simple if you have An Activity A and you make 3 fragments like B ,C and D.Now if you are in fragment B or C and onBackPressed you want to move on Fragment D every time .Then you have to just Override the onBackPressed() method in main Activity A and also when you jump to any fragment then pass a TAG or name of that fragment by which you recognized that fragment in main Activity A.

I am giving the example of that one by which you can easily understand that....

if (savedInstanceState == null) {

   getSupportFragmentManager().beginTransaction().add(R.id.container, new C_fragment(),"xyz").commit();

}

or if you are moving from fragment B to fragment C..and on back press you want to come on Fragment D...like below

btn.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View view) {

        getActivity().getSupportFragmentManager().beginTransaction().add(R.id.container, new C_frament(), "xyz").commit();
        ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle("Fragment C");
    }
});

Now you have to just override the onBackPressed() method in main activity....like below..

@Override
public void onBackPressed() {
    FragmentManager fragmentManager =getSupportFragmentManager();
    if (((C_fragment) getSupportFragmentManager().findFragmentByTag("xyz")) != null && ((C_fragment) getSupportFragmentManager().findFragmentByTag("xyz")).isVisible()) {
        Fragment fragment = new D_Fragment();
        fragmentManager.beginTransaction().replace(R.id.container, fragment).commit();
        getSupportActionBar().setTitle("D fragment ");
    } else {
        super.onBackPressed();
    }
}
作者: Abhishek Raghuvanshi 发布者: 04.05.2015 07:04

5

2518 作者的声誉

使用onDestroyView()怎么样?

@Override
public void onDestroyView() {
    super.onDestroyView();
}
作者: The Finest Artist 发布者: 23.05.2015 05:15

7

2004 作者的声誉

好吧,我这样做了,它对我有用

简单的界面

FragmentOnBackClickInterface.java

public interface FragmentOnBackClickInterface {
    void onClick();
}

示例实现

MyFragment.java

public class MyFragment extends Fragment implements FragmentOnBackClickInterface {

// other stuff

public void onClick() {
       // what you want to call onBackPressed?
}

然后在活动中覆盖onBackPressed

    @Override
public void onBackPressed() {
    int count = getSupportFragmentManager().getBackStackEntryCount();
    List<Fragment> frags = getSupportFragmentManager().getFragments();
    Fragment lastFrag = getLastNotNull(frags);
    //nothing else in back stack || nothing in back stack is instance of our interface
    if (count == 0 || !(lastFrag instanceof FragmentOnBackClickInterface)) {
        super.onBackPressed();
    } else {
        ((FragmentOnBackClickInterface) lastFrag).onClick();
    }
}

private Fragment getLastNotNull(List<Fragment> list){
    for (int i= list.size()-1;i>=0;i--){
        Fragment frag = list.get(i);
        if (frag != null){
            return frag;
        }
    }
    return null;
}
作者: Błażej 发布者: 04.09.2015 12:31

1

137 作者的声誉

I have used another approach as follows:

  • An Otto event bus to communicate between the Activity and its Fragments
  • A Stack in the Activity containing custom back actions wrapped in a Runnable that the calling fragment defines
  • When onBackPressed is called in the controlling Activity, it pops the most recent custom back action and executes its Runnable. If there's nothing on the Stack, the default super.onBackPressed() is called

The full approach with sample code is included here as an answer to this other SO question.

作者: aoemerson 发布者: 23.11.2015 12:39

1

88 作者的声誉

I know it's too late but I had the same problem last week. None of the answers helped me. I then was playing around with the code and this worked, since I already added the fragments.

在“活动”中,设置一个OnPageChangeListenerViewPager以便您知道用户何时处于第二个活动中。如果他在第二个活动中,请true按如下方式创建一个布尔值:

    mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.pager);
    mViewPager.setAdapter(mSectionsPagerAdapter);
    mViewPager.setCurrentItem(0);
    mViewPager.addOnPageChangeListener(new OnPageChangeListener() {

        @Override
        public void onPageSelected(int position) {
            // TODO Auto-generated method stub
                mSectionsPagerAdapter.instantiateItem(mViewPager, position);
                if(position == 1)
                    inAnalytics = true;
                else if(position == 0)
                    inAnalytics = false;
        }

        @Override
        public void onPageScrolled(int position, float arg1, int arg2) {
            // TODO Auto-generated method stub
        }

        @Override
        public void onPageScrollStateChanged(int arg0) {
            // TODO Auto-generated method stub

        }
    });

现在,每当按下后退按钮时检查布尔值,并将当前项设置为第一个片段:

@Override
public void onBackPressed() {
    if(inAnalytics)
        mViewPager.setCurrentItem(0, true);
    else 
        super.onBackPressed();
}
作者: zeeshan khan 发布者: 31.05.2016 10:16

3

373 作者的声誉

只需按以下步骤操作:

总是在添加片段时

fragmentTransaction.add(R.id.fragment_container, detail_fragment, "Fragment_tag").addToBackStack(null).commit();

然后在主活动中,覆盖 onBackPressed()

if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
    getSupportFragmentManager().popBackStack();
} else {
    finish();
}

要处理应用中的后退按钮,

Fragment f = getActivity().getSupportFragmentManager().findFragmentByTag("Fragment_tag");
if (f instanceof FragmentName) {
    if (f != null) 
        getActivity().getSupportFragmentManager().beginTransaction().remove(f).commit()               
}

而已!

作者: Divya 发布者: 21.07.2016 02:43

1

46 作者的声誉

public class MyActivity extends Activity {

    protected OnBackPressedListener onBackPressedListener;

    public interface OnBackPressedListener {
        void doBack();
    }

    public void setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
        this.onBackPressedListener = onBackPressedListener;
    }

    @Override
    public void onBackPressed() {
        if (onBackPressedListener != null)
            onBackPressedListener.doBack();
        else
            super.onBackPressed();
    } 

    @Override
    protected void onDestroy() {
        onBackPressedListener = null;
        super.onDestroy();
    }
}

在你的片段中添加以下内容,不要忘记实现mainactivity的界面。

public class MyFragment extends Framgent implements MyActivity.OnBackPressedListener {
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
         ((MyActivity) getActivity()).setOnBackPressedListener(this);
    }

@Override
public void doBack() {
    //BackPressed in activity will call this;
}

}
作者: joelvarma 发布者: 02.08.2016 07:06

2

373 作者的声誉

最佳方案,

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;

public class BaseActivity extends AppCompatActivity {
    @Override
    public void onBackPressed() {

        FragmentManager fm = getSupportFragmentManager();
        for (Fragment frag : fm.getFragments()) {
            if (frag == null) {
                super.onBackPressed();
                finish();
                return;
            }
            if (frag.isVisible()) {
                FragmentManager childFm = frag.getChildFragmentManager();
                if (childFm.getFragments() == null) {
                    super.onBackPressed();
                    finish();
                    return;
                }
                if (childFm.getBackStackEntryCount() > 0) {
                    childFm.popBackStack();
                    return;
                }
                else {

                    fm.popBackStack();
                    if (fm.getFragments().size() <= 1) {
                        finish();
                    }
                    return;
                }

            }
        }
    }
}
作者: Shervin Gharib 发布者: 10.08.2016 07:26

3

3547 作者的声誉

简短而甜蜜的回答:

getActivity().onBackPressed();

我的案例的整个场景的解释:

我在MainActivity中有FragmentA,我从FragmentA打开FragmentB(FragmentB是FragmentA的子片段或嵌套片段)

 Fragment duedateFrag = new FragmentB();
 FragmentTransaction ft  = getFragmentManager().beginTransaction();
 ft.replace(R.id.container_body, duedateFrag);
 ft.addToBackStack(null);
 ft.commit();

现在,如果你想从FragmentB转到FragmentA,你可以简单地放入getActivity().onBackPressed(); FragmentB。

作者: Parsania Hardik 发布者: 23.12.2016 09:55

7

409 作者的声誉

您应该像下面一样为项目添加界面;

public interface OnBackPressed {

     void onBackPressed();
}

然后,您应该在片段上实现此接口;

public class SampleFragment extends Fragment implements OnBackPressed {

    @Override
    public void onBackPressed() {
        //on Back Pressed
    }

}

你可以在你的活动onBackPressed事件下触发这个onBackPressed事件,如下所示;

public class MainActivity extends AppCompatActivity {
       @Override
        public void onBackPressed() {
                Fragment currentFragment = getSupportFragmentManager().getFragments().get(getSupportFragmentManager().getBackStackEntryCount() - 1);
                if (currentFragment instanceof OnBackPressed) {  
                    ((OnBackPressed) currentFragment).onBackPressed();
                }
                super.onBackPressed();
        }
}
作者: oyenigun 发布者: 12.01.2017 11:25

8

661 作者的声誉

这只是一个小代码,可以解决这个问题:

 getActivity().onBackPressed();

希望它可以帮助别人:)

作者: Shahid Sarwar 发布者: 19.01.2017 09:02

20

1099 作者的声誉

since this question and some of the answers are over five years old, let me share my solution. This is a follow-up and modernization to the answer from @oyenigun

UPDATE: At the bottom of this article, I added an alternative implementation using an abstract Fragment extension that won't involve the Activity at all, which would be useful for anyone with a more complex fragment hierarchy involving nested fragments that require different back behavior.

I needed to implement this because some of the fragments I use have smaller views that I would like to dismiss with the back button, such as small information views that pop up, etc, but this is good for anyone who needs to override the behavior of the back button inside fragments.

First, define an Interface

public interface Backable {
    boolean onBackPressed();
}

这个接口,我称之为Backable(我是命名约定的坚持者),有一个onBackPressed()必须返回boolean值的方法。我们需要强制执行布尔值,因为我们需要知道按下后退按钮是否“吸收”了后退事件。返回true意味着它具有,并且不需要进一步的操作,否则,false表示仍然必须进行默认的后退操作。此接口应该是它自己的文件(最好是在一个名为的单独包中interfaces)。请记住,将类分成包是很好的做法。

其次,找到顶部片段

我创建了一个返回Fragment后栈中最后一个对象的方法。我使用标签......如果您使用ID,请进行必要的更改。我在实用程序类中有这个静态方法来处理导航状态等...当然,把它放在最适合你的地方。为了启发,我把我的一个叫做NavUtils

public static Fragment getCurrentFragment(Activity activity) {
    FragmentManager fragmentManager = activity.getFragmentManager();
    if (fragmentManager.getBackStackEntryCount() > 0) {
        String lastFragmentName = fragmentManager.getBackStackEntryAt(
                fragmentManager.getBackStackEntryCount() - 1).getName();
        return fragmentManager.findFragmentByTag(lastFragmentName);
    }
    return null;
}

确保后堆栈计数大于0,否则ArrayOutOfBoundsException可能会在运行时抛出。如果它不大于0,则返回null。我们稍后会检查一个空值...

第三,在片段中实施

Backable在需要覆盖后退按钮行为的任何片段中实现接口。添加实现方法。

public class SomeFragment extends Fragment implements 
        FragmentManager.OnBackStackChangedListener, Backable {

...

    @Override
    public boolean onBackPressed() {

        // Logic here...
        if (backButtonShouldNotGoBack) {
            whateverMethodYouNeed();
            return true;
        }
        return false;
    }

}

onBackPressed()覆盖中,放置您需要的任何逻辑。如果您希望后退按钮弹出后退堆栈(默认行为),则返回true,表示您的后退事件已被吸收。否则,返回false。

最后,在你的活动中......

覆盖onBackPressed()方法并将此逻辑添加到它:

@Override
public void onBackPressed() {

    // Get the current fragment using the method from the second step above...
    Fragment currentFragment = NavUtils.getCurrentFragment(this);

    // Determine whether or not this fragment implements Backable
    // Do a null check just to be safe
    if (currentFragment != null && currentFragment instanceof Backable) {

        if (((Backable) currentFragment).onBackPressed()) {
            // If the onBackPressed override in your fragment 
            // did absorb the back event (returned true), return
            return;
        } else {
            // Otherwise, call the super method for the default behavior
            super.onBackPressed();
        }
    }

    // Any other logic needed...
    // call super method to be sure the back button does its thing...
    super.onBackPressed();
}

我们在后面的堆栈中获取当前片段,然后我们进行空检查并确定它是否实现了我们的Backable接口。如果是,请确定事件是否被吸收。如果是这样,我们已经完成onBackPressed()并且可以返回。否则,将其视为正常的背压并调用超级方法。

不参与活动的第二选择

At times, you don't want the Activity to handle this at all, and you need to handle it directly within the fragment. But who says you can't have Fragments with a back press API? Just extend your fragment to a new class.

Create an abstract class that extends Fragment and implements the View.OnKeyListner interface...

import android.app.Fragment;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;

public abstract class BackableFragment extends Fragment implements View.OnKeyListener {

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        view.setFocusableInTouchMode(true);
        view.requestFocus();
        view.setOnKeyListener(this);
    }

    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        if (event.getAction() == KeyEvent.ACTION_UP) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                onBackButtonPressed();
                return true;
            }
        }

        return false;
    }

    public abstract void onBackButtonPressed();
}

As you can see, any fragment that extends BackableFragment will automatically capture back clicks using the View.OnKeyListener interface. Just call the abstract onBackButtonPressed() method from within the implemented onKey() method using the standard logic to discern a back button press. If you need to register key clicks other than the back button, just be sure to call the super method when overriding onKey() in your fragment, otherwise you'll override the behavior in the abstraction.

Simple to use, just extend and implement:

public class FragmentChannels extends BackableFragment {

    ...

    @Override
    public void onBackButtonPressed() {
        if (doTheThingRequiringBackButtonOverride) {
            // do the thing
        } else {
            getActivity().onBackPressed();
        }
    }

    ...
}

Since the onBackButtonPressed() method in the super class is abstract, once you extend you must implement onBackButtonPressed(). It returns void because it just needs to perform an action within the fragment class, and does not need to relay the absorption of the press back to the Activity. Make sure you do call the Activity onBackPressed() method if whatever you're doing with the back button doesn't require handling, otherwise, the back button will be disabled... and you don't want that!

Caveats As you can see, this sets the key listener to the root view of the fragment, and we'll need to focus it. If there are edit texts involved (or any other focus-stealing views) in your fragment that extends this class, (or other inner fragments or views that have the same), you'll need to handle that separately. There's a good article on extending an EditText to lose focus on a back press.

I hope someone finds this useful. Happy coding.

作者: mwieczorek 发布者: 19.01.2017 11:41

3

797 作者的声誉

在活动生命周期中,当我们使用FragmentActivity或AppCompatActivity时,总是android后退按钮处理FragmentManager事务。

要处理后台堆栈,我们不需要处理其后台堆栈计数或标记任何内容,但我们应该在添加或替换片段时保持焦点。请找到以下代码片段来处理后退按钮的情况,

    public void replaceFragment(Fragment fragment) {

        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        if (!(fragment instanceof HomeFragment)) {
            transaction.addToBackStack(null);
        }
        transaction.replace(R.id.activity_menu_fragment_container, fragment).commit();
    }

在这里,我不会为我的home片段添加堆栈,因为它是我的应用程序的主页。如果将addToBackStack添加到HomeFragment,那么应用程序将等待删除活动中的所有片段,然后我们将获得空白屏幕,因此我保持以下条件,

if (!(fragment instanceof HomeFragment)) {
            transaction.addToBackStack(null);
}

现在,您可以看到之前在活动中添加的片段,app将在到达HomeFragment时退出。您还可以查看以下代码段。

@Override
public void onBackPressed() {

    if (mDrawerLayout.isDrawerOpen(Gravity.LEFT)) {
        closeDrawer();
    } else {
        super.onBackPressed();
    }
}
作者: Deva 发布者: 07.05.2017 12:47

6

492 作者的声誉

这是我的解决方案:

MyActivity.java中:

public interface OnBackClickListener {
        boolean onBackClick();
    }

    private OnBackClickListener onBackClickListener;

public void setOnBackClickListener(OnBackClickListener onBackClickListener) {
        this.onBackClickListener = onBackClickListener;
    }

@Override
    public void onBackPressed() {
        if (onBackClickListener != null && onBackClickListener.onBackClick()) {
            return;
        }
        super.onBackPressed();
    }

并在片段中:

((MyActivity) getActivity()).setOnBackClickListener(new MyActivity.OnBackClickListener() {
    @Override
    public boolean onBackClick() {
        if (condition) {
            return false;
        }

        // some codes

        return true;
    }
});
作者: Hamidreza Samadi 发布者: 01.08.2017 06:03

116

1289 作者的声誉

我认为最好的解决方案是

JAVA解决方案

创建简单的界面:

public interface IOnBackPressed {
    /**
     * If you return true the back press will not be taken into account, otherwise the activity will act naturally
     * @return true if your processing has priority if not false
     */
    boolean onBackPressed();
}

在你的活动中

public class MyActivity extends Activity {
    @Override public void onBackPressed() {
    Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.main_container);
       if (!(fragment instanceof IOnBackPressed) || !((IOnBackPressed) fragment).onBackPressed()) {
          super.onBackPressed();
       }
    } ...
}

最后在你的片段中:

public class MyFragment extends Fragment implements IOnBackPressed{
   @Override
   public boolean onBackPressed() {
       if (myCondition) {
            //action not popBackStack
            return true; 
        } else {
            return false;
        }
    }
}

KOTLIN解决方案

1 - 创建界面

interface IOnBackPressed {
    fun onBackPressed(): Boolean
}

2 - 准备您的活动

class MyActivity : AppCompatActivity() {
    override fun onBackPressed() {
        val fragment =
            this.supportFragmentManager.findFragmentById(R.id.main_container)
        (fragment as? IOnBackPressed)?.onBackPressed()?.not()?.let {
            super.onBackPressed()
        }
    }
}

3 - 在目标片段中实施

class MyFragment : Fragment(), IOnBackPressed {
    override fun onBackPressed(): Boolean {
        return if (myCondition) {
            //action not popBackStack
            true
        } else {
            false
        }
    }
}
作者: Maxime Jallu 发布者: 26.09.2017 11:34

4

41 作者的声誉

@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
                replaceFragmentToBackStack(getActivity(), WelcomeFragment.newInstance(bundle), tags);

                return true;
            }

            return false;
        }
    });
}
作者: Gururaj Hosamani 发布者: 21.03.2018 10:20

1

240 作者的声誉

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

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

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

(同样添加我的fragmenManager在活动中声明O现在每次更改片段时,当前片段String将成为当前片段的名称。然后在活动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)
    }

}

我可以确认这种方法适合我。

作者: Haider Malik 发布者: 08.07.2018 02:38

2

366 作者的声誉

只需在onKeyUp()中执行:

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

    if (keyCode == KeyEvent.KEYCODE_BACK) {
        // do something
        return true;  // return true if back handled, false otherwise
    }

    return super.onKeyUp(keyCode, event);
}
作者: b0b 发布者: 13.09.2018 12:42

3

358 作者的声誉

根据AndroidX发布说明androidx.activity 1.0.0-alpha01正在发布和介绍ComponentActivity,现有的新基类FragmentActivityAppCompatActivity。这个版本为我们带来了一个新功能:

您现在可以注册一个OnBackPressedCallbackvia addOnBackPressedCallback来接收onBackPressed()回调,而无需覆盖您活动中的方法。

作者: TonnyL 发布者: 07.11.2018 05:33

2

1201 作者的声誉

您可以在活动中注册片段来处理背压:

interface BackPressRegistrar {
    fun registerHandler(handler: BackPressHandler)
    fun unregisterHandler(handler: BackPressHandler)
}

interface BackPressHandler {
    fun onBackPressed(): Boolean
}

用法:

在片段中:

private val backPressHandler = object : BackPressHandler {
    override fun onBackPressed(): Boolean {
        showClosingWarning()
        return false
    }
}

override fun onResume() {
    super.onResume()
    (activity as? BackPressRegistrar)?.registerHandler(backPressHandler)
}

override fun onStop() {
    (activity as? BackPressRegistrar)?.unregisterHandler(backPressHandler)
    super.onStop()
}

在活动中:

class MainActivity : AppCompatActivity(), BackPressRegistrar {


    private var registeredHandler: BackPressHandler? = null
    override fun registerHandler(handler: BackPressHandler) { registeredHandler = handler }
    override fun unregisterHandler(handler: BackPressHandler) { registeredHandler = null }

    override fun onBackPressed() {
        if (registeredHandler?.onBackPressed() != false) super.onBackPressed()
    }
}
作者: Francis 发布者: 19.04.2019 07:32
32x32