Java 当对话框打开时,如何处理屏幕方向的更改?

Java 当对话框打开时,如何处理屏幕方向的更改?,java,android,Java,Android,我有一个android应用程序,它已经在处理方向的更改,即清单中有一个android:configChanges=“orientation”,活动中有一个onConfigurationChange()处理程序,可以切换到适当的布局并进行准备。我有一个横向/纵向版本的布局 我面临的问题是,活动有一个对话框,当用户旋转设备方向时,该对话框可能会打开。我还有一个横向/纵向版本的对话框 我是否应该立即更改对话框的布局,或者锁定活动的旋转,直到用户取消对话框 后一种锁定应用程序的选项对我很有吸引力,因为它

我有一个android应用程序,它已经在处理方向的更改,即清单中有一个
android:configChanges=“orientation”
,活动中有一个
onConfigurationChange()
处理程序,可以切换到适当的布局并进行准备。我有一个横向/纵向版本的布局

我面临的问题是,活动有一个对话框,当用户旋转设备方向时,该对话框可能会打开。我还有一个横向/纵向版本的对话框

我是否应该立即更改对话框的布局,或者锁定活动的旋转,直到用户取消对话框

后一种锁定应用程序的选项对我很有吸引力,因为它省去了在对话框中执行任何特殊操作的麻烦。我假设我可能会在打开对话框时禁用方向,例如

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
然后当它解散的时候

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
这样做明智吗?如果屏幕方向在锁定时确实发生了变化,那么在解锁时是否会立即感觉到方向的变化


有其他选择吗?

我建议您的对话框应该覆盖
onSaveInstanceState()
onRestoreInstanceState(Bundle)
以将其状态保存到Bundle中

然后在活动中重写这些方法,检查对话框是否显示,如果显示,则调用对话框的方法以保存和恢复其状态

如果您是从片段显示此对话框,则需要覆盖ActivityCreated(Bundle)上的
而不是
上的RestoreInstanceState


有关源代码示例,请参阅Android附带的内置时钟应用程序,其中以这种方式处理时间选择器对话框。

如果您自己处理方向更改,则以下是一种方法

我不会说这是一个优雅的解决方案,但它是有效的:

通过使用静态变量activeInstance,并重写onStart()以设置activeInstance=this,重写onCancel()以设置activeInstance=null,可以跟踪对话框类本身内部是否有活动实例

为AnyCurrentInstance()提供一个静态方法updateConfigurationForAnyCurrentInstance(),该方法测试该activeInstance变量,如果非null,则调用方法activeInstance.reInitializeDialog(),该方法将被编写为包含setContentView()调用以及连接对话框控件处理程序的代码(按钮onClick处理程序等)-这是通常出现在onCreate()中的代码。接下来,您将(从对话框对象中的成员变量)将所有显示的数据恢复到这些控件中。因此,例如,如果您有一个要查看的项目列表,并且用户在方向更改之前正在查看该列表中的项目3,则在从对话框资源重新加载控件并重新连接控件处理程序之后,您将在UpdateConfiguration for AnyCurrentInstance()的末尾重新显示相同的项目3

然后,您可以从onCreate()调用相同的reInitializeDialog()方法,就在super.onCreate()之后,并在调用之后放置特定于onCreate()的初始化代码(例如,设置用户可以选择的项目列表,如上所述)

这将导致为对话框的新方向加载相应的资源(纵向或横向)(前提是您定义了两个具有相同名称的资源,一个在布局文件夹中,另一个在布局区域文件夹中,与往常一样)

下面是一个名为YourDialog的类中的一些代码:

ArrayList<String> listOfPossibleChoices = null;
int currentUserChoice = 0;

static private YourDialog activeInstance = null;

@Override
protected void onStart() {
  super.onStart();
  activeInstance = this;
}

@Override
public void cancel() {
  super.cancel();
  activeInstance = null;
}


static public void updateConfigurationForAnyCurrentInstance() {
    if(activeInstance != null) {
        activeInstance.reInitializeDialog();
        displayCurrentUserChoice();
    }
}

private void reInitializeDialog() {
  setContentView(R.layout.your_dialog);
  btnClose = (Button) findViewById(R.id.btnClose);
  btnClose.setOnClickListener(this);
  btnNextChoice = (Button) findViewById(R.id.btnNextChoice);
  btnNextChoice.setOnClickListener(this);
  btnPriorChoice = (Button) findViewById(R.id.btnPriorChoice);
  btnPriorChoice.setOnClickListener(this);
  tvCurrentChoice = (TextView) findViewById(R.id.tvCurrentChoice);
}

private void displayCurrentUserChoice() {
  tvCurrentChoice.setText(listOfPossibleChoices.get(currentUserChoice));
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    reInitializeDialog();
    listOfPossibleChoices = new ArrayList<String>();
    listOfPossibleChoices.add("One");
    listOfPossibleChoices.add("Two");
    listOfPossibleChoices.add("Three");
    currentUserChoice = 0;
    displayCurrentUserChoice();
}

@Override
public void onClick(View v) {
    int viewID = v.getId();

    if(viewID == R.id.btnNextChoice) {
      if(currentUserChoice < (listOfPossibleChoices.size() - 1))
        currentUserChoice++;
        displayCurrentUserChoice();
      }
    }
    else if(viewID == R.id.btnPriorChoice) {
      if(currentUserChoice > 0) {
        currentUserChoice--;
        displayCurrentUserChoice();
      }
    }
    Etc.
ArrayList listOfPossibleChoices=null;
int currentUserChoice=0;
静态私有YourDialog activeInstance=null;
@凌驾
受保护的void onStart(){
super.onStart();
activeInstance=this;
}
@凌驾
公开作废取消(){
super.cancel();
activeInstance=null;
}
AnyCurrentInstance()的静态公共void UpdateConfiguration{
if(activeInstance!=null){
activeInstance.reInitializeDialog();
displayCurrentUserChoice();
}
}
私有void重新初始化对话框(){
setContentView(R.layout.your_对话框);
btnClose=(按钮)findViewById(R.id.btnClose);
btnClose.setOnClickListener(此);
btnNextChoice=(按钮)findViewById(R.id.btnNextChoice);
btnNextChoice.setOnClickListener(此);
btnPriorChoice=(按钮)findViewById(R.id.btnPriorChoice);
btnPriorChoice.setOnClickListener(此);
tvCurrentChoice=(TextView)findViewById(R.id.tvCurrentChoice);
}
私有void displayCurrentUserChoice(){
tvCurrentChoice.setText(可能的选项列表.get(currentUserChoice));
}
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
重新初始化对话框();
listOfPossibleChoices=new ArrayList();
可能的选择列表。添加(“一”);
可能的选择列表。添加(“两个”);
可能的选择列表。添加(“三”);
currentUserChoice=0;
displayCurrentUserChoice();
}
@凌驾
公共void onClick(视图v){
int viewID=v.getId();
if(viewID==R.id.btnNextChoice){
if(currentUserChoice<(可能选项列表.size()-1))
currentUserChoice++;
displayCurrentUserChoice();
}
}
else if(viewID==R.id.BTNPROORCHOICE){
如果(currentUserChoice>0){
当前用户选择--;
displayCurrentUserChoice();
}
}
等

然后,在主活动的onConfigurationChanged()方法中,只要在onConfigurationChanged()时调用Dialog.UpdateConfiguration for AnyCurrentInstance()由操作系统调用。

我建议不要关闭屏幕旋转,而不是关闭对话框的配置更改。您可以使用以下两种方法之一:

第一种方法是在onSaveInstanceState(outState)方法中使用一个标志变量,并还原对话框onCreate(bundle)方法:

在这个e
Class MyClass extends Activity {
    Boolean isShowingDialog = false;
    AlertDialog myDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        if(savedInstanceState!=null){
            isShowingDialog = savedInstanceState.getBoolean("IS_SHOWING_DIALOG", false);
            if(isShowingDialog){
                createDialog();
            }
        }

    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        outState.putBoolean("IS_SHOWING_DIALOG", isShowingDialog);
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onPause() {
        if(myDialog!=null && myDialog.isShowing()) {
            myDialog.dismiss();
        }
    }

    private void createDialog() {
        AlertDialog.Builder dialog_builder = new AlertDialog.Builder(this);
        dialog_builder.setTitle("Some Title"):
        ... more dialog settings ...

        myDialog = dialog_builder.create();
        myDialog.show();
        isShowingDialog = true;
    }

    private void hideDialog(){
        myDialog.dismiss();
        isShowingDialog = false;
    }
}