如何在Fragments中实现onBackPressed()?

And*_*era 422 android android-fragments onbackpressed

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

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

Hw.*_*ter 295

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

@Override
public void onBackPressed() {

    int count = getSupportFragmentManager().getBackStackEntryCount();

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

}
Run Code Online (Sandbox Code Playgroud)

  • 但是您不能在此代码中使用片段类中的变量、类和函数 (4认同)
  • count == 1将允许在单击后退按钮上关闭第一个片段.但否则最好的解决方案 (3认同)
  • 如果您使用的是支持 v7 库并且您的 Activity 从 [FragmentActivity](http://developer.android.com/reference/android/support/v4/app/FragmentActivity.html)(或子类,例如 AppCompatActivity ) 默认情况下会发生这种情况。参见 [FragmentActivity#onBackPressed](http://developer.android.com/reference/android/support/v4/app/FragmentActivity.html#onBackPressed()) (2认同)
  • @Prabs如果你正在使用支持v4片段,那么请确保你使用的是getSupportFragmentManager().getBackStackEntryCount(); (2认同)

Max*_*llu 129

我认为最好的解决方案是

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();
}
Run Code Online (Sandbox Code Playgroud)

在你的活动中

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();
       }
    } ...
}
Run Code Online (Sandbox Code Playgroud)

最后在你的片段中:

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

KOTLIN解决方案

1 - 创建界面

interface IOnBackPressed {
    fun onBackPressed(): Boolean
}
Run Code Online (Sandbox Code Playgroud)

2 - 准备您的活动

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

3 - 在目标片段中实施

class MyFragment : Fragment(), IOnBackPressed {
    override fun onBackPressed(): Boolean {
        return if (myCondition) {
            //action not popBackStack
            true
        } else {
            false
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 不应该是`.onBackPressed()?. takeIf {!it} ?. let {...}`吗?`.not()`仅返回反数。 (4认同)
  • 什么是“R.id.main_container”?那是 FragmentPager 的 ID 吗? (3认同)
  • 如果您不想为活动中的所有片段实现它。```覆盖 fun onBackPressed() { valfragment = this.supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as?NavHostFragment val currentFragment =fragment?.childFragmentManager?.fragments?.get(0) as?FragmentOnBackPressListener if (currentFragment != null) { currentFragment.onBackPressed().takeIf { !it }?.let { super.onBackPressed() } } else { super.onBackPressed() } }``` (3认同)
  • `val fragment = this.supportFragmentManager.findFragmentById(R.id.flContainer) as? NavHostFragment val currentFragment = fragment?.childFragmentManager?.fragments?.get(0) as? IOnBackPressed currentFragment?.onBackPressed()?.takeIf { !it }?.let{ super.onBackPressed() }` 这适用于使用 Kotlin 和 NavigationController 的人 (2认同)

dea*_*ish 92

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

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

  1. 创建类接口 OnBackPressedListener

    public interface OnBackPressedListener {
        public void doBack();
    }
    
    Run Code Online (Sandbox Code Playgroud)
  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);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 从现在开始,我们将处理我们的代码BaseActivity及其片段

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

    protected OnBackPressedListener onBackPressedListener;
    
    Run Code Online (Sandbox Code Playgroud)
  5. create方法来设置监听器 BaseActivity

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

    @Override
    public void onBackPressed() {
        if (onBackPressedListener != null)
            onBackPressedListener.doBack();
        else
            super.onBackPressed();
    
    Run Code Online (Sandbox Code Playgroud)
  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;
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

  • 您可以自定义单击侦听器而不是新的baseBackPressedListener并以匿名方式调用它来设置自己的行为,如下所示:`((BaseActivity)activity).setOnBackPressedListener(new OnBackpressedListener(){public void doBack(){//...your stuff这里}});` (2认同)

Rod*_*ues 80

这对我有用: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;
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案的问题是getView()只返回主视图(而不是子视图,如果它们获得焦点).因此,如果您有一个EditText并输入一些文本然后按"后退"一次隐藏键盘,第二次按"返回"是从"EditText"(一个视图本身)启动,这个方法似乎没有抓住"然后按"按钮按下(因为它只捕捉主视图).据我了解,您可以捕获"EditText"以及任何其他视图上的按键事件,但如果您有一个"复杂"的形式,那么这不是那么干净和可维护. (18认同)
  • 工作完美!但是,您还必须通过再写一个IF条件来处理默认操作.因为,如果它是Expanded,我正在降低我的slideUpPanel.所以,我首先必须标记检查是否(面板已启动)然后...... (2认同)
  • 当Layout具有EditText时,这不起作用 (2认同)

HaM*_*ReD 64

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

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

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

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

  • 非常漂亮的想法!一些额外的想法:+重要的是通过广告来自活动>片段(而不是相反的方式)来实现这种逻辑.OnBackPressed仅在活动级别可用,因此在此处捕获事件并将其广播到所有"侦听"片段是关键.+使用EventBus(如Square的Otto)可以实现像这样简单的案例! (4认同)
  • 我还没有使用过Square的EventBus,但我将在未来的产品中使用.我认为这是一个更好的纯java解决方案,如果你可以敲掉你的架构部分的Android,那就更好了. (2认同)

Ste*_*iaz 47

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

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

@Override
    public void onDetach() {
        super.onDetach();
        PUT YOUR CODE HERE
    }
Run Code Online (Sandbox Code Playgroud)

这将是工作.

  • 但是这里的问题是你不知道片段是由于背压还是由于某些其他动作而被分离,这导致用户去了其他一些活动或片段. (14认同)
  • 当片段不再附加到其活动时,将调用onDetach().这是在onDestroy()之后调用的.虽然按下后退按钮可以获得此代码,但是当您从片段更改为片段时,也会获得此代码.你可以做一些漂亮的事情让这项工作尽管...... (5认同)
  • 不要忘记添加`isRemoving()`,如http://stackoverflow.com/a/27103891/2914140中所述. (2认同)

Amj*_*reh 40

谷歌已经发布了一个新的API来处理onBackPressedFragment

activity?.onBackPressedDispatcher?.addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {

            }
        })
Run Code Online (Sandbox Code Playgroud)

  • 如何在这种方法中调用 super.onBackPressed ? (5认同)
  • 这是这些天来的真正答案。 (2认同)

Rud*_*udi 25

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

fragmentManager.beginTransaction().replace(R.id.content_frame,fragment).addToBackStack("tag").commit();
Run Code Online (Sandbox Code Playgroud)

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


B-G*_*teR 24

使用导航组件,你可以做这样的

爪哇

public class MyFragment extends Fragment {

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // This callback will only be called when MyFragment is at least Started.
    OnBackPressedCallback callback = new OnBackPressedCallback(true /* enabled by default */) {
        @Override
        public void handleOnBackPressed() {
            // Handle the back button event
        }
    });
    requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);

    // The callback can be enabled or disabled here or in handleOnBackPressed()
}
...
}
Run Code Online (Sandbox Code Playgroud)

科特林

class MyFragment : Fragment() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // This callback will only be called when MyFragment is at least Started.
    val callback = requireActivity().onBackPressedDispatcher.addCallback(this) {
        // Handle the back button event
    }

    // The callback can be enabled or disabled here or in the lambda
}
...
}
Run Code Online (Sandbox Code Playgroud)


mwi*_*rek 20

由于这个问题和一些答案已经超过五年了,让我分享一下我的解决方案.这是对@oyenigun的回答的后续和现代化

更新: 在本文的底部,我添加了一个使用抽象Fragment扩展的替代实现,它根本不涉及Activity,这对于任何具有更复杂的片段层次结构的人来说都是有用的,这些片段层次结构涉及需要不同反向行为的嵌套片段.

我需要实现这个,因为我使用的一些片段具有较小的视图,我想用后退按钮解除,例如弹出的小信息视图等,但这对于需要覆盖行为的任何人都有好处.片段内的后退按钮.

首先,定义一个接口

public interface Backable {
    boolean onBackPressed();
}
Run Code Online (Sandbox Code Playgroud)

这个接口,我称之为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;
}
Run Code Online (Sandbox Code Playgroud)

确保后堆栈计数大于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;
    }

}
Run Code Online (Sandbox Code Playgroud)

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();
}
Run Code Online (Sandbox Code Playgroud)

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

不参与活动的第二选择

有时,您根本不希望Activity处理此问题,您需要在片段中直接处理它.但是谁说你不能拥有带有反压API的片段?只需将您的片段扩展到一个新类.

创建一个扩展Fragment并实现View.OnKeyListner接口的抽象类......

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();
}
Run Code Online (Sandbox Code Playgroud)

如您所见,任何扩展的片段BackableFragment都会使用该View.OnKeyListener界面自动捕获返回的点击次数.只需使用标准逻辑onBackButtonPressed()从已实现的onKey()方法中调用抽象方法,即可识别后退按钮按下.如果你需要注册后退按钮以外的关键点击,只需确保super在覆盖onKey()片段时调用方法,否则你将覆盖抽象中的行为.

简单易用,只需扩展和实现:

public class FragmentChannels extends BackableFragment {

    ...

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

    ...
}
Run Code Online (Sandbox Code Playgroud)

由于onBackButtonPressed()超类中的方法是抽象的,所以一旦扩展就必须实现onBackButtonPressed().它返回void是因为它只需要在片段类中执行一个动作,并且不需要将按下的吸收传递回Activity.如果您使用后退按钮执行的操作不需要处理,请确保调用Activity onBackPressed()方法,否则后退按钮将被禁用...而您不希望这样!

注意事项 正如您所看到的,这将关键监听器设置为片段的根视图,我们需要关注它.如果片段中涉及的编辑文本(或任何其他焦点窃取视图)扩展了此类(或其他具有相同内部片段或视图的内部片段或视图),则需要单独处理.有一篇关于扩展EditText的文章,以便不再关注背压.

我希望有人觉得这很有用.快乐的编码.

  • 只是一个旁注。`instanceof` 隐式执行 null 检查,因此无需在此之前显式检查 null (2认同)

San*_*shi 17

新的更好的方法:遵循 a 中的一段代码Fragment将帮助您捕获后退事件。

爪哇

@Override
public void onAttach(@NonNull Context context) {
    super.onAttach(context);

    OnBackPressedCallback callback = new OnBackPressedCallback(true) {
        @Override
        public void handleOnBackPressed() {
            Toast.makeText(mContext, "back pressed", Toast.LENGTH_SHORT).show();
            
            // And when you want to go back based on your condition
            if (yourCondition) {
                this.setEnabled(false);
                requireActivity().onBackPressed();
            }
        }
    };

    requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
}
Run Code Online (Sandbox Code Playgroud)

科特林

activity?.onBackPressedDispatcher?.addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) {
    override fun handleOnBackPressed() {

    }
})
Run Code Online (Sandbox Code Playgroud)


tan*_*993 16

在 kotlin 中,这要简单得多。

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            //
        }
    })
}
Run Code Online (Sandbox Code Playgroud)

  • 这是 kotlin 开发人员的最佳解决方案之一。谢啦。 (3认同)

Ido*_*doT 15

解决方案很简单:

1)如果你有一个所有片段都扩展的基础片段类,那么将这个代码添加到它的类中,否则创建这样一个基础片段类

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

2)在Activity类中,重写onBackPressed,如下所示:

private BaseFragment _currentFragment;

@Override
public void onBackPressed()
{
      super.onBackPressed();
     _currentFragment.onBackPressed();
}
Run Code Online (Sandbox Code Playgroud)

3)在Fragment类中,添加所需的代码:

 @Override
 public void onBackPressed()
 {
    setUpTitle();
 }
Run Code Online (Sandbox Code Playgroud)


林奕忠*_*林奕忠 9

onBackPressed() 导致Fragment与Activity分离.

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

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

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

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

@Override
public void onDestroyView() {
    super.onDestroyView();
    if(isRemoving()){
        // onBackPressed()
    }
}
Run Code Online (Sandbox Code Playgroud)


Bła*_*żej 8

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

简单的界面

FragmentOnBackClickInterface.java

public interface FragmentOnBackClickInterface {
    void onClick();
}
Run Code Online (Sandbox Code Playgroud)

示例实现

MyFragment.java

public class MyFragment extends Fragment implements FragmentOnBackClickInterface {

// other stuff

public void onClick() {
       // what you want to call onBackPressed?
}
Run Code Online (Sandbox Code Playgroud)

然后在活动中覆盖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;
}
Run Code Online (Sandbox Code Playgroud)


小智 8

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

public interface OnBackPressed {

     void onBackPressed();
}
Run Code Online (Sandbox Code Playgroud)

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

public class SampleFragment extends Fragment implements OnBackPressed {

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

}
Run Code Online (Sandbox Code Playgroud)

你可以在你的活动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();
        }
}
Run Code Online (Sandbox Code Playgroud)


小智 8

在片段的 onCreate 方法中添加以下内容:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    OnBackPressedCallback callback = new OnBackPressedCallback(true) {
        @Override
        public void handleOnBackPressed() {
            //Handle the back pressed
        }
    };
    requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
}
Run Code Online (Sandbox Code Playgroud)

  • 添加此 myFragment 后压可以工作,但现在活动后压没有 (3认同)

Aks*_*hat 7

如果您使用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();
}
Run Code Online (Sandbox Code Playgroud)

在您的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));
}
Run Code Online (Sandbox Code Playgroud)

BackPressedMessage.java只是一个POJO对象

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


小智 7

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

在您的片段中添加以下内容,不要忘记实现 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;
}

}
Run Code Online (Sandbox Code Playgroud)


Sha*_*war 7

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

 getActivity().onBackPressed();
Run Code Online (Sandbox Code Playgroud)

希望它可以帮助别人:)

  • 他要求覆盖行为,而不是简单地调用activity方法. (3认同)
  • 我仔细阅读了,谢谢.当他询问如何覆盖时,您的解决方案只是将onBackPressed方法转发回Activity. (2认同)

Ham*_*adi 6

这是我的解决方案:

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();
    }
Run Code Online (Sandbox Code Playgroud)

并在片段中:

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

        // some codes

        return true;
    }
});
Run Code Online (Sandbox Code Playgroud)


Fra*_*cis 6

更新:OnBackPressedDispatcher应该使用。

指南如何使用可在developer.android.com/guide/navigation/navigation-custom-back获取


您可以在活动中注册片段来处理后按:

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

interface BackPressHandler {
    fun onBackPressed(): Boolean
}
Run Code Online (Sandbox Code Playgroud)

用法:

在片段中:

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()
}
Run Code Online (Sandbox Code Playgroud)

活动中:

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()
    }
}
Run Code Online (Sandbox Code Playgroud)


aar*_*ino 6

如果您使用的是androidx.appcompat:appcompat:1.1.0或更高版本,则可以将OnBackPressedCallback片段添加到片段,如下所示

requireActivity()
    .onBackPressedDispatcher
    .addCallback(this, object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            Log.d(TAG, "Fragment back pressed invoked")
            // Do custom work here    

            // if you want onBackPressed() to be called as normal afterwards
            if (isEnabled) {
                isEnabled = false
                requireActivity().onBackPressed()
            }
        }
    }
)
Run Code Online (Sandbox Code Playgroud)

参见https://developer.android.com/guide/navigation/navigation-custom-back

  • 如果您使用的是`androidx-core-ktx`,您可以使用`requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) { /* 按下后退时执行的代码 */ }` (8认同)
  • 我就是这个意思!!这么多古老的答案让我“你在开玩笑吧?” 现在谷歌推荐片段而不是活动。 (3认同)
  • 将 addCallback 方法的第一个参数的“this”更改为“viewLifecycleOwner”,就完成了!这样您就不必担心取消注册回调,因为回调将附加到活动生命周期中。 (3认同)
  • 需要注意的是,应像本示例中那样添加“LifecycleOwner”参数。如果没有它,如果按下后退按钮,之后启动的任何片段都将调用“handleBackPressed()”。 (2认同)

Kha*_*dov 6

您可以onBackPressedDispatcher像这样使用父活动:

val backpress = requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, true) {
            // here dispatcher works for any action when back pressed
}
Run Code Online (Sandbox Code Playgroud)

您还可以随时从片段启用/禁用后按按钮,如下所示:

backpress.isEnabled = true/false
Run Code Online (Sandbox Code Playgroud)


小智 6

 requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
        //your code 
    }
Run Code Online (Sandbox Code Playgroud)


小智 5

@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;
        }
    });
}
Run Code Online (Sandbox Code Playgroud)


Ton*_*nyL 5

根据AndroidX 发行说明androidx.activity 1.0.0-alpha01发布并引入了ComponentActivity现有的新基类FragmentActivityAppCompatActivity。这个版本给我们带来了一个新功能:

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


Kri*_* CN 5

现在,通过片段内的回调处理 onBackPressed 来提供自定义后退导航变得更加容易。

class MyFragment : Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val onBackPressedCallback = object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                if (true == conditionForCustomAction) {
                    myCustomActionHere()
                } else  NavHostFragment.findNavController(this@MyFragment).navigateUp();    
        }
    }
    requireActivity().onBackPressedDispatcher.addCallback(
        this, onBackPressedCallback
    )
    ...
}
Run Code Online (Sandbox Code Playgroud)

如果您想要基于某些条件的默认后退操作,您可以使用:

 NavHostFragment.findNavController(this@MyFragment).navigateUp();
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

412754 次

最近记录:

5 年,11 月 前