【问题标题】:How to have an Activity notify a Fragment that the back button has been pressed如何让活动通知片段已按下后退按钮
【发布时间】:2015-07-03 21:57:25
【问题描述】:

我已经研究了几天,还没有找到可行的解决方案。有很多可用的信息,但由于我对 Android 缺乏经验,我无法获得任何可行的建议。

我有一个 Activity,上面有 3 个 Fragment 堆栈,所有这些都使用 FragmentManager Transactions 呈现并添加到后台堆栈。当第三个 Fragment 处于活动状态时,我需要拦截 onBackPressed() 方法并在 Fragment 被销毁之前执行一些额外的操作。

我尝试使用回调和接口在活动中捕获 onBackPressed() 并将其发送到第三个片段,但没有成功。

对于 Activity 的 onBackPressed() 方法,在堆栈中深入观察 Fragment 的正确方法是什么。

如果不清楚,请告诉我。

感谢您的帮助。

【问题讨论】:

  • onBackPressed() 有必要吗?或者你只是想在片段被破坏时做点什么?
  • 也许覆盖onPause会更好?
  • 堆栈上的最后 2 个片段需要同时弹出,或者一个紧随其后,我通过调用 popBackStack() 2 次使用内置的取消按钮完成此操作(可能不是最好的方法......)所以我需要做同样的 onBackPressed() 否则只有 1 个 Fragment 被破坏。
  • 您阅读网页developer.android.com/training/implementing-navigation/… 了吗?我认为此时,您应该发布相关代码以供我们查看任何可能的问题。

标签: android android-fragments interface callback onbackpressed


【解决方案1】:

未编译和测试,但这列出了基本方法:

public interface BackButonListener {
    boolean OnBackButtonPressed();
} 

public interface BackButtonWatchable {
     void addBackButtonListener(BackButtonListener listener);
     void removeBackButtonListener(BackButtonListener listener);
}

public class MyActivity extends Activity implements BackButtonWatchable {
...
    private static ArrayList<BackButtonListener> backButtonListeners
        = new ArrayList<BackButtonListener>();
    @Override 
    public void addBackButtonListener(BackButtonListener listener) {
          backButtonListeners.add(listener);
    }
    @Override
    public void removeBackButtonListener(BackButtonListener listener) {
          backButtonListeners.remove(listener);
    }
...
    @Override 
    public void onBackButtonPressed() 
    {
        boolean supressBackButton = false;
        for (BackButtonListener listener: backButtonListeners)
        {
             if (!listener.OnBackButtonPressed()) {
                  suppressBackButton = true;
             }
        }
        if (!suppressBackButton) {
            super.onBackButtonPressed();
        }
    }
}


public class MyFragment extends Fragment implements BackButtonListerer {
     @Override 
     public void onResume()
     {
          ((BackButtonWatchable)getActivity()).addBackButtonListener(this);
     }
     @Override 
     public void onPause()     {
          ((BackButtonWatchable)getActivity()).removeBackButtonListener(this);
     }
}

【讨论】:

  • 明确一点,我们处理的是一个Activity和一个Fragment,都是Activity中的接口,还是一个在Activity中,一个在Fragment中?
  • 我提议在顶层声明接口。不属于活动。如果您只想在一个活动中使用您的片段,您可以将 Fragment.getActivity() 的值强制转换为您的顶级类,而根本不使用接口。
  • ... 可能正确的模式是在片段中声明接口。在这种情况下,应将 BackButtonWatchable 重命名为 MyFragment.MyFragmentListener。 (片段的优秀模式),然后包含片段的任何活动都必须实现 MyFragment.MyFragmentListener。很想将 MyFragment.getActivity() 转换为您的顶级类,但如果您确实想在另一个活动中重新托管片段,事情就会变得困难。 MyFragmentListener 接口很有帮助,因为它迫使您保持片段和活动之间的联系精简和平均。
【解决方案2】:

克里特界面

public interface OnBackPressedListener {
   void onBackPressed();
}

并在活动中创建字段

private OnBackPressedListener mListener;

你的 onBackPressed() 应该看起来像

if (mListener != null) {
   mListener.onBackPressed();
} else { /* do your acitivty usual stuff */ }

创建片段时,您在活动中将此片段注册为 mListener,并且不要在 onDestroy 中将其设置为 null。

【讨论】:

    【解决方案3】:

    这是回答我问题的帖子。对于 Android 新手来说,这告诉了我一切都需要去哪里。

    https://stackoverflow.com/a/30865486/2640458

    需要从其活动中查看 onBackPress() 方法的 Fragment:

    public class RatingFragment extends Fragment implements ContentActivity.OnBackPressedListener  {
    
    @Override
    public void doBack() {
        getFragmentManager().popBackStack();
    }
    

    上面Fragment中对监听器的非常重要的订阅:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_rating, container, false);
    
        ((ContentActivity)getActivity()).setOnBackPressedListener(this);
    }
    

    需要向上述Fragment发送onBackPress()方法的Activity:

    public class ContentActivity 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();
    }
    }
    

    【讨论】:

    • 看起来不错,恭喜!您的答案与其他发布的答案相似。您可以通过点赞其他帖子来表达您的感激之情。
    猜你喜欢
    • 1970-01-01
    • 2011-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-13
    • 1970-01-01
    • 2011-12-18
    • 2018-01-02
    相关资源
    最近更新 更多