【问题标题】:Android 4.1.2 dialogs are called twiceAndroid 4.1.2 对话框被调用两次
【发布时间】:2012-12-06 17:18:41
【问题描述】:

当我调用显示对话框时,我的应用程序出现了这个问题,它以某种方式被调用了两次。这只发生在 android 4.1 及更高版本上。低版本运行良好,所以我不认为这是任何代码问题。

您以前听说过\遇到过这个问题吗?

这里是代码:

Button edit = (Button) ad.findViewById(R.id.editBtn);
        edit.setTypeface(roboto);
        edit.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                setDate();
                ad.dismiss();
            }
        });

        ad.show();

        ad.setOnDismissListener(new OnDismissListener() {

            @Override
            public void onDismiss(DialogInterface dialog) {
                shiftsActivity.setPressed(true);

            }
        });
    }

    public void setDate() {
    // Initialize and open the set date dialog
    DatePickerDialog setDateDialog = new DatePickerDialog(Shifts.this,
            datePickerListener, dateAndTime.get(Calendar.YEAR),
            dateAndTime.get(Calendar.MONTH),
            dateAndTime.get(Calendar.DAY_OF_MONTH));

    setDateDialog.setTitle("Set Date");
    setDateDialog.show();

}

public void setStartTime() {

    TimePickerDialog setStartTimeDialog = new TimePickerDialog(Shifts.this,
            startTimePicker, dateAndTime.get(Calendar.HOUR),
            dateAndTime.get(Calendar.MINUTE), true);

    setStartTimeDialog.setTitle("Started At:");
    setStartTimeDialog.show();

}

public void setEndTime() {

    TimePickerDialog setEndTimeDialog = new TimePickerDialog(Shifts.this,
            setEndTime, dateAndTime.get(Calendar.HOUR),
            dateAndTime.get(Calendar.MINUTE), true);
    setEndTimeDialog.setTitle("Ended:");
    setEndTimeDialog.show();
}

TimePickerDialog.OnTimeSetListener startTimePicker = new TimePickerDialog.OnTimeSetListener() {

    @Override
    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
        startIntHours = hourOfDay;
        startIntMinutes = minute;
        editStartTime = String.format("%02d", hourOfDay) + ":"
                + String.format("%02d", minute);
        setEndTime();

    }
};

TimePickerDialog.OnTimeSetListener setEndTime = new TimePickerDialog.OnTimeSetListener() {

    @Override
    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {

        finishIntHours = hourOfDay;
        finsihIntMinutes = minute;

        if (finishIntHours < startIntHours) {
            finishIntHours = finishIntHours + Utility.HOURS_TIME_UNIT;
        }

        if (finsihIntMinutes < startIntMinutes) {
            finsihIntMinutes = finsihIntMinutes + Utility.MINUTES_TIME_UNIT;
        }

        totalHours = finishIntHours - startIntHours;
        totalMinutes = finsihIntMinutes - startIntMinutes;
        Log.i("TotalHours in time picker", "" + totalHours);
        Log.i("Totalminute in time picker", "" + totalMinutes);

        editEndTime = String.format("%02d", hourOfDay) + ":"
                + String.format("%02d", minute);

        replace(Shifts.view, Shifts.position);

    }
};

【问题讨论】:

  • 有趣的部分是:setStartTime 在哪里调用
  • 在 4.0.3 上运行正常
  • 没错,问题从4.1及以上开始。
  • 我更新了代码以包含对 setStartTime 的调用,以便更好地理解流程
  • 究竟什么叫了两次?所有的对话框,还是一个特定的?

标签: android dialog


【解决方案1】:

根据您的代码,这些方法都不会被调用,因为您从不使用TimePickerDialogs

话虽如此,有一个与DatePickerDialog/TimePickerDialog 的行为相关的已知问题可能相关:http://code.google.com/p/android/issues/detail?id=34833

【讨论】:

  • 感谢您的快速回复马克,我已经添加了调用整个流程的代码。单击调用 setDate() 的按钮,流程开始。
  • @Yosi199:如果我引用的错误对您没有帮助,那么我没有进一步的答案。但是,在我看来,用户最好有一个DateAndTimeActivity,托管一个DatePicker 和一个TimePicker,而不是用两个单独的对话框大惊小怪。
  • 我计划进一步审查该错误,因为您提供的链接中有建议的临时解决方案。否则,我将重新审视我的代码并考虑您的建议。非常感谢您抽出宝贵的时间,您确实帮助了我。
【解决方案2】:

对于需要 TimeChooserDialog 的人来说,这是一个基本的解决方案,它不会两次调用侦听器,带有基本选项

public static AlertDialog getTimePickerDialog(Context context, final OnTimeSetListener listener, int hour, int minute, boolean is24HFormat) {
    AlertDialog.Builder builder = new AlertDialog.Builder(context);
    final TimePicker timePicker = new TimePicker(context);
    timePicker.setIs24HourView(is24HFormat);
    timePicker.setCurrentHour(hour);
    timePicker.setCurrentMinute(minute);
    builder.setView(timePicker);
    builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
        @Override
        public void onClick(DialogInterface arg0, int arg1) {
            if(null != listener) {
                listener.onTimeSet(timePicker, timePicker.getCurrentHour(), timePicker.getCurrentMinute());
            }
        }
    });
    builder.setNegativeButton(android.R.string.cancel, null);
    return builder.create();
}

【讨论】:

  • 这调用了你创建的自定义对话框两次。
【解决方案3】:

如果您查看 android 源代码,似乎 onTimeSet() 在 onStop() 期间被调用。该对话框还在其 onClick() 方法中调用 onTimeSet()。

为了解决这个问题,我必须重写对话框的关闭和取消函数来设置一个布尔值,我检查了是否从按钮单击或关闭/取消调用 onTimeSet

【讨论】:

  • 谢谢,这不再相关,但我仍然重视这些信息以备将来使用
【解决方案4】:

TimePicker 也出现了同样的问题。我解决了这个问题。

new TimePickerDialog.OnTimeSetListener() {
    @Override
    public void onTimeSet(TimePicker view, int setHour, int setMinute) {  
        if (view.isShown()) {
            // This method will return true only once
        }
    }
};

iShown():

返回此视图及其所有祖先的可见性

返回 如果此视图及其所有祖先都是可见的,则为真

【讨论】:

    【解决方案5】:

    我试试看,如果你仍然有问题,我可以试试classic singleton

    类似这样的东西 :) 阅读更多相关信息。

    public void setStartTime() {
    
        TimePickerDialog setStartTimeDialog = NULL;
        if(setStartTimeDialog == null) {
           new TimePickerDialog(Shifts.this, startTimePicker, dateAndTime.get(Calendar.HOUR),dateAndTime.get(Calendar.MINUTE), true);
    
        setStartTimeDialog.setTitle("Started At:");
           }
        setStartTimeDialog.show();
    
    }
    

    【讨论】:

    • 感谢您的帮助,但这对我没有帮助。我已经更新了代码,所以如果您能再看一下,我将不胜感激。谢谢
    【解决方案6】:

    不要使用内置的 TimePickerDialog 或 DatePickerDialog。而是创建一个自定义对话框,如此处所示。它简单易用,而且很有效!

            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
            final TimePicker timePicker = new TimePicker(getActivity());
            builder.setTitle("Set Time");
            builder.setView(timePicker);
            builder.setNegativeButton("Cancel", new OnClickListener() {
    
                @Override
                public void onClick(DialogInterface dialog, int which) {
    
                }
            });
            builder.setPositiveButton("OK"), new OnClickListener() {
    
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    int minute = timePicker.getCurrentMinute();
                    int hourOfDay = timePicker.getCurrentHour();
                }
            });
            builder.show();
    

    【讨论】:

      【解决方案7】:

      我没有违反 super.onClose() 或制作自定义对话框,而是通过包装真实侦听器并扩展 TimePickerDialog 来解决它,该对话框启用和禁用从包装器到真实侦听器的转发。这不是替代品,但它已经足够整洁了。

      public class TimePickerDialogCustom extends TimePickerDialog
      {
          protected TimePickerDialogOnTimeSetListenerWrapper listenerWrapper;
      
          public TimePickerDialogCustom(Context context,
                  TimePickerDialogOnTimeSetListenerWrapper listener,
                  int hourOfDay, int minute, boolean is24HourView)
          {
              super(context, listener, hourOfDay, minute, is24HourView);
              listenerWrapper = listener;
          }
          @Override
          protected void onStop()
          {
              if (listenerWrapper != null)
                  listenerWrapper.enabled = false;
              super.onStop();
              if (listenerWrapper != null)
                  listenerWrapper.enabled = true;
          }
          public static final class TimePickerDialogOnTimeSetListenerWrapper implements TimePickerDialog.OnTimeSetListener
          {
              private boolean enabled = true;
              private final TimePickerDialog.OnTimeSetListener delegate;
      
              public TimePickerDialogOnTimeSetListenerWrapper(TimePickerDialog.OnTimeSetListener delegate)
              {
                  this.delegate = delegate;
              }
              @Override
              public void onTimeSet(TimePicker view, int hourOfDay, int minute)
              {
                  if (enabled)
                  {
                      this.delegate.onTimeSet(view, hourOfDay, minute);
                  }
              }
          }
      }
      

      然后使用它:

          TimePickerDialogCustom.TimePickerDialogOnTimeSetListenerWrapper listenerWrapper =
                  new TimePickerDialogCustom.TimePickerDialogOnTimeSetListenerWrapper(realListener);
          // Create a new instance of DatePickerDialog and return it
          TimePickerDialogCustom dialog = new TimePickerDialogCustom(
                  getActivity(),
                  listenerWrapper,
                  hourOfDay,
                  minute,
                  DateFormat.is24HourFormat(getActivity()));
      

      【讨论】:

        【解决方案8】:

        我遇到了两次显示时间选择器的问题。我已经覆盖了 TimePickerDialog 的 onStop() 并解决了这个问题。此外,您不应在覆盖的 onStop() 中调用 super.onStop()。

        @Override
        public void onStop() {
            //super.onStop();
            Log.d(TAG, "onStop of starttime TimePickerDialog.");
        }
        

        【讨论】:

        • 03-14 15:18:47.891: E/AndroidRuntime(29055): android.app.SuperNotCalledException: Fragment DatePickerFragment{425cf2a0} 没有调用到 super.onStop() 03-14 15: 18:47.891: E/AndroidRuntime(29055): 在 android.app.Fragment.performStop(Fragment.java:1961) 03-14 15:18:47.891: E/AndroidRuntime(29055): 在 android.app.FragmentManagerImpl.moveToState (FragmentManager.java:970)
        猜你喜欢
        • 2011-03-10
        • 1970-01-01
        • 1970-01-01
        • 2017-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多