【问题标题】:Android Dialog reopen after rotate device旋转设备后Android对话框重新打开
【发布时间】:2012-01-11 08:05:28
【问题描述】:

我正在编写一个非常简单的应用程序来打开我的自定义共享对话框。 XML 布局仅包含 1 个按钮:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@color/white"
    android:gravity="center_horizontal">

    <Button android:layout_width="fill_parent" android:layout_height="wrap_content"
        android:layout_margin="20dip"
        android:text="Click here to open Share Dialog"
        android:onClick="onBtnShareClick"/>

</LinearLayout>

在 Activity 上,我创建了一个自定义共享对话框

public class CustomDialog extends Activity {

    private static final int SHOW_DIALOG_SHARE = 1;
    private ArrayAdapter<ShareItem> mShareAdapter;

    @Override
    protected void onCreate(Bundle savedState) {
        super.onCreate(savedState);

        setContentView(R.layout.custom_dialog);

        final ShareItem[] items = {
            //new Item("Menu item", R.drawable.icon_assistance),
            new ShareItem("Banbe", R.drawable.ic_banbe),
            new ShareItem("Facebook", R.drawable.ic_facebook),
            new ShareItem("Twitter", R.drawable.ic_twitter),
            new ShareItem("Gmail", R.drawable.ic_gmail),
            new ShareItem("Other sharing options...", 0)
        };

        mShareAdapter = new ArrayAdapter<ShareItem>(
        this,
        android.R.layout.select_dialog_item,
        android.R.id.text1,
        items){
            public View getView(int position, View convertView, ViewGroup parent) {
                //User super class to create the View
                View v = super.getView(position, convertView, parent);
                TextView tv = (TextView)v.findViewById(android.R.id.text1);

                //Put the image on the TextView
                tv.setCompoundDrawablesWithIntrinsicBounds(items[position].icon, 0, 0, 0);

                //Add margin between image and text (support various screen densities)
                int dp5 = (int) (5 * getResources().getDisplayMetrics().density + 0.5f);
                tv.setCompoundDrawablePadding(dp5);

                return v;
            }
        };
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
            case SHOW_DIALOG_SHARE:
            return new AlertDialog.Builder(this)
            .setIcon(R.drawable.icon)
            .setTitle(R.string.app_name)
            .setAdapter(mShareAdapter, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int item) {
                    Toast.makeText(CustomDialog.this, "Click on item " + item, Toast.LENGTH_SHORT).show();
                }
            })
            .show();
        }
        return null;
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        // TODO Auto-generated method stub
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onRestoreInstanceState(savedInstanceState);
    }

    public void onBtnShareClick(View v) {
        showDialog(SHOW_DIALOG_SHARE);
    }

    protected class ShareItem {
        public final String text;
        public final int icon;
        public ShareItem(String text, Integer icon) {
            this.text = text;
            this.icon = icon;
        }
        @Override
        public String toString() {
            return text;
        }
    }

}

当点击按钮时,我的分享对话框将会打开。都很好。

现在,我将设备旋转到纵向模式,单击按钮打开对话框。之后,按返回关闭共享对话框。 将设备旋转到横向模式。虽然我没有点击按钮,但突然重新打开了共享对话框。

当我尝试使用本机共享对话框时,我没有看到这个错误。也许是自定义共享对话框的原因?

谁能告诉我这里出了什么问题?

【问题讨论】:

    标签: android dialog rotation screen-rotation


    【解决方案1】:

    您好,您必须在应用程序清单文件中添加屏幕方向支持。

     <activity android:name=".TestApp"
         android:label="@string/app_name"   android:configChanges="orientation">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    

    并且还覆盖了下面的方法,

      public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
      }
    

    【讨论】:

    • 它有效。伟大的。但是我们是否有另一种方法来修复它而不是添加 configChanges="orientation"?因为我不想在这里添加configChanges。
    【解决方案2】:

    使用 create() 方法而不是 show() 方法

    new AlertDialog.Builder(this).create()

    【讨论】:

      【解决方案3】:

      尝试使用从DialogFragment扩展的自己的类

      例如:

          public class QuestionDialogFragment extends DialogFragment
          {
              public final static String BF_TITLE = "QuestionDialogFragment.BF_TITLE";
              public final static String BF_QUESTION = "QuestionDialogFragment.BF_QUESTION";
      
              private Callback mCallback;
      
              public static void init(FragmentManager fragmentManager, String title, String question, Callback callback)
              {
                  Bundle bundle = new Bundle();
                  bundle.putString(BF_TITLE, title);
                  bundle.putString(BF_QUESTION, question);
      
                  QuestionDialogFragment dialog = new QuestionDialogFragment();
                  dialog.setCallbackListener(callback);
                  dialog.setArguments(bundle);
                  dialog.show(fragmentManager, null);
              }
      
              @Override
              public void onCreate(Bundle savedInstanceState)
              {
                  super.onCreate(savedInstanceState);
      
                  setCancelable(false);
              }
      
              @Override
              public Dialog onCreateDialog(Bundle savedInstanceState)
              {
                  Bundle bundle = getArguments();
      
                  String title = null;
                  String question = null;
      
                  if (bundle != null)
                  {
                      if (bundle.containsKey(BF_TITLE))
                      {
                          title = bundle.getString(BF_TITLE);
                      }
                      if (bundle.containsKey(BF_QUESTION))
                      {
                          question = bundle.getString(BF_QUESTION);
                      }
                  }
      
                  AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
                  alertDialogBuilder.setTitle(title);
                  alertDialogBuilder.setMessage(question);
                  //null should be your on click listener
                  alertDialogBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener()
                  {
                      @Override
                      public void onClick(DialogInterface dialog, int which)
                      {
                          mCallback.success();
                          dialog.dismiss();
                      }
                  });
                  alertDialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener()
                  {
      
                      @Override
                      public void onClick(DialogInterface dialog, int which)
                      {
                          mCallback.cancel();
                          dialog.cancel();
                      }
                  });
      
                  return alertDialogBuilder.create();
              }
      
              public void setCallbackListener(Callback callback)
              {
                  this.mCallback = callback;
              }
      
              public static interface Callback
              {
                  void success();
                  void cancel();
              }
      }
      

      并在代码中的任何地方使用它:

                  QuestionDialogFragment.init(
                      getFragmentManager(),
                      "Some title",
                      "Some question?",
                      new QuestionDialogFragment.Callback()
                      {
                          @Override
                          public void success()
                          {
                              // @TODO if user choice YES;
                          }
      
                          @Override
                          public void cancel()
                          {
                              // @TODO if user choice CANCEL;
                          }
                      });
      

      如果您想创建自己的视图而不是标准对话框窗口:

        Dialog onCreateDialog(Bundle savedInstanceState) 
      

      使用

        View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
      

      例如:

      需要创建值/布局/your_fragment_layout.xml

          <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
                       android:layout_width="match_parent"
                       android:layout_height="match_parent"
                       android:id="@+id/kom_purchase_dialog_root_view">
      
              <TextView
                  android:id="@+id/kom_purchase_dialog_message_text"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:layout_gravity="center"
                  android:text="some text"/>
      
              <LinearLayout
                  android:layout_gravity="bottom"
                  android:orientation="horizontal"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content">
      
                  <Button
                      android:id="@+id/kom_purchase_dialog_negative_button"
                      android:layout_alignParentBottom="true"
                      android:layout_width="0dp"
                      android:layout_weight="1"
                      android:layout_height="wrap_content"
                      android:text="Cancel"/>
      
                  <Button
                      android:id="@+id/kom_purchase_dialog_positive_button"
                      android:layout_toRightOf="@+id/kom_purchase_dialog_negative_button"
                      android:layout_alignParentBottom="true"
                      android:layout_width="0dp"
                      android:layout_weight="1"
                      android:layout_height="wrap_content"
                      android:text="Ok"/>
              </LinearLayout>
          </FrameLayout>
      

      对于这个布局,将自己的类更改为:

      public class QuestionDialogFragment2 extends DialogFragment
      {
      
          public final static String BF_TITLE = "QuestionDialogFragment.BF_TITLE";
          public final static String BF_QUESTION = "QuestionDialogFragment.BF_QUESTION";
      
          private Callback mCallback;
      
          public static void init(FragmentManager fragmentManager, String title, String question, Callback callback)
          {
              Bundle bundle = new Bundle();
              bundle.putString(BF_TITLE, title);
              bundle.putString(BF_QUESTION, question);
      
              QuestionDialogFragment2 dialog = new QuestionDialogFragment2();
              dialog.setCallbackListener(callback);
              dialog.setArguments(bundle);
              dialog.show(fragmentManager, null);
          }
      
          @Override
          public void onCreate(Bundle savedInstanceState)
          {
              super.onCreate(savedInstanceState);
              setCancelable(false);
          }
      
          @Override
          public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
          {
              Bundle bundle = getArguments();
      
              String title = null;
              String question = null;
      
              if (bundle != null)
              {
                  if (bundle.containsKey(BF_TITLE))
                  {
                      title = bundle.getString(BF_TITLE);
                  }
                  if (bundle.containsKey(BF_QUESTION))
                  {
                      question = bundle.getString(BF_QUESTION);
                  }
              }
              View view = super.onCreateView(inflater, container, savedInstanceState);
              if (view == null)
              {
                  view = inflater.inflate(R.layout.your_fragment_layout, null, false);
                  view.setTag(new Holder(view));
              }
              Holder holder = (Holder) view.getTag();
              holder.messageTextView.setText(question);
              holder.positiveButton.setOnClickListener(new View.OnClickListener()
              {
                  @Override
                  public void onClick(View v)
                  {
                      mCallback.success();
                  }
              });
              holder.negativeButton.setOnClickListener(new View.OnClickListener()
              {
                  @Override
                  public void onClick(View v)
                  {
                      mCallback.cancel();
                  }
              });
              return view;
          }
      
          public void setCallbackListener(Callback callback)
          {
              this.mCallback = callback;
          }
      
          public static interface Callback
          {
              void success();
              void cancel();
          }
      
          private final class Holder
          {
              public TextView messageTextView;
              public Button positiveButton;
              public Button negativeButton;
      
              private Holder(View view)
              {
                  messageTextView = (TextView) view.findViewById(R.id.question_dialogfragment_message_textview);
                  positiveButton = (Button) view.findViewById(R.id.question_dialogfragment_positive_button);
                  negativeButton = (Button) view.findViewById(R.id.question_dialogfragment_negative_button);
              }
          }
      }
      

      和同样的用法:

                  QuestionDialogFragment2.init(
                      getFragmentManager(),
                      "Some title",
                      "Some question?",
                      new QuestionDialogFragment2.Callback()
                      {
                          @Override
                          public void success()
                          {
                              // @TODO if user choice YES;
                          }
      
                          @Override
                          public void cancel()
                          {
                              // @TODO if user choice CANCEL;
                          }
                      });
      

      这两种方法都可以在 void onSaveInstanceState(Bundle outState) 中工作,并在轮换后保存状态。我认为它比使用简单对话框更好且通用。

      【讨论】:

        【解决方案4】:

        使用 Dialog 或 AlertDialog 无关紧要。为了避免在旋转屏幕时关闭对话框,请使用以下代码:

        dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
        

        【讨论】:

        • 一段时间后,我意识到这个选项没有意义。使用DialogFragment 会更有效率。因为您可以轻松自定义它,并且可以在旋转屏幕期间保存状态。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-03
        相关资源
        最近更新 更多