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

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


当前回答

这是我的解决方案:

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

其他回答

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

}

通过处理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
    )
    ...
}

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

 NavHostFragment.findNavController(this@MyFragment).navigateUp();

如果你想要那种功能,你需要在你的活动中覆盖它,然后给你所有的片段添加一个YourBackPressed接口,当你按下后退按钮时,你就会在相关的片段上调用这个接口。

编辑:我想补充我之前的答案。

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

支持库中的LocalBroadcastManager可以帮助解决这个问题,你只需要在onBackPressed中发送广播,并在你的片段中订阅。我认为Messaging是一种更加解耦的实现,可伸缩性更好,所以它是我现在的官方实现建议。只要使用Intent的动作作为你信息的过滤器。发送你新创建的ACTION_BACK_PRESSED,从你的活动发送它,并在相关片段中监听它。

onBackPressed()导致Fragment从Activity中分离。

根据斯特林·迪亚兹的回答,我认为他是对的。但有些情况是错误的。(例如:旋转屏幕)

所以,我认为我们可以检测是否isremoval()来实现目标。

你可以在onDetach()或onDestroyView()上写。它是工作。

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

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

我有同样的问题,我为它创建了一个新的侦听器,并在我的片段中使用。

1 -你的活动应该有一个监听器接口和一个监听器列表

你应该实现添加和删除监听器的方法

你应该重写onBackPressed方法来检查监听器是否使用了背按

public class MainActivity ... {

    /**
     * Back press listener list. Used for notifying fragments when onBackPressed called
     */
    private Stack<BackPressListener> backPressListeners = new Stack<BackPressListener>();


    ...

    /**
     * Adding new listener to back press listener stack
     * @param backPressListener
     */
    public void addBackPressListener(BackPressListener backPressListener) {
        backPressListeners.add(backPressListener);
    }

    /**
     * Removing the listener from back press listener stack
     * @param backPressListener
     */
    public void removeBackPressListener(BackPressListener backPressListener) {
        backPressListeners.remove(backPressListener);
    }


    // Overriding onBackPressed to check that is there any listener using this back press
    @Override
    public void onBackPressed() {

        // checks if is there any back press listeners use this press
        for(BackPressListener backPressListener : backPressListeners) {
            if(backPressListener.onBackPressed()) return;
        }

        // if not returns in the loop, calls super onBackPressed
        super.onBackPressed();
    }

}

4 -你的片段必须实现接口的背压

5 -你需要添加片段作为背按的监听器

如果片段使用这个背压,你应该从onBackPressed返回true

7 -重要-你必须删除片段从列表onDestroy

public class MyFragment extends Fragment implements MainActivity.BackPressListener {


    ...

    @Override
    public void onAttach(Activity activity) {
        super.onCreate(savedInstanceState);

        // adding the fragment to listener list
        ((MainActivity) activity).addBackPressListener(this);
    }

    ...

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

        // removing the fragment from the listener list
        ((MainActivity) getActivity()).removeBackPressListener(this);
    }

    ...

    @Override
    public boolean onBackPressed() {

        // you should check that if this fragment is the currently used fragment or not
        // if this fragment is not used at the moment you should return false
        if(!isThisFragmentVisibleAtTheMoment) return false;

        if (isThisFragmentUsingBackPress) {
            // do what you need to do
            return true;
        }
        return false;
    }
}

有一个Stack来代替ArrayList,以便能够从最新的片段开始。在向后台堆栈添加片段时也可能出现问题。所以你需要检查碎片是否可见,而使用背压。否则,其中一个片段将使用事件,并且最新的片段将不会在背按时关闭。

我希望这能解决所有人的问题。