TL; DR
それは1964ではないが、2100はひどくフォーマット。 CalendarView
にバグがあります。 formatDateRange()
は動作しません過去2038
回避策#1、私は実際に分析
CalendarView
// Calendar view is a cascade of bugs.
// Work around that by explicitly disabling it.
datePicker.setCalendarViewShown(false);
を使用回避策#2は、月/年の名でを生成するためのandroid.text.format.DateUtils.formatDateRange()
を使用しています
class DatePickerDialog1964 extends DatePickerDialog {
DatePickerDialog1964(Context c) {
super(c, null, 2013, 4, 21);
@SuppressWarnings("deprecation")
Date min = new Date(2013-1900, 4, 21);
DatePicker p = getDatePicker();
CalendarView cv = p.getCalendarView(); // should check for null
long cur = cv.getDate();
int d = cv.getFirstDayOfWeek();
p.setMinDate(min.getTime());
cv.setDate(cur + 1000L*60*60*24*40);
cv.setFirstDayOfWeek((d + 1) % 7);
cv.setDate(cur);
cv.setFirstDayOfWeek(d);
}
}
ヘッダーカレンダービューは、月の番号が変更されたときにのみヘッダーを更新します。たとえば、月の数字が同じで年が変更された場合、ヘッダーは更新されません。
レイアウトフェーズのどこかで、基になるListView
は、リストが最後までスクロールされたかのように、カレンダービューでOnScrollListener
を呼び出します。月の数字が変更された場合、ヘッダーは上記のテストコードで更新され、formatDateRange()
に渡されるミリ秒値は4131043200000
で、2100年後半にあり、2100はDatePicker
のデフォルト最大値です。
formatDateRange()
は、具体的にはset()
メソッドを使用してミリ秒を内部のカレンダー表現として使用します(android.text.format.Time
)。基本的なネイティブコードはチェックしませんでしたが、渡されたミリ秒の値が、の32ビットのtime_t
秒の値に切り捨てられ、62年を少し超える値にラップされます。 Time
自体は、1900年からint
として年を表すstruct tm
を使用しているため、1960年にはTime
となり、ヘッダでフォーマットされます。
これは、CalendarView
と平文で再現することができます。スピナーを使用して年を2038年以降に移動し、ヘッダーの更新をトリガーするために月を変更すると、1902年にヘッダーラップされた年が表示されます。
ここで、カレンダー表示を最大の日付にスクロールします。回答はカレンダービューの週ListView
アダプターのようです。最小日付から数週間のインデックスが作成されますが、最小日付が変更されると、アダプタのnotifyDataSetChanged()
は呼び出されません。上記の回避策#1は次の理由で機能します。
- 月を1か月以上変更すると、月のヘッダーが変更されます。
- 週の最初の曜日を変更すると、週のリストビューにアダプタのデータが変更されたことが通知されます。
私の最初の本能は、廃止予定のメソッドを使用しているときにバグの挙動が現れた場合は、廃止予定のメソッドなしでやり直してください。カレンダーを使用して日付を設定しても同じ問題が発生しますか? – Jules
これは非推奨です。 'setMinDate()'は 'long'ミリ秒の値をとり、' DatePicker'に渡されたことを確認しました。単にこの廃止予定の 'Date'コンストラクタを使用して、この問題を示すサンプルを調理してください。 – laalto
あなたが固定されたminDateで暮らすことができれば、XMLを介して設定することは実際には機能します。それ以外の場合は、CalendarView.javaをAOSPから取り出すことで、より洗練された修正を利用できます。 – lilbyrdie