Android開発初心者の私はシンプルなドラムロール式のDatePickerを実装しようとした時に、意外と複数のサイトを参照しながら試行錯誤しました。
同じような初心者の方の参考になれば幸いです。
#サンプルの仕様
・日付入力欄は直接日付を入力することもできる。
・入力欄が空白など日付として認識できない場合、初期値として今日がDatePickerに表示される。
・入力欄が日付の場合、DatePickerには入力欄の日付が初期表示される。
・DatePickerで選択した日付が入力欄に反映される。
#サンプルの仕様変更(2022年1月6日)
:::note alert
■ 古い仕様
・日付入力欄をクリックするとドラムロール式DatePickerが表示される。
:::
■ 変更後の仕様
※ 日付入力欄のどこをクリックしてもDatePickerを表示する仕様だとうざったいので仕様変更
・日付入力欄はクリックしてもなにも起こらない。
・下向き矢印を入力欄とは独立したImageViewにし、下向き矢印をクリックした時だけDatePickerを表示する。
#環境
android studio arctic fox | 2020.3.1 patch 4
compileSdk 32
#コード
さっそくコードの主要部分を紹介します。
ここではわかり易さを重視して必要な部分のコードのみ抜粋しています。
ソース全体は https://github.com/masayahak/Datepicker へアップしています。
DatePickerを呼び出すアクティビティ
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/date_label"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="販売開始日"
app:startIconDrawable="@drawable/ic_calendar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/date"
android:layout_width="190dp"
android:layout_height="60dp"
android:inputType="date"
android:clickable="false"
/>
</com.google.android.material.textfield.TextInputLayout>
<!-- DatePicker表示ボタン -->
<ImageButton
android:id="@+id/date_picker_actions"
android:layout_width="48dp"
android:layout_height="48dp"
android:contentDescription="DatePicker"
android:src="@drawable/ic_arrow_down"
app:layout_constraintTop_toTopOf="@id/date_label"
app:layout_constraintBottom_toBottomOf="@id/date_label"
android:layout_marginTop="4dp"
app:layout_constraintEnd_toEndOf="@id/date_label"
android:layout_marginEnd="8dp"
app:tint="@android:color/black"
android:background="@color/white"
/>
日付入力欄としてTextInputEditTextを利用し、android:clickable="false"にしました。
DatePickerダイアログを表示するのはImageButtonが担当しています。
ImageButtonのandroid:src="@drawable/ic_arrow_down"は下向きの矢印アイコンです。
クリックでDatePickerダイアログが表示されることを明示するためのアイコンです。
@RequiresApi(Build.VERSION_CODES.O)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val img = findViewById<ImageView>(R.id.date_picker_actions)
img.setOnClickListener {
// ドラムロール式DatePickerを呼び出す
val eText = findViewById<View>(R.id.date) as EditText
MyDatePicker.showDatePicker(eText)
}
}
MyDatePicker.showDatePickerで汎用化したDatePickerダイアログを呼び出しています。
引数へDatePickerが値を受け渡しする日付入力用のEditTextを渡してます。
汎用化したDatePicker
@RequiresApi(Build.VERSION_CODES.O)
object MyDatePicker {
fun showDatePicker (eText : EditText) {
// 日付入力フィールドが空白など日付ではないときの初期値として、「今日」を設定
val defaultDate = LocalDate.now()
var year = defaultDate.year
var monthValue = defaultDate.monthValue
var dayOfMonth = defaultDate.dayOfMonth
// 日付入力フィールドの値が日付の場合はその値を設定
val ldt = toLocaleDate(eText.text.toString())
if (ldt != null) {
year = ldt.year
monthValue = ldt.monthValue
dayOfMonth = ldt.dayOfMonth
}
// ドラム式DatePicker表示
val picker = DatePickerDialog(
eText.rootView.context,
AlertDialog.THEME_HOLO_LIGHT, // テーマ:ドラム式 背景白
// ダイアログでOKをクリックされたときの処理 日付入力フィールドへ値を設定
{ _, getYear, getMonthOfYear, getDayOfMonth
-> eText.setText(String.format("%d/%02d/%02d",
getYear,
getMonthOfYear + 1, // 月はZEROオリジン
getDayOfMonth))
},
// DatePickerが初期表示する日付
year,
monthValue - 1, // 月はZEROオリジン
dayOfMonth
)
picker.show()
}
private const val DATE_FORMAT = "yyyy/MM/dd"
fun toLocaleDate(stringDate : String) : LocalDate? {
val df = DateTimeFormatter.ofPattern(DATE_FORMAT)
return try { LocalDate.parse(stringDate, df) } catch (t: Throwable) { null }
}
}
#終わりに
非常に短いコードですが、1つずつ調べながら手作りするのは大変ですよね。お役に立てれば幸いです。
コメント、質問も歓迎です。