【问题标题】:The best way to handle back behavior on DialogFragment?处理 DialogFragment 上的后退行为的最佳方法?
【发布时间】:2014-01-04 23:05:04
【问题描述】:

所以我有一个 DialogFragment 显示区域选择列表。一旦用户点击该区域,列表重新获取数据以显示街道选择列表。此时,我想允许用户按硬件后退按钮返回到区域选择。这可能吗?我尝试覆盖下面的一些方法,但我只能点击事件但不能阻止它的发生。

@Override
public void onCancel(DialogInterface dialog) {
    if(isDismissable()){
        super.onCancel(dialog);
    }else {
        Log.d(TAG, "Don't dismiss cancel this dialog!");
    }
}

@Override
public void dismissAllowingStateLoss() {
    if(isDismissable()){
        super.dismissAllowingStateLoss();
    }else {
        Log.d(TAG, "Don't dismiss this dialog!");
    }
}

@Override
public void dismiss() {
    if(isDismissable()){
        super.dismiss();
    }else {
        Log.d(TAG, "Don't dismiss this dialog!");
    }
}

dismiss() 在用户按下返回按钮时被调用,但即使我不调用super.dismiss(),对话框也会被关闭。

有没有办法做到这一点?我还研究了 Google+ 应用如何在 DialogFragment 中显示 ActionBar 以提供 HomeAsUp,但我找不到任何相关信息。

【问题讨论】:

    标签: android android-dialogfragment


    【解决方案1】:

    我看到了两种解决方案:

    最简单的:将区域选择和街道选择列表作为单独的常用片段,并将它们都放在单独的活动中,并通过简单的主题将此活动作为对话框: <activity android:theme="@android:style/Theme.Dialog" />excludeFromRecents="true" 在最近使用的应用程序中没有这个。 首先加载区域选择,然后通过addToBackStack(null) 添加街道选择,这样您将在下面有AreaSelection 片段。

    如果您出于任何原因不想有单独的活动,您可以从对话框片段中添加一个对话框侦听器,其实现者(活动)将打开AreaFragment。对您的代码有基本的了解后,这个简单的项目应该可以做到:

    所有者活动:

    import com.example.adip.fragments.AreaSelectionFragment;
    import com.example.adip.fragments.StreetSelectionFragment;
    import com.example.adip.fragments.AreaSelectionFragment.AreaSelectionListener;
    import com.example.adip.fragments.StreetSelectionFragment.StreetSelectionListener;
    
    import android.os.Bundle;
    import android.support.v4.app.DialogFragment;
    import android.support.v4.app.FragmentActivity;
    import android.view.View;
    import android.view.View.OnClickListener;
    
    public class DialogsActivity extends FragmentActivity implements OnClickListener,
            AreaSelectionListener, StreetSelectionListener {
    
        private static final String AREA_TAG = "AREA_TAG";
    
        private static final String STREETS_TAG = "STREETS_TAG";
    
        @Override
        protected void onCreate(Bundle savedInstance) {
            super.onCreate(savedInstance);
            setContentView(R.layout.area_selections);
            findViewById(R.id.btnStuff).setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            showArea();
        }
    
        private void showArea() {
            DialogFragment df = new AreaSelectionFragment();
            df.show(getSupportFragmentManager(), AREA_TAG);
        }
    
        @Override
        public void onStreetsUserCanceled() {
            showArea();
        }
    
        @Override
        public void showStreets() {
            DialogFragment df = new StreetSelectionFragment();
            df.show(getSupportFragmentManager(), STREETS_TAG);
        }
    
    }
    

    AreaSelectionFragment(根据您的需要扩展):

    import android.app.Activity;
    import android.app.AlertDialog;
    import android.app.Dialog;
    import android.content.DialogInterface;
    import android.content.DialogInterface.OnClickListener;
    import android.os.Bundle;
    import android.support.v4.app.DialogFragment;
    
    public class AreaSelectionFragment extends DialogFragment {
        public static interface AreaSelectionListener {
            void showStreets();
        }
    
        private AreaSelectionListener areaSelectionListener;
    
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            if (activity instanceof AreaSelectionListener) {
                areaSelectionListener = (AreaSelectionListener) activity;
            } else {
                throw new ClassCastException("Parent Activity must implement AreaSelectionListener");
            }
        }
    
        @Override
        public void onDetach() {
            super.onDetach();
            areaSelectionListener = null;
        }
    
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            return new AlertDialog.Builder(getActivity()).setTitle("Area Selection")
                    .setPositiveButton("OK", new OnClickListener() {
    
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            areaSelectionListener.showStreets();
                        }
                    }).setNegativeButton("Cancel", null).create();
        }
    }
    

    还有StreetSelectionFragment(再次:根据您的需要扩展它):

    import android.app.Activity;
    import android.app.AlertDialog;
    import android.app.Dialog;
    import android.content.DialogInterface;
    import android.content.DialogInterface.OnClickListener;
    import android.os.Bundle;
    import android.support.v4.app.DialogFragment;
    
    public class StreetSelectionFragment extends DialogFragment {
        public static interface StreetSelectionListener {
            void onStreetsUserCanceled();
        }
    
        private StreetSelectionListener selectionListener;
    
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            if (activity instanceof StreetSelectionListener) {
                selectionListener = (StreetSelectionListener) activity;
            } else {
                throw new ClassCastException("Parent activity must implement StreetSelectionListener");
            }
        }
    
        @Override
        public void onDetach() {
            selectionListener = null;
            super.onDetach();
        }
    
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            Dialog dialog = new AlertDialog.Builder(getActivity()).setTitle("Street Selection")
                    .setPositiveButton("OK", null).setNegativeButton("Cancel", new OnClickListener() {
    
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            selectionListener.onStreetsUserCanceled();
                        }
                    }).create();
            return dialog;
        }
    
        @Override
        public void onCancel(DialogInterface dialog) {
            super.onCancel(dialog);
            selectionListener.onStreetsUserCanceled();
        }
    }
    

    【讨论】:

    • 两种解决方案都不好... 1. 如果您在嵌套片段中工作,则不起作用,2. 将启动一个新对话框,因此当内容变化。
    【解决方案2】:

    在 DialogFragment 上处理返回行为的最佳方法?

    处理DialogFragment 上的后退行为的最佳方法是不要乱用它并保持原样,在此过程中重新考虑您当前的方法。如果我在应用程序中看到一个对话框并且我正在回击,我希望 将对话框弹出 出屏幕并且不在对话框的页面之间导航(我希望我没有误读您的问题)。

    有没有办法做到这一点?

    在您的DialogFragment 中,您可以使用自定义Dialog(我假设您只是使用onCreateDialog() 回调来返回带有列表的Dialog),您可以覆盖onKeyDown() 回调处理被按下的背部:

    public class CustomDialog extends Dialog {
    
        protected CustomDialog(Context context) {
            super(context);
        }
    
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
                // the back key was pressed so do something?
                return true;
            }
            return super.onKeyDown(keyCode, event);
        }
    
    }
    

    我还研究了 Google+ 应用如何在 DialogFragment 提供 HomeAsUp 但我找不到任何信息。

    您总是可以让Activity 看起来像Dialog

    【讨论】:

    • 谢谢。我使用 DialogFragment,因为我可能将它用作平板电脑版本中的 Fragment。我现在正在 DialogFragment 顶部制作一个人造 ActionBar。
    【解决方案3】:
    The best way is to override onBackPressed() in the dialog , you created in onCreateDialog().
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new Dialog(getActivity(), getTheme()){
            @Override
            public void onBackPressed() {
                //do your stuff
            }
        };
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多