/**
* Interface to describe the navigation destinations for the app
*/
interface NavigationDestination {
/**
* Unique name to define the path for a composable
*/
val route: String
/**
* String resource id to that contains title to be displayed for the screen.
*/
val titleRes: Int
}
class PlanMakeViewModel(
savedStateHandle: SavedStateHandle,
private val planRepository: PlanRepository,
): ViewModel() {
/**
* Make Plan UI state
*/
var planMakeUiState by mutableStateOf(PlanMakeUiState())
private set
/**
* Initialize private values in presence of an existing Plan object
*/
init {
try {
val planId: Int = checkNotNull(savedStateHandle[DestinationPlanEdit.PLAN_ID])
viewModelScope.launch {
planMakeUiState = planRepository
.getPlanOne(planId)
.filterNotNull()
.first()
.toMakePlanUiState()
}
} catch(_: Exception) {
/**
* No Plan ID supplied
*
* Assume user is making plan, or plan is missing in database
*/
}
}
/**
* Check that no fields are empty
*/
private fun validateInput(planCheck: Plan = planMakeUiState.plan): Boolean {
return with(planCheck) {
note.isNotBlank()
}
}
/**
* Updates the [planMakeUiState] with the value provided in the argument. This method also triggers
* a validation for input values.
*/
fun updateUiState(planUpdated: Plan) {
planMakeUiState = PlanMakeUiState(
plan = planUpdated,
fieldNotEmptyAll = validateInput(planUpdated)
)
}
/**
* Insert + Update current plan
*/
suspend fun planUpsert() {
if (validateInput()) planRepository.planUpsert(planMakeUiState.plan.toEntity())
}
}
Они взяты из моего проекта приложения Outlook Planner на GitHub
Под лицензией GPL вы можете git клонировать его на свои компьютеры и проверять самостоятельно.
Моя цель на NavHost — извлечь Plan.id из составной функции Home, а затем перенести это значение в DestinationPlanEdit.routeWithId для редактирования этого < em>Plan и сохраните его в базе данных Room. Единственная проблема заключается в том, что он возвращает следующую ошибку:
FATAL EXCEPTION: main
Process: com.outlook.planner, PID: 19658
java.lang.IllegalArgumentException: Navigation destination that matches request NavDeepLinkRequest{ uri=android-app://androidx.navigation/2131689725/3 } cannot be found in the navigation graph ComposeNavGraph(0x0) startDestination={Destination(0xf08bc5ce) route=2131689704}
at androidx.navigation.NavController.navigate(NavController.kt:1819)
at androidx.navigation.NavController.navigate(NavController.kt:2225)
at androidx.navigation.NavController.navigate$default(NavController.kt:2220)
at com.outlook.planner.ui.navigation.OutlookPlannerNavHostKt$OutlookPlannerNavHost$1$1$2.invoke(OutlookPlannerNavHost.kt:38)
at com.outlook.planner.ui.navigation.OutlookPlannerNavHostKt$OutlookPlannerNavHost$1$1$2.invoke(OutlookPlannerNavHost.kt:34)
at com.outlook.planner.ui.pages.home.HomeKt$Home$2$1$1$1$1.invoke(Home.kt:52)
at com.outlook.planner.ui.pages.home.HomeKt$Home$2$1$1$1$1.invoke(Home.kt:52)
at androidx.compose.foundation.ClickablePointerInputNode$pointerInput$3.invoke-k-4lQ0M(Clickable.kt:987)
at androidx.compose.foundation.ClickablePointerInputNode$pointerInput$3.invoke(Clickable.kt:981)
Я не знаю, как это решить. Я просмотрел различные видеоуроки в Интернете (большинство из которых бесполезны, поскольку в них преподаются XML и фрагменты, а это не то, что я изучаю в Основах Android с Compose
Я спрашиваю за помощью относительно причины этой проблемы, так как я устал и не могу исправить это самостоятельно. Но мне нужна эта функция для работы.
Заранее спасибо. РЕДАКТИРОВАТЬ
Еще несколько соответствующих файлов на случай, если клонирование проектов GitHub вам не по душе: PlanMakeUiState.kt< /strong>
/**
* Data class that represents the plan UI state
*
* Uses:
* - Hold current plan
* - Check if all fields are not empty
* - To show MaterialTimePicker or not
* - To show MaterialDatePicker or not
*/
data class PlanMakeUiState(
val plan: Plan = Plan(
note = "",
year = LocalDateTime.now().year,
month = LocalDateTime.now().monthValue,
date = LocalDateTime.now().dayOfMonth,
hour = LocalDateTime.now().hour,
minute = LocalDateTime.now().minute,
),
val fieldNotEmptyAll: Boolean = false
)
@Composable
fun PlanMake(
modifier: Modifier = Modifier,
pageCurrent: String,
navigateBack: () -> Unit,
context: Context = LocalContext.current,
viewModel: PlanMakeViewModel = viewModel(factory = AppViewModelProvider.Factory)
) {
/**
* Immutable values
*/
val coroutineScope = rememberCoroutineScope()
Scaffold(
floatingActionButton = {
AppFAB(
pageCurrent = pageCurrent,
onClick = {
coroutineScope.launch {
viewModel.planUpsert()
navigateBack()
}
}
)
},
modifier = modifier
) { innerPadding ->
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.padding(innerPadding)
.fillMaxWidth()
) {
ViewingArea(pageCurrent = pageCurrent)
/**
* Note of plan
*/
MakePlanBody(
modifier = modifier,
planMakeUiState = viewModel.planMakeUiState,
onPlanValueChange = viewModel::updateUiState,
context = context
)
}
}
}
/**
* References:
* https://codingwithrashid.com/how-to-add-underlined-text-in-android-jetpack-compose/
*/
@Composable
fun MakePlanBody(
modifier: Modifier = Modifier,
planMakeUiState: PlanMakeUiState,
onPlanValueChange: (Plan) -> Unit,
context: Context
) {
/**
* Encompass the Plan in the UI state to a concise pointer variable
*/
val plan: Plan = planMakeUiState.plan
/**
* Embellishment values
*/
val heightSpacer: Dp = 32.dp
val heightSpacerBetweenTextAndButton: Dp = 8.dp
val textStyle = TextStyle(textAlign = TextAlign.Left)
val sizeFontOfHeader = 16.sp
val sizeFontOfDateTimeValue = 24.sp
/**
* Logic variables
*/
var showPickerTime: Boolean by remember { mutableStateOf(false) }
var showPickerDate: Boolean by remember { mutableStateOf(false) }
/**
* Display variables
*/
var displayTime: LocalTime by remember { mutableStateOf(LocalTime.of(plan.hour, plan.minute)) }
var displayDate: LocalDate by remember { mutableStateOf(LocalDate.of(plan.year, plan.month, plan.date)) }
/**
* Field to insert a note
*/
Text(
text = "Note",
fontSize = sizeFontOfHeader
)
TextField(
value = planMakeUiState.plan.note,
onValueChange = { noteNew -> onPlanValueChange(plan.copy(note = noteNew)) },
textStyle = textStyle,
placeholder = {
Text(
text = "Your note here",
textAlign = TextAlign.Center,
)
}
)
Spacer(modifier = Modifier.height(heightSpacer))
/**
* Field to pick a time
*/
Text(
text = stringResource(id = R.string.ask_time),
fontSize = sizeFontOfHeader
)
Spacer(modifier = Modifier.height(heightSpacerBetweenTextAndButton))
Text(
text = buildAnnotatedString {
append("On")
append(" ")
withStyle(style = SpanStyle(textDecoration = TextDecoration.Underline)) {
append(displayTime.toString())
}
},
fontSize = sizeFontOfDateTimeValue,
)
Spacer(modifier = Modifier.height(heightSpacerBetweenTextAndButton))
Button(
onClick = { showPickerTime = !showPickerTime },
) {
Text(
text = stringResource(id = R.string.set_time)
)
if(showPickerTime) {
ShowMaterialDateTimePicker(
context = context,
typeReturn = TYPE_TIME,
onDateTimeSet = {
newTime -> onPlanValueChange(plan.copy(hour = newTime.hour, minute = newTime.minute))
}
)
showPickerTime = !showPickerTime
}
// Update the time to show on UI screen
displayTime = LocalTime.of(plan.hour, plan.minute)
}
Spacer(modifier = Modifier.height(heightSpacer))
/**
* Field to pick a date
*/
Text(
text = stringResource(id = R.string.ask_date),
fontSize = sizeFontOfHeader
)
Spacer(modifier = Modifier.height(heightSpacerBetweenTextAndButton))
Text(
text = when(displayDate) {
LocalDate.now() -> "Today!"
LocalDate.now().plusDays(1) -> "Tomorrow!"
else -> "${displayDate.dayOfMonth} ${displayDate.month} ${displayDate.year}"
},
fontSize = sizeFontOfDateTimeValue,
)
Spacer(modifier = Modifier.height(heightSpacerBetweenTextAndButton))
Button(
onClick = { showPickerDate = !showPickerDate },
) {
Text(
text = stringResource(id = R.string.set_date)
)
if(showPickerDate) {
ShowMaterialDateTimePicker(
typeReturn = TYPE_DATE,
onDateTimeSet = {newDate -> onPlanValueChange(plan.copy(date = newDate.dayOfMonth, month = newDate.monthValue, year = newDate.year))
}
)
showPickerDate = !showPickerDate
}
// Update the [displayDate] to show on UI screen display
displayDate = LocalDate.of(plan.year, plan.month, plan.date)
}
}
@Composable
fun ShowMaterialDateTimePicker(
context: Context? = null,
typeReturn: String,
onDateTimeSet: (LocalDateTime) -> Unit
) {
/**
* Shared variables among the dialogs
*/
var pickedDateTime: LocalDateTime = LocalDateTime.now()
/**
* Check if user wants date or time
*/
when(typeReturn) {
/**
* RETURN:
* Time in Hours & Minutes
*
* Build the MaterialTimePicker Dialog
*/
TYPE_TIME -> {
val pickerTime = PickerTime(
modeInput = MaterialTimePicker.INPUT_MODE_CLOCK,
title = "Set a Time",
setClockFormat = is24HourFormat(context)
).dialog
/**
* Show it
*/
pickerTime.show(
getActivity().supportFragmentManager,
DestinationPlanMake.route
)
/**
* Save its values
*/
pickerTime.addOnPositiveButtonClickListener {
/**
* Convert the chosen time to Java's new API called "LocalDateTime"
* then pass two arguments to it to be made:
* - date = LocalDateTime.now().toLocalDate()
* - time = Picked time of user
*/
pickedDateTime = LocalDateTime.of(
LocalDateTime.now().toLocalDate(),
LocalTime.of(pickerTime.hour, pickerTime.minute)
)
/**
* And then we return that value
*/
Log.d("ADebug", "Picked time is now ${pickedDateTime.toLocalTime()}")
onDateTimeSet(pickedDateTime)
}
}
/**
* RETURN:
* Date in Year, Month, Date
*
* Build the MaterialDatePicker Dialog
*/
TYPE_DATE -> {
val pickerDate = PickerDate(title = stringResource(id = R.string.set_date)).dialog
/**
* Show it
*/
pickerDate.show(
getActivity().supportFragmentManager,
DestinationPlanMake.route
)
/**
* Save its values
*/
pickerDate.addOnPositiveButtonClickListener { dateInLong ->
/**
* Convert the chosen date to Java's new API called "LocalDateTime"
* then pass two arguments to it to be made:
* - date = Conversion of user's picked date from long (default type) to a date
* - time = Picked time of user
*
* NOTE:
* By default, this returns the date yesterday, so
* use plusDays() or UTC timezone to correct that
*
* - https://stackoverflow.com/a/7672633
*/
// pickedDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(dateInLong), TimeZone.getDefault().toZoneId())
pickedDateTime = Instant.ofEpochMilli(dateInLong).atZone(ZoneId.of("UTC")).toLocalDateTime()
/**
* And then we return that value
*/
Log.d("ADebug", "What is ${pickedDateTime.dayOfMonth} ${pickedDateTime.monthValue} ${pickedDateTime.year} to you?")
Log.d("ADebug", "Correct date should be ${LocalDateTime.now().toLocalDate()} to you?")
Log.d("ADebug", "Timezone is ${TimeZone.getDefault()}\n vs. ${TimeZone.getTimeZone("UTC")} to you?")
// Log.d("ADebug", "What is $selectedDate to you?")
onDateTimeSet(pickedDateTime)
}
}
else -> {
/**
* Neither was specified,
* so return a generic answer: Today
*/
onDateTimeSet(pickedDateTime)
}
}
}
[b]Вот мой соответствующий код, созданный с помощью Kotlin + Jetpack Compose:[/b] [b]OutlookPlannerNavHost.kt[/b] [code]/** * Provides Navigation graph for the application. */ @Composable fun OutlookPlannerNavHost( navController: NavHostController, modifier: Modifier = Modifier ) { NavHost( navController = navController, startDestination = DestinationHome.route, modifier = modifier ) { /** * Home page */ composable(route = DestinationHome.route) { Home( modifier = modifier, pageCurrent = DestinationHome.route, navigateToPlanMake = { navController.navigate(route = DestinationPlanMake.route) }, navigateToPlanEdit = { planId -> navController.navigate(route = "${DestinationPlanEdit.route}/${planId}") } ) } /** * Make Plan page */ composable(route = DestinationPlanMake.route) { PlanMake( modifier = modifier, pageCurrent = DestinationPlanEdit.route, navigateBack = { navController.popBackStack() }, ) } /** * Edit Plan page * (AKA Make Plan page with a Plan object passed) */ composable( route = DestinationPlanEdit.routeWithId, arguments = listOf(navArgument(name = DestinationPlanEdit.PLAN_ID) { type = NavType.IntType }) ) { Log.d("Args", it.arguments?.getInt(DestinationPlanEdit.PLAN_ID).toString()) PlanMake( modifier = modifier, pageCurrent = DestinationPlanEdit.route, navigateBack = { navController.popBackStack() }, ) } } } [/code] [b]Home.kt[/b] [code]@Composable fun Home( modifier: Modifier = Modifier, navigateToPlanMake: () -> Unit, navigateToPlanEdit: (Int) -> Unit, pageCurrent: String, viewModel: HomeViewModel = viewModel(factory = AppViewModelProvider.Factory) ) { /** * Immutable variables */ val homeUiState by viewModel.homeUiState.collectAsState() val planList = homeUiState.planList
Scaffold ( floatingActionButton = { AppFAB( pageCurrent = pageCurrent, onClick = navigateToPlanMake ) }, modifier = modifier, ) { LazyColumn (modifier = modifier.padding(it)) { item { ViewingArea() } items(items = planList) { planEntity -> PlanCard( planEntity = planEntity, modifier = modifier .padding(16.dp) .clickable { navigateToPlanEdit(planEntity.id) } ) } } } } [/code] [b]NavigationDestination.kt[/b] [code]/** * Interface to describe the navigation destinations for the app */ interface NavigationDestination { /** * Unique name to define the path for a composable */ val route: String
/** * String resource id to that contains title to be displayed for the screen. */ val titleRes: Int } [/code] [b]DestinationPlanEdit.kt[/b] [code]object DestinationPlanEdit: NavigationDestination { override val route = R.string.route_plan_edit.toString() override val titleRes = R.string.name_plan_edit /** * Additional values for routing */ const val PLAN_ID: String = "planId" val routeWithId: String = "$route/${PLAN_ID}" } [/code] [b]PlanMakeViewModel.kt[/b] [code]class PlanMakeViewModel( savedStateHandle: SavedStateHandle, private val planRepository: PlanRepository, ): ViewModel() { /** * Make Plan UI state */ var planMakeUiState by mutableStateOf(PlanMakeUiState()) private set
/** * Initialize private values in presence of an existing Plan object */ init { try { val planId: Int = checkNotNull(savedStateHandle[DestinationPlanEdit.PLAN_ID]) viewModelScope.launch { planMakeUiState = planRepository .getPlanOne(planId) .filterNotNull() .first() .toMakePlanUiState() } } catch(_: Exception) { /** * No Plan ID supplied * * Assume user is making plan, or plan is missing in database */ } }
/** * Check that no fields are empty */ private fun validateInput(planCheck: Plan = planMakeUiState.plan): Boolean { return with(planCheck) { note.isNotBlank() } }
/** * Updates the [planMakeUiState] with the value provided in the argument. This method also triggers * a validation for input values. */ fun updateUiState(planUpdated: Plan) { planMakeUiState = PlanMakeUiState( plan = planUpdated, fieldNotEmptyAll = validateInput(planUpdated) ) }
/** * Insert + Update current plan */ suspend fun planUpsert() { if (validateInput()) planRepository.planUpsert(planMakeUiState.plan.toEntity()) } } [/code] Они взяты из моего проекта приложения Outlook Planner на GitHub Под лицензией GPL вы можете git клонировать его на свои компьютеры и проверять самостоятельно. Моя цель на NavHost — извлечь Plan.id из составной функции Home, а затем перенести это значение в DestinationPlanEdit.routeWithId для редактирования этого < em>Plan и сохраните его в базе данных Room. [b]Единственная проблема заключается в том, что он возвращает следующую ошибку:[/b] [code]FATAL EXCEPTION: main Process: com.outlook.planner, PID: 19658 java.lang.IllegalArgumentException: Navigation destination that matches request NavDeepLinkRequest{ uri=android-app://androidx.navigation/2131689725/3 } cannot be found in the navigation graph ComposeNavGraph(0x0) startDestination={Destination(0xf08bc5ce) route=2131689704} at androidx.navigation.NavController.navigate(NavController.kt:1819) at androidx.navigation.NavController.navigate(NavController.kt:2225) at androidx.navigation.NavController.navigate$default(NavController.kt:2220) at com.outlook.planner.ui.navigation.OutlookPlannerNavHostKt$OutlookPlannerNavHost$1$1$2.invoke(OutlookPlannerNavHost.kt:38) at com.outlook.planner.ui.navigation.OutlookPlannerNavHostKt$OutlookPlannerNavHost$1$1$2.invoke(OutlookPlannerNavHost.kt:34) at com.outlook.planner.ui.pages.home.HomeKt$Home$2$1$1$1$1.invoke(Home.kt:52) at com.outlook.planner.ui.pages.home.HomeKt$Home$2$1$1$1$1.invoke(Home.kt:52) at androidx.compose.foundation.ClickablePointerInputNode$pointerInput$3.invoke-k-4lQ0M(Clickable.kt:987) at androidx.compose.foundation.ClickablePointerInputNode$pointerInput$3.invoke(Clickable.kt:981) [/code] Я не знаю, как это решить. Я просмотрел различные видеоуроки в Интернете (большинство из которых бесполезны, поскольку в них преподаются XML и фрагменты, а это не то, что я изучаю в Основах Android с Compose Я спрашиваю за помощью относительно причины этой проблемы, так как я устал и не могу исправить это самостоятельно. Но мне нужна эта функция для работы. Заранее спасибо. [b]РЕДАКТИРОВАТЬ[/b] Еще несколько соответствующих файлов на случай, если клонирование проектов GitHub вам не по душе: [b]PlanMakeUiState.kt< /strong>
[code]/** * Data class that represents the plan UI state * * Uses: * - Hold current plan * - Check if all fields are not empty * - To show MaterialTimePicker or not * - To show MaterialDatePicker or not */ data class PlanMakeUiState( val plan: Plan = Plan( note = "", year = LocalDateTime.now().year, month = LocalDateTime.now().monthValue, date = LocalDateTime.now().dayOfMonth, hour = LocalDateTime.now().hour, minute = LocalDateTime.now().minute, ), val fieldNotEmptyAll: Boolean = false )[/code]
/** * References: * https://codingwithrashid.com/how-to-add-underlined-text-in-android-jetpack-compose/ */ @Composable fun MakePlanBody( modifier: Modifier = Modifier, planMakeUiState: PlanMakeUiState, onPlanValueChange: (Plan) -> Unit, context: Context ) { /** * Encompass the Plan in the UI state to a concise pointer variable */ val plan: Plan = planMakeUiState.plan
/** * Embellishment values */ val heightSpacer: Dp = 32.dp val heightSpacerBetweenTextAndButton: Dp = 8.dp val textStyle = TextStyle(textAlign = TextAlign.Left) val sizeFontOfHeader = 16.sp val sizeFontOfDateTimeValue = 24.sp
/** * Logic variables */ var showPickerTime: Boolean by remember { mutableStateOf(false) } var showPickerDate: Boolean by remember { mutableStateOf(false) }
/** * Display variables */ var displayTime: LocalTime by remember { mutableStateOf(LocalTime.of(plan.hour, plan.minute)) } var displayDate: LocalDate by remember { mutableStateOf(LocalDate.of(plan.year, plan.month, plan.date)) }
/** * Field to insert a note */ Text( text = "Note", fontSize = sizeFontOfHeader ) TextField( value = planMakeUiState.plan.note, onValueChange = { noteNew -> onPlanValueChange(plan.copy(note = noteNew)) }, textStyle = textStyle, placeholder = { Text( text = "Your note here", textAlign = TextAlign.Center, ) } ) Spacer(modifier = Modifier.height(heightSpacer))
/** * Field to pick a time */ Text( text = stringResource(id = R.string.ask_time), fontSize = sizeFontOfHeader ) Spacer(modifier = Modifier.height(heightSpacerBetweenTextAndButton)) Text( text = buildAnnotatedString { append("On") append(" ") withStyle(style = SpanStyle(textDecoration = TextDecoration.Underline)) { append(displayTime.toString()) } }, fontSize = sizeFontOfDateTimeValue, ) Spacer(modifier = Modifier.height(heightSpacerBetweenTextAndButton)) Button( onClick = { showPickerTime = !showPickerTime }, ) { Text( text = stringResource(id = R.string.set_time) ) if(showPickerTime) { ShowMaterialDateTimePicker( context = context, typeReturn = TYPE_TIME, onDateTimeSet = { newTime -> onPlanValueChange(plan.copy(hour = newTime.hour, minute = newTime.minute)) } ) showPickerTime = !showPickerTime } // Update the time to show on UI screen displayTime = LocalTime.of(plan.hour, plan.minute) } Spacer(modifier = Modifier.height(heightSpacer))
/** * Field to pick a date */ Text( text = stringResource(id = R.string.ask_date), fontSize = sizeFontOfHeader ) Spacer(modifier = Modifier.height(heightSpacerBetweenTextAndButton)) Text( text = when(displayDate) { LocalDate.now() -> "Today!" LocalDate.now().plusDays(1) -> "Tomorrow!" else -> "${displayDate.dayOfMonth} ${displayDate.month} ${displayDate.year}" }, fontSize = sizeFontOfDateTimeValue, ) Spacer(modifier = Modifier.height(heightSpacerBetweenTextAndButton)) Button( onClick = { showPickerDate = !showPickerDate }, ) { Text( text = stringResource(id = R.string.set_date) ) if(showPickerDate) { ShowMaterialDateTimePicker( typeReturn = TYPE_DATE, onDateTimeSet = {newDate -> onPlanValueChange(plan.copy(date = newDate.dayOfMonth, month = newDate.monthValue, year = newDate.year)) } ) showPickerDate = !showPickerDate } // Update the [displayDate] to show on UI screen display displayDate = LocalDate.of(plan.year, plan.month, plan.date) } }
@Composable fun ShowMaterialDateTimePicker( context: Context? = null, typeReturn: String, onDateTimeSet: (LocalDateTime) -> Unit ) { /** * Shared variables among the dialogs */ var pickedDateTime: LocalDateTime = LocalDateTime.now()
/** * Check if user wants date or time */ when(typeReturn) { /** * RETURN: * Time in Hours & Minutes * * Build the MaterialTimePicker Dialog */ TYPE_TIME -> { val pickerTime = PickerTime( modeInput = MaterialTimePicker.INPUT_MODE_CLOCK, title = "Set a Time", setClockFormat = is24HourFormat(context) ).dialog
/** * Show it */ pickerTime.show( getActivity().supportFragmentManager, DestinationPlanMake.route ) /** * Save its values */ pickerTime.addOnPositiveButtonClickListener { /** * Convert the chosen time to Java's new API called "LocalDateTime" * then pass two arguments to it to be made: * - date = LocalDateTime.now().toLocalDate() * - time = Picked time of user */ pickedDateTime = LocalDateTime.of( LocalDateTime.now().toLocalDate(), LocalTime.of(pickerTime.hour, pickerTime.minute) ) /** * And then we return that value */ Log.d("ADebug", "Picked time is now ${pickedDateTime.toLocalTime()}") onDateTimeSet(pickedDateTime) } } /** * RETURN: * Date in Year, Month, Date * * Build the MaterialDatePicker Dialog */ TYPE_DATE -> { val pickerDate = PickerDate(title = stringResource(id = R.string.set_date)).dialog
/** * Show it */ pickerDate.show( getActivity().supportFragmentManager, DestinationPlanMake.route ) /** * Save its values */ pickerDate.addOnPositiveButtonClickListener { dateInLong -> /** * Convert the chosen date to Java's new API called "LocalDateTime" * then pass two arguments to it to be made: * - date = Conversion of user's picked date from long (default type) to a date * - time = Picked time of user * * NOTE: * By default, this returns the date yesterday, so * use plusDays() or UTC timezone to correct that * * - https://stackoverflow.com/a/7672633 */ // pickedDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(dateInLong), TimeZone.getDefault().toZoneId()) pickedDateTime = Instant.ofEpochMilli(dateInLong).atZone(ZoneId.of("UTC")).toLocalDateTime()
/** * And then we return that value */ Log.d("ADebug", "What is ${pickedDateTime.dayOfMonth} ${pickedDateTime.monthValue} ${pickedDateTime.year} to you?") Log.d("ADebug", "Correct date should be ${LocalDateTime.now().toLocalDate()} to you?") Log.d("ADebug", "Timezone is ${TimeZone.getDefault()}\n vs. ${TimeZone.getTimeZone("UTC")} to you?") // Log.d("ADebug", "What is $selectedDate to you?") onDateTimeSet(pickedDateTime) } } else -> { /** * Neither was specified, * so return a generic answer: Today */ onDateTimeSet(pickedDateTime) } } }[/code]
Я пытаюсь внедрить навигацию от уведомления о толчке к экрану через DeepLinks, и я заставил его работать для некоторых из моих уведомлений. Но навигация на мой детальный экран просто не хочет работать. Я размышлял об этом в течение нескольких дней,...
Я пытаюсь внедрить навигацию от уведомления о толчке к экрану через DeepLinks, и я заставил его работать для некоторых из моих уведомлений. Но навигация на мой детальный экран просто не хочет работать. Я размышлял об этом в течение нескольких дней,...
Я пишу приложение, которое использует Androidx.navigation для перемещения между экранами, и после этой документации:
Kotlin-dsl
Я изо всех сил пытаюсь понять, как получить доступ к параметрам в пункте назначения.
Мой (упрощенный) маршрут экрана...