Android 4.1.2对话框被调用两次。

14

当我调用显示对话框的功能时,我的应用程序出现了一个问题,它会以某种方式被调用两次。这仅在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);

    }
};

1
有趣的部分是:setStartTime 在哪里被调用了? - zapl
什么被称为“双倍”?所有对话框还是特定的一个? - Andy
setStartTime 被调用了两次,而 setEndTime 被调用了三次。 - Yosi199
兄弟,我也遇到了同样的问题,你是怎么解决的,请说明一下。 - HimanshuR
同样的问题仍然存在于4.4版本。 - Marcos
显示剩余3条评论
8个回答

11

谢谢您的快速回复,马克。我已经添加了调用整个流程的代码。在按钮点击时,您调用setDate()并开始流程。 - Yosi199
@Yosi199:如果我提到的错误对您没有帮助,那么我就没有更多的答案了。然而,在我看来,让用户使用一个单独的“日期和时间活动”来托管“DatePicker”和“TimePicker”,而不是纠缠于两个单独的对话框,似乎会更好。 - CommonsWare
我计划进一步审查这个错误,因为你提供的链接中有一个建议的临时解决方案。否则,我将重新审查我的代码并考虑你的建议。非常感谢你的时间和帮助。 - Yosi199

3

这里提供一个基本解决方案,适用于需要 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();
}

这意味着您已经两次调用了自定义对话框。 - James

2

如果你查看Android源代码,可以发现onTimeSet()在onStop()时被调用。对话框在其onClick()方法中也会调用onTimeSet()。

为了解决这个问题,我不得不重写对话框的dismiss和cancel函数来设置一个布尔值,如果onTimeSet是从按钮点击或dismiss/cancel中调用的,则检查该布尔值。


谢谢,这已经不相关了,但我仍然珍视这些信息以备将来使用。 - Yosi199

1

我也遇到了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():

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

如果该视图及其所有祖先都是可见的,则返回True


0

与其违反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()));

0

我试过了,对我来说很有效,如果你还有问题,尝试使用经典的单例模式。

类似这样 :) 了解更多相关内容。

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();

}

谢谢你的帮助,但那没有帮到我。我已经更新了代码,所以如果你能再看一下就感激不尽了。谢谢。 - Yosi199

0
不要使用内置的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();

-1

我遇到了显示时间选择器两次的问题。我重写了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: 片段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): 中发生 03-14 15:18:47.891: E/AndroidRuntime(29055): 在android.app.FragmentManagerImpl.moveToState(FragmentManager.java:970) - Golan Shay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接