是否有一种方法,我们可以实现onBackPressed()在Android片段类似的方式,我们实现在Android活动?

因为Fragment的生命周期没有onBackPressed()。在android3.0片段中是否有其他替代方法来覆盖onBackPressed() ?


当前回答

这很简单,如果你有一个活动A,你做了3个片段,如B,C和D。现在,如果你在片段B或C和onBackPressed你想移动到片段D每次。然后你必须重写onBackPressed()方法在主活动A,也当你跳转到任何片段,然后传递一个标签或名称的片段,通过你识别的片段在主活动A。

我举了一个例子,通过这个例子你可以很容易地理解....

if (savedInstanceState == null) {

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

}

或者如果你正从片段B移动到片段C,在背按时你想要进入片段D…像下面的

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");
    }
});

现在你必须重写主活动....中的onBackPressed()方法像下面. .

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

其他回答

 requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
        //your code 
    }

既然这个问题和一些答案已经超过5年了,让我分享一下我的解决方案。这是@oyenigun的回答的后续和现代化

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

我需要实现这一点,因为我使用的一些片段具有较小的视图,我希望通过返回按钮来消除这些视图,例如弹出的小信息视图,等等,但这对于需要覆盖片段内返回按钮行为的任何人都是有益的。

首先,定义一个接口

public interface Backable {
    boolean onBackPressed();
}

This interface, which I call Backable (I'm a stickler for naming conventions), has a single method onBackPressed() that must return a boolean value. We need to enforce a boolean value because we will need to know if the back button press has "absorbed" the back event. Returning true means that it has, and no further action is needed, otherwise, false says that the default back action still must take place. This interface should be it's own file (preferably in a separate package named interfaces). Remember, separating your classes into packages is good practice.

其次,找到顶部的片段

我创建了一个方法,返回后面堆栈中的最后一个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();
}

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

第二种选择是不参与活动

有时,您根本不希望Activity处理它,而需要直接在片段中处理它。但是谁说Fragments不能带有背压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();
}

正如您所看到的,任何扩展BackableFragment的片段都会使用视图自动捕获回点击。OnKeyListener接口。只需在实现的onKey()方法中调用抽象的onBackButtonPressed()方法,使用标准逻辑来识别后退按钮的按下。如果你需要注册按键点击而不是返回按钮,只要确保在你的片段中覆盖onKey()时调用super方法,否则你将覆盖抽象中的行为。

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

public class FragmentChannels extends BackableFragment {

    ...

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

    ...
}

由于超类中的onBackButtonPressed()方法是抽象的,一旦扩展,就必须实现onBackButtonPressed()。它返回void,因为它只需要在fragment类中执行一个动作,而不需要将压力的吸收传递回Activity。如果你对后退按钮所做的事情不需要处理,请确保你调用Activity onBackPressed()方法,否则,后退按钮将被禁用…你不会想要这样的!

警告 如您所见,这将关键侦听器设置为片段的根视图,我们需要集中它。如果在扩展该类的片段(或具有相同内容的其他内部片段或视图)中涉及到编辑文本(或任何其他焦点窃取视图),则需要单独处理。有一篇很好的文章介绍了如何扩展EditText以使其失去对背压的关注。

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

如何使用onDestroyView()?

@Override
public void onDestroyView() {
    super.onDestroyView();
}

这一行代码将从任何片段中进行操作,它将弹出backstack上的当前片段。

getActivity().getSupportFragmentManager().popBackStack();

这个对我很有用: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;
        }
    });
}