15

jetpack compose 是否有日期时间选择器视图,或者我应该自己创建它?我试图用谷歌搜索它,但我找不到准备使用的组件。

4

9 回答 9

14

似乎他们仍在努力,与此同时,如果您需要一些非常简单的东西,您可以使用 compose 与 Android Views 的互操作:

@Composable
fun DatePicker(onDateSelected: (LocalDate) -> Unit, onDismissRequest: () -> Unit) {
    val selDate = remember { mutableStateOf(LocalDate.now()) }

    //todo - add strings to resource after POC
    Dialog(onDismissRequest = { onDismissRequest() }, properties = DialogProperties()) {
        Column(
            modifier = Modifier
                .wrapContentSize()
                .background(
                    color = MaterialTheme.colors.surface,
                    shape = RoundedCornerShape(size = 16.dp)
                )
        ) {
            Column(
                Modifier
                    .defaultMinSize(minHeight = 72.dp)
                    .fillMaxWidth()
                    .background(
                        color = MaterialTheme.colors.primary,
                        shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp)
                    )
                    .padding(16.dp)
            ) {
                Text(
                    text = "Select date".toUpperCase(Locale.ENGLISH),
                    style = MaterialTheme.typography.caption,
                    color = MaterialTheme.colors.onPrimary
                )

                Spacer(modifier = Modifier.size(24.dp))

                Text(
                    text = selDate.value.format(DateTimeFormatter.ofPattern("MMM d, YYYY")),
                    style = MaterialTheme.typography.h4,
                    color = MaterialTheme.colors.onPrimary
                )

                Spacer(modifier = Modifier.size(16.dp))
            }

            CustomCalendarView(onDateSelected = {
                selDate.value = it
            })

            Spacer(modifier = Modifier.size(8.dp))

            Row(
                modifier = Modifier
                    .align(Alignment.End)
                    .padding(bottom = 16.dp, end = 16.dp)
            ) {
                TextButton(
                    onClick = onDismissRequest
                ) {
                    //TODO - hardcode string
                    Text(
                        text = "Cancel",
                        style = MaterialTheme.typography.button,
                        color = MaterialTheme.colors.onPrimary
                    )
                }

                TextButton(
                    onClick = {
                        onDateSelected(selDate.value)
                        onDismissRequest()
                    }
                ) {
                    //TODO - hardcode string
                    Text(
                        text = "OK",
                        style = MaterialTheme.typography.button,
                        color = MaterialTheme.colors.onPrimary
                    )
                }

            }
        }
    }
}

@Composable
fun CustomCalendarView(onDateSelected: (LocalDate) -> Unit) {
    // Adds view to Compose
    AndroidView(
        modifier = Modifier.wrapContentSize(),
        factory = { context ->
            CalendarView(ContextThemeWrapper(context, R.style.CalenderViewCustom))
        },
        update = { view ->
            view.minDate = // contraints
            view.maxDate = // contraints

            view.setOnDateChangeListener { _, year, month, dayOfMonth ->
                onDateSelected(
                    LocalDate
                        .now()
                        .withMonth(month + 1)
                        .withYear(year)
                        .withDayOfMonth(dayOfMonth)
                )
            }
        }
    )
}

<style name="CalenderViewCustom" parent="ThemeOverlay.MaterialComponents.MaterialCalendar">
        <item name="colorAccent"><day selection color></item>
        <item name="colorOnPrimary"><text color></item>
        <item name="colorSurface"><background color></item>
</style>

你最终会得到这样的结果:

在此处输入图像描述

于 2021-05-12T03:23:56.327 回答
12

使用库

在撰写本文时,它尚未实施。但是有一个开源库Compose Material Dialogs

日期和时间选择器

没有图书馆

您也可以在没有库的情况下执行此操作,您可以将其放在 onclick 操作中

private fun showDatePicker() {
    val picker = MaterialDatePicker.Builder.datePicker().build()
    activity?.let {
        picker.show(it.supportFragmentManager, picker.toString())
        picker.addOnPositiveButtonClickListener {

        }
    }
}

老办法 :D

于 2021-01-12T04:21:33.527 回答
8

目前,jetpack compose 处于 Alpha 状态,androidx.ui.* 中没有 DateTime Picker。但是,稍后 android 团队将添加它或使 jetpack compose 与其他组件(如 android.widget.DatePicker)互操作,或者我们可以使用 jetpack compose 从 stratch 开发漂亮的日期时间选择器,就像 Flutter所做的那样

目前,

class DateTimeActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val c = Calendar.getInstance()
        val year = c.get(Calendar.YEAR)
        val month = c.get(Calendar.MONTH)
        val day = c.get(Calendar.DAY_OF_MONTH)
        val mHour = c[Calendar.HOUR_OF_DAY]
        val mMinute = c[Calendar.MINUTE]

        val datePickerDialog = DatePickerDialog(
            this, DatePickerDialog.OnDateSetListener
            { datePicker: DatePicker, day: Int, month: Int, year: Int ->
                setContent {
                    Column {
                        Text("$day, $month, $year")
                    }
                }
            }, year, month, day
        )


        val timePickerDialog = TimePickerDialog(
            this,
            TimePickerDialog.OnTimeSetListener { view, hourOfDay, minute ->
                setContent {
                    Column {
                        Text("$hourOfDay:$minute")
                    }
                }
            }, mHour, mMinute, false
        )


        setContent {
            Column {
                Button(text = "Date",
                    style = OutlinedButtonStyle(),
                    onClick = {
                        datePickerDialog.show()
                    })
                Button(text = "Time",
                    style = OutlinedButtonStyle(),
                    onClick = {
                        timePickerDialog.show()
                    })
            }
        }
    }
}
于 2020-02-28T02:35:28.473 回答
7

您可以在 jetpack compose 中显示几行日期选择器

 AndroidView(
            { CalendarView(it) },
            modifier = Modifier.wrapContentWidth(),
            update = { views ->
                views.setOnDateChangeListener { calendarView, i, i2, i3 ->
                }
            }
        )
于 2021-08-22T16:05:06.987 回答
1

没有 3rd 方库,使用 Android View 解决方案:

import android.app.TimePickerDialog

@Composable
fun ShowTimePicker(context: Context, initHour: Int, initMinute: Int) {
    val time = remember { mutableStateOf("") }
    val timePickerDialog = TimePickerDialog(
        context,
        {_, hour : Int, minute: Int ->
            time.value = "$hour:$minute"
        }, initHour, initMinute, false
    )
    Button(onClick = {
        timePickerDialog.show()
    }) {
        Text(text = "Open Time Picker")
    }
}

界面效果

感谢Kiran-Bahalaskar

于 2021-11-04T23:21:13.247 回答
1

你可以使用 DatePickerDialog

val calendar = Calendar.getInstance()
            val listener = DatePickerDialog.OnDateSetListener { view, year, month, dayOfMonth ->
                calendar[Calendar.DAY_OF_MONTH] = dayOfMonth
                calendar[Calendar.MONTH] = month
                calendar[Calendar.YEAR] = year
                
                selectedDate = calendar.timeInMillis
            }
            
            DatePickerDialog(
                context,
                listener,
                calendar[Calendar.YEAR],
                calendar[Calendar.MONTH],
                calendar[Calendar.DAY_OF_MONTH]
            ).show()
于 2021-12-02T02:12:17.187 回答
0

据我所知,Jetpack Compose 中仍然缺少很多小部件。实现它们的唯一方法是使用 AndroidView 和膨胀布局。这是我的时间选择器代码: XML 文件:

    <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TimePicker
        android:id="@+id/simpleTimePicker"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:datePickerMode="spinner"
        android:timePickerMode="spinner"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btn_set_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Set Time"
        android:textColor="#FFFFFF"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/simpleTimePicker"
        tools:ignore="TextContrastCheck" />

    <Button
        android:id="@+id/btn_cancel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Cancel"
        android:textColor="#FFFFFF"

        app:layout_constraintEnd_toStartOf="@+id/btn_set_time"
        app:layout_constraintTop_toBottomOf="@+id/simpleTimePicker"
        tools:ignore="TextContrastCheck" />
    </androidx.constraintlayout.widget.ConstraintLayout>

还有我在 Kotlin 的 Jetpack compose 窗口中的代码:

 Dialog(onDismissRequest = { timePickerStart = false }) {
                        AndroidView(
                            factory = { context: Context ->
                                LayoutInflater.from(context).inflate(R.layout.customtimepicker, null, false)
                            },
                            modifier = Modifier.fillMaxWidth()
                                .background(Color.White),
                            update = { view ->
                                val setTimebutton = view.findViewById<Button>(R.id.btn_set_time)
                                val cancelButton = view.findViewById<Button>(R.id.btn_cancel)
                                val simpleTimePicker = view.findViewById<TimePicker>(R.id.simpleTimePicker)
                                simpleTimePicker.setIs24HourView(true)
                                setTimebutton.setOnClickListener {
                                    var hour = simpleTimePicker.hour
                                    var minute = simpleTimePicker.minute
                                    addNotePlusViewModel.startTime.value = convertToInstant(hour, minute)
                                    timePickerStart = false
                                }
                                cancelButton.setOnClickListener {
                                    timePickerStart = false
                                }
                            }
                        )
                    }
于 2021-12-29T15:19:16.553 回答
0

我创建了一个小型库,用于在 Compose 中呈现日历:https ://github.com/boguszpawlowski/ComposeCalendar 。它本身不是日期选择器,但您可以将其配置为表现得像一个。

于 2021-10-16T10:20:10.343 回答
0

你可以做这样的事情

import androidx.annotation.StringRes
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
import com.google.android.material.datepicker.CalendarConstraints
import com.google.android.material.datepicker.MaterialDatePicker
import com.google.android.material.datepicker.MaterialPickerOnPositiveButtonClickListener
import java.util.*
import kotlin.time.Duration.Companion.hours
import kotlin.time.DurationUnit

@Composable
fun rememberDatePickerDialog(
    @StringRes title: Int,
    select: Date? = null,
    bounds: CalendarConstraints? = null,
    onDateSelected: (Date) -> Unit = {},
): MaterialDatePicker<Long> {
    val datePicker = remember {
        MaterialDatePicker.Builder.datePicker()
            .setSelection((select?.time
                ?: Date().time) + 24.hours.toLong(DurationUnit.MILLISECONDS))
            .setCalendarConstraints(bounds)
            .setTitleText(title)
            .build()
    }

    DisposableEffect(datePicker) {
        val listener = MaterialPickerOnPositiveButtonClickListener<Long> {
            if (it != null) onDateSelected(Date(it))
        }
        datePicker.addOnPositiveButtonClickListener(listener)
        onDispose {
            datePicker.removeOnPositiveButtonClickListener(listener)
        }
    }

    return datePicker
}

FragmentManager用于显示选择器(单击按钮)。在使用以下内容之前,请确保您的活动从 a开始。FragmentActivity

@Composable
fun rememberFragmentManager(): FragmentManager {
    val context = LocalContext.current
    return remember(context) {
        (context as FragmentActivity).supportFragmentManager
    }
}

示例用例。

val DATE_FORMAT = SimpleDateFormat("dd/MM/yyyy", Locale.getDefault())
var date by remember {
  mutableStateOf(TextFieldValue(DATE_FORMAT.format(Date())))
}
val fragmentManager = rememberFragmentManager()

val datePicker = rememberDatePickerDialog(
    select = DATE_FORMAT.parse(date.text),
    title = R.string.select_date,
) { date = TextFieldValue(DATE_FORMAT.format(it)) }

TextField(
  readOnly = true,
  value = date,
  onValueChange = { date = it },
  trailingIcon = {
    IconButton({ datePicker.show(fragmentManager, "Date") }) {
       Icon(Icons.Default.DateRange,contentDescription = null)
    }
  },
)
于 2022-02-11T09:53:36.877 回答