【问题标题】:Prevent user from selecting past time - TimePickerDialog防止用户选择过去的时间 - TimePickerDialog
【发布时间】:2015-09-25 05:22:34
【问题描述】:

重要编辑:我做了一些搜索,似乎 OnTimeChangedListener 在 Android 5.0 (API 21) 中没有触发。 Gustavo 下面的答案适用于 API 20 或更低版本,以及我测试过的 API 22。 (Source)

我想阻止用户输入当前时间之前的时间。我使用Date 提供的before 方法检查有效时间。如何防止对话框在此有效性检查中接受无效时间?

我省略了初始化所选时间的多余代码(作为Date)。

final Calendar mcurrentTime = Calendar.getInstance();
final int hour = mcurrentTime.get(Calendar.HOUR_OF_DAY);
final int minute = mcurrentTime.get(Calendar.MINUTE);
final TimePickerDialog mTimePicker;
mTimePicker = new TimePickerDialog(MainActivity.this, new TimePickerDialog.OnTimeSetListener() {
    @Override
    public void onTimeSet(TimePicker timePicker, int selectedHour, int selectedMinute) {

        //PSEUDO: Date selectedDateTime init here

        if (selectedDateTime.before(mcurrentTime.getTime())) {
            // prevent user from selecting time
        }
    }
}, hour, minute, true);//true = 24 hour time
mTimePicker.setTitle("Select Time");
mTimePicker.show(); 

【问题讨论】:

  • 查看answer这个帖子。
  • 我相信我已经这样做了,但没有成功:gist.github.com/mcguile/7cfc107bba3772228d26.
  • 检查 onTimeChanged 方法的值。将其与您的价值观进行比较。
  • 你能用你的代码添加答案吗?遵循您的代码会简单得多。成功后将接受答案。
  • 检查您在选择器上的时间,您可以在里面滚动值,但顶部的时间不会改变。检查例如 mTimePicker.setMin(9, 00)mTimePicker.setMax(18, 00)

标签: android date datetime android-dialog timepicker


【解决方案1】:

Here原帖。

按照答案,您应该添加 TimePickerDialog 类。

public class RangeTimePickerDialog extends TimePickerDialog {

private int minHour = -1;
private int minMinute = -1;

private int maxHour = 25;
private int maxMinute = 25;

private int currentHour = 0;
private int currentMinute = 0;

private Calendar calendar = Calendar.getInstance();
private DateFormat dateFormat;


public RangeTimePickerDialog(Context context, OnTimeSetListener callBack, int hourOfDay, int minute, boolean is24HourView) {
    super(context, callBack, hourOfDay, minute, is24HourView);
    currentHour = hourOfDay;
    currentMinute = minute;
    dateFormat = DateFormat.getTimeInstance(DateFormat.SHORT);

    try {
        Class<?> superclass = getClass().getSuperclass();
        Field mTimePickerField = superclass.getDeclaredField("mTimePicker");
        mTimePickerField.setAccessible(true);
        TimePicker mTimePicker = (TimePicker) mTimePickerField.get(this);
        mTimePicker.setOnTimeChangedListener(this);
    } catch (NoSuchFieldException e) {
    } catch (IllegalArgumentException e) {
    } catch (IllegalAccessException e) {
    }
}

public void setMin(int hour, int minute) {
    minHour = hour;
    minMinute = minute;
}

public void setMax(int hour, int minute) {
    maxHour = hour;
    maxMinute = minute;
}

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

    Log.d("DADADADA", "onTimeChanged");

    boolean validTime = true;
    if (hourOfDay < minHour || (hourOfDay == minHour && minute < minMinute)) {
        validTime = false;
    }

    if (hourOfDay > maxHour || (hourOfDay == maxHour && minute > maxMinute)) {
        validTime = false;
    }

    if (validTime) {
        currentHour = hourOfDay;
        currentMinute = minute;
    }

    updateTime(currentHour, currentMinute);
    updateDialogTitle(view, currentHour, currentMinute);
}

private void updateDialogTitle(TimePicker timePicker, int hourOfDay, int minute) {
    calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
    calendar.set(Calendar.MINUTE, minute);
    String title = dateFormat.format(calendar.getTime());
    setTitle(title);
}
}

之后,将 TimePickerDialog 替换为 RangeTimePickerDialog

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final Calendar mcurrentTime = Calendar.getInstance();
    final int hour = mcurrentTime.get(Calendar.HOUR_OF_DAY);
    final int minute = mcurrentTime.get(Calendar.MINUTE);
    final RangeTimePickerDialog mTimePicker;
    mTimePicker = new RangeTimePickerDialog(MainActivity.this, new TimePickerDialog.OnTimeSetListener() {
        @Override
        public void onTimeSet(TimePicker timePicker, int selectedHour, int selectedMinute) {

            Log.d("TAG", "inside OnTimeSetListener");

        }
    }, hour, minute, true);//true = 24 hour time
    mTimePicker.setTitle("Select Time");
    mTimePicker.setMin(hour, minute);
    mTimePicker.show();
}
}

在那之后,检查你的对话框,时间没有超过限制,我已经用 setMax()setMin() 进行了检查,并且只设置了一个。

【讨论】:

  • 这是我拥有的确切代码。标题不会更改为显示您建议的选择时间,也不会限制您可以选择的时间。有些东西不见了。
  • 清理您的项目并再次运行它。我的代码正在手机上运行。 Android SDK 14 或更高版本。
  • 对不起,我已经这样做了,没有任何改变。我的代码与您的完全相同。我不明白为什么它对你有用,而不对我有用。它允许我选择任何时间,并且时间更改为所选时间。我在 API 21 上。
  • 好答案。除了使用反射。普通的界面会好很多。仍然 +1
  • 请给出更好的解决方案
【解决方案2】:

方法onTimeSet() 在对话框关闭时调用一次,在单击完成按钮时调用两次。

我会在第二次调用时在该方法中验证。忽略第一个。如果无效,则显示错误(可能是 toast)并再次显示对话框

细化

两个onTimeSet 调用将是相同的时间。现在,我没有参考,但我相信 one 调用是在显示对话框时(时间设置与否)然后被取消。 就是这样,但不是取消,而是当用户点击“完成”时。

我说忽略第一个的原因是可以设置时间,并决定取消。在这种情况下,不要接受onTimeSet()。如果这对您来说无关紧要,则无需担心。

【讨论】:

  • 我不知道它 onTimeSet() 被调用了两次。能否详细说明如何区分第一次调用和第二次调用?
  • 你知道如何忽略第一个电话吗?或者甚至识别它是第一次还是第二次调用?
  • 多种方式。这就是您必须将注意力集中在可行的算法上的地方。我可能会使用和 int。显示对话框时将其设置为 0。然后,当您收到 dateSet 时,检查 int。如果为 0,则添加一个/忽略日期。如果为 1,则处理日期。 (然后是安全的。再次将 int 设置回 0)。类似的东西。
  • 啊,好吧,我早就想到了。我只是假设你的意思是它有定义的方法。
猜你喜欢
  • 2017-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 2021-09-10
  • 2014-02-19
相关资源
最近更新 更多