🌊

JetpackCompose DatePickerを使う方法

2021/10/08に公開

残念ながらJetpackComposeにはDatePickerがない......

なので前回と同じではありますがMaterialDatePickerを使ってしまいましょう。

サンプルコード

@Composable
fun MainScreen(){

    var datePicked : String? by remember {
        mutableStateOf(null)
    }

    val updatedDate = { date : Long? ->
     datePicked = DateFormater(date)
}

    Scaffold(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
    ) {
        DatePickerview( datePicked, updatedDate )
    }

}

@Composable
fun DatePickerview(
    datePicked : String?,
    updatedDate : ( date : Long? ) -> Unit,
) {
    val activity = LocalContext.current as AppCompatActivity
    
    fun showDatePicker(
        activity: AppCompatActivity,
	updatedDate: (Long?) -> Unit)
    ) {
        val calendar: Calendar = Calendar.getInstance()
        calendar.apply {
            set(Calendar.YEAR, 1950)
            set(Calendar.MONTH, 1)
            set(Calendar.DAY_OF_MONTH, 1)
        }
        MaterialDatePicker.Builder.datePicker()
            .setSelection(calendar.timeInMillis).build().apply {
                show(activity.supportFragmentManager, "Tag")
                addOnPositiveButtonClickListener {
                    validInputEntity.update {
                        updatedDate(it)
                    }
                }
            }
    }

    Box(
        modifier = Modifier
            .fillMaxSize()
            .wrapContentSize(Alignment.TopStart)
            .padding(top = 10.dp)
            .border(0.5.dp, MaterialTheme.colors.onSurface.copy(alpha = 0.5f))
            .clickable{
                showDatePicker(activity, updatedDate)
            }
    ) {

        ConstraintLayout(
            modifier = Modifier
                .fillMaxWidth()
                .padding(16.dp)
        ) {

            val (lable, iconView) = createRefs()

            Text(
                text= datePicked?:"Date Picker",
                color = MaterialTheme.colors.onSurface,
                modifier = Modifier
                    .fillMaxWidth()
                    .constrainAs(lable) {
                        top.linkTo(parent.top)
                        bottom.linkTo(parent.bottom)
                        start.linkTo(parent.start)
                        end.linkTo(iconView.start)
                        width = Dimension.fillToConstraints
                    }
            )

            Icon(
                imageVector = Icons.Default.DateRange,
                contentDescription = null,
                modifier = Modifier
                    .size(20.dp, 20.dp)
                    .constrainAs(iconView) {
                        end.linkTo(parent.end)
                        top.linkTo(parent.top)
                        bottom.linkTo(parent.bottom)
                    },
                tint = MaterialTheme.colors.onSurface
            )

        }

    }
}

fun dateFormater(milliseconds: Long): String {
        milliseconds.let {
            val formatter = SimpleDateFormat("yyyy/MM/dd", Locale.JAPANESE)
            return formatter.format(milliseconds)
        }
    }

解説

側は何でもいいから適当に用意して、

onClickしたらMaterialDatePicker.Builder.datePicker()を

showするようにして表示している感じ。

しかしまた今回も色の変更ができない......

諦めてxmlいじってテーマ作ってスタイル作って

MaterialDatePicker用のカスタムスタイルを作りましょう。

kotlinで完結したいね......

色変更のサンプルコード

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <style name="AlertDialogTheme" parent="ThemeOverlay.MaterialComponents.MaterialAlertDialog">
        <item name="buttonBarPositiveButtonStyle">@style/Positive.Button</item>
        <item name="buttonBarNegativeButtonStyle">@style/Negative.Button</item>
    </style>

    <style name="Positive.Button" parent="Widget.MaterialComponents.Button.TextButton">
        <item name="android:textColor">@color/blue</item>
        <item name="android:textStyle">bold</item>
    </style>

    <style name="Negative.Button" parent="Widget.MaterialComponents.Button.TextButton">
        <item name="android:textColor">@color/blue</item>
    </style>

    <!-- MaterialDatePicker のテーマ -->
    <style name="MaterialCalendarTheme" parent="ThemeOverlay.MaterialComponents.MaterialCalendar">
        <item name="materialCalendarStyle">@style/MyMaterialCalendar</item>
        <item name="buttonBarPositiveButtonStyle">@style/Positive.Button</item>
        <item name="buttonBarNegativeButtonStyle">@style/Negative.Button</item>
        <item name="materialCalendarHeaderTitle">@style/MyMaterialCalendarHeaderTitle</item>
        <item name="materialCalendarHeaderSelection">@style/MyMaterialCalendarHeaderSelection</item>
        <item name="materialCalendarYearNavigationButton">@style/MyMaterialCalendarSelection</item>
        <item name="materialCalendarMonthNavigationButton">@style/MyMaterialCalendarSelection</item>
        <item name="materialCalendarHeaderToggleButton">@style/HeaderToggleButton</item>
        <!-- 曜日や手入力テキスト色 -->
        <item name="android:textColorPrimary">@color/black</item>
        <!-- ヘッダーの背景色 -->
        <item name="colorPrimary">@color/bland</item>
        <!-- 日付の背景色 -->
        <item name="colorSurface">@color/white</item>
        <!-- 日付の年選択時の年の色 -->
        <item name="colorOnSurface">@color/black</item>
        <!-- ヘッダーのアイコン色 -->
        <item name="colorOnPrimary">@color/white</item>
    </style>

    <!-- MaterialDatePicker のスタイル -->
    <style name="MyMaterialCalendar" parent="Widget.MaterialComponents.MaterialCalendar">
        <item name="dayStyle">@style/MyMaterialCalendarDay</item>
        <item name="daySelectedStyle">@style/MyMaterialCalendarDaySelected</item>
    </style>

    <!-- MaterialDatePicker のヘッダータイトル -->
    <style name="MyMaterialCalendarHeaderTitle" parent="Widget.MaterialComponents.MaterialCalendar.HeaderTitle">
        <item name="android:textColor">@color/white</item>
    </style>

    <!-- MaterialDatePicker の選択されたヘッダータイトル -->
    <style name="MyMaterialCalendarHeaderSelection" parent="Widget.MaterialComponents.MaterialCalendar.HeaderSelection">
        <item name="android:textColor">@color/white</item>
    </style>

    <!-- MaterialDatePicker の年月選択ボタン -->
    <style name="MyMaterialCalendarSelection" parent="Base.Widget.MaterialComponents.MaterialCalendar.NavigationButton">
        <item name="android:textColor">@color/black</item>
    </style>

    <!-- MaterialDatePicker の日付 -->
    <style name="MyMaterialCalendarDay" parent="Widget.MaterialComponents.MaterialCalendar.Day">
        <item name="itemTextColor">@color/black</item>
    </style>

    <!-- MaterialDatePicker の選択された日 -->
    <style name="MyMaterialCalendarDaySelected" parent="Widget.MaterialComponents.MaterialCalendar.Day.Selected">
        <item name="itemFillColor">@color/bland</item>
        <item name="itemTextColor">@color/white</item>
    </style>

     <!-- MaterialDatePicker の直接入力切り替えボタン -->
    <style name="HeaderToggleButton" parent="@style/Widget.MaterialComponents.MaterialCalendar.HeaderToggleButton">
        <!--        <item name="android:visibility">gone</item>-->
    </style>
</resources>

参考記事

https://sgkantamani.medium.com/how-to-show-date-picker-in-jetpack-compose-8bc77a3ce408

https://stackoverflow.com/questions/60870677/materialdatepicker-error-materialcalendarfullscreentheme-attribute-to-be-set-in/60870678

https://note.com/numero_dev/n/n9da97a48e14c

https://qiita.com/ue-moo/items/0b407dc4e4f571a52d8d

https://stackoverflow.com/questions/62090970/how-to-change-the-color-of-the-materialdatepicker-in-keyboard-mode-also-it-i/62091571#62091571

Discussion