Android 如何将onBackPressedCallback添加到片段?

Android 如何将onBackPressedCallback添加到片段?,android,Android,我已经在几个地方看到了这一点,但由于网上没有例子,我不知道我是否误解了它的含义,所以我不能完全理解如何实现它 我想知道这是否意味着我可以在片段中添加一个回调,在它进入活动之前提取onBackPressed() 在我的片段中,我已经实现了 implements OnBackPressedCallBack @Override public boolean handleOnBackPressed() { Log.d(TAG, "handleOnBackPressed: hello");

我已经在几个地方看到了这一点,但由于网上没有例子,我不知道我是否误解了它的含义,所以我不能完全理解如何实现它

我想知道这是否意味着我可以在片段中添加一个回调,在它进入活动之前提取
onBackPressed()

在我的片段中,我已经实现了

implements OnBackPressedCallBack
@Override
public boolean handleOnBackPressed() {
    Log.d(TAG, "handleOnBackPressed: hello");
    return true;
}
然后实施该方法

implements OnBackPressedCallBack
@Override
public boolean handleOnBackPressed() {
    Log.d(TAG, "handleOnBackPressed: hello");
    return true;
}
但它不是拿起它直接进入主要活动
onBackPressed()

我进一步阅读,发现我的片段需要从片段活动中扩展出来

public class MainExampleFragment extends FragmentActivity implements View.OnClickListener, OnBackPressedCallback {
而不是

appCompatActivity.getSuppportFragmentManager
召唤

FragmentActivity.getSupportFragmentManager 
相反,这会在尝试设置捆绑包时抛出Fragment.newInstance方法并出错

有人知道这方面的信息吗?谢谢

AppCompatActivity扩展碎片Activity扩展 ComponentActivity(androidx.fragment.app.ComponentActivity)扩展了 (androidx.core.app.ComponentActivity)


因此,addOnBackPressedCallback也应该适用于AppCompatActivity

更新的方法

现在很容易将backpress处理程序添加到任何具有


不推荐的方法:不要使用

您不能在片段内直接处理反压的
onBackpressed

相反,您可以通过某种方式将
onBackPressed
事件传递给当前显示的片段

一种基本的方法是创建这样的接口:

interface BackHandler {
    handleBackPressed(): Boolean
}
然后在你的片段上实现如下:

class YourFragment : Fragment(), BackHandler {
    ...
    override handleBackPressed(): Boolean {
        // do Your thing here
    }
    ...
}
在您的活动中,请在按下时执行此操作:

class YourActivity: Activity() {
    ...
    override onBackPressed() {
        val currentFragment = supportFragmentManager.findFragmentById(yourviewid)
        if (currentFragment is BackHandler) {
            (currentFragment as BackHandler).handleBackPressed()
        } else {
            super.onBackPressed()
        }
    }
    ...
}

这只是一种方法。您还可以使用类似于
EventBus
或其他实现的东西。关键的一点是Android没有为片段提供这种开箱即用的功能。

正如@Derek Zhu所指出的,如果您在活动中覆盖onBackPressed,那么片段的onBackPressed回调就不起作用。我发现如果我想在活动中也使用它,那么我也需要在backpressedDispatcher.addCallback中使用
on

活动:

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

                // if you want onBackPressed() to be called as normal afterwards
                if (isEnabled) {
                    isEnabled = false
                    requireActivity().onBackPressed()
                }
            }
        }
)
片段:

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()
                }
            }
        }
)
上面的结果是,将调用back pressed片段,然后调用Activity back pressed。

这就是我所做的

public class MyFragment extends Fragment {

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

        requireActivity().getOnBackPressedDispatcher().addCallback(this, onBackPressedCallback);
    }

    private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(true /* Enabled by default */) {
        @Override
        public void handleOnBackPressed() {
            // Handle the back button event

            if (fieldsModified()) {
                // User made changes on EditText on the Fragment. Confirm exit to avoid loss of data

                AlertDialog.Builder builder= new AlertDialog.Builder(getContext());
                builder.setMessage(msg_confirm_close_form);
                builder.setPositiveButton(R.string.btn_yes, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        closeFragment();
                    }
                });
                builder.setNegativeButton(R.string.btn_no, null);
                builder.show();
            }
            else {
                closeFragment();
            }
        }

        private void closeFragment() {
            // Disable to close fragment
            this.setEnabled(false);
            requireActivity().getOnBackPressedDispatcher().onBackPressed();
        }
    };  
}

您必须在片段中实现回调,以便通过来自您活动的调度程序截获onBackPressed事件。

如果有人不知道我正在更新片段和AppCompacTActivity的OnBackPressedCallBack,并且我在这里嵌套了片段

零碎

public class MessageFragment extends Fragment  {

public MessageFragment() {
    // Required empty public constructor
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    // This callback will only be called when MyFragment is at least Started.
    OnBackPressedCallback callback = new OnBackPressedCallback(true ) {
        @Override
        public void handleOnBackPressed() {
            // Handle the back button event
            FragmentManager fm= getFragmentManager();
            if (fm != null) {
                if (fm.getBackStackEntryCount() > 0) {
                    fm.popBackStack();
                    Log.e( "backpress Frag","back" );

                }

                List<Fragment> fragList = fm.getFragments();
                if (fragList != null && fragList.size() > 0) {
                    for (Fragment frag : fragList) {
                        if (frag == null) {
                            continue;
                        }
                        if (frag.isVisible()) {
                          Log.e( "backpress Frag","Visible" );
                        }
                    }
                }
            }


        }
    };
    requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
    super.onCreate( savedInstanceState );
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View root=inflater.inflate( R.layout.fragment_listning, container, false );

    return root;
}

在back Press上使用事件总线我遇到了完全相同的问题,因为我在activity中重写了OnBackPress(),并且在某些情况下没有调用super方法,因此,fragment没有接收已调度的事件调用请记住,
OnBackPressedCallback
是在最新版本的AppCompat中引入的,该版本是
androidx。AppCompat:AppCompat:1.1.0-rc01
截至今天的Requiresponsibility()。getOnBackPressedDispatcher()。onBackPressed()当我写这一行时,应用程序崩溃了。为什么?这种方法对我很有效@SunilChaudhary此片段附加的活动也扩展了androidx.appcompat.app.AppCompatActivity
-可能要检查您扩展的活动类型,并检查您使用的是androidx appcompat依赖项的最新版本。我正在使用androidx.appcompat:appcompat:1.3.0-alpha02这可能也是一种使用接口的方法。但现在这已经过时了,做一些简单的事情,比如在backButtonPress上回调,要做的工作要多得多。顺便说一句,你在“你不能直接处理片段内部的onBackpressed”这句话中是错误的。您可以以不同的方式添加OnBackPressed。请参阅,这是一种不推荐的方法。。我甚至不记得这里有这个。这个答案是在新方法出现前几年发布的。你可以忽略这一点。我会在有时间的时候更新我的答案。