У меня есть композитный, который использует холст для рисования задач на часовом циферблате. Задачи считываются из состояния ViewModel, которое, в свою очередь, загружает их из базы данных. Список задач варьируется в зависимости от выбранной даты. Когда вы выбираете дату (например, 26 июня) на компоненте календаря, ViewModel загружает задачи на 26 июня и рисует их (рисунок задачи не показан в примере ниже). < /P>
Когда я нажимаю на холм, журнал показывает данные для 26 июня. Если я выберу новую дату (например, 27 июня), задачи для 27 июня загружаются должным образом. Журналы LogCat показывают данные 26 июня (первоначальная загрузка данных), 26 июня данных (после нажатия на холст), 27 июня данных (после выбора 27 июня), а затем снова 26 июня данных (после нажатия на холст), даже если я не выбрал эту дату снова - циферблат определенно был нанесен с правильными данными (для 27 -го июня). < /P>
факт, что является фактом, что это затрудняет. Я ожидаю, что он останется 27 июня, пока я не выберу другую дату. Эта проблема с датой датой, дату, возникает только тогда, когда я нажимаю на циферблат, а затем выбираю другую дату. Если я продолжаю выбирать разные даты без , нажав на циферблат между выбором даты, данные не возвращаются к предыдущей дате самостоятельно.
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.onGloballyPositioned
import kotlin.math.min
import android.util.Log
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.ui.Alignment
import com.example.circularplanner.ui.viewmodel.DayState
import com.example.circularplanner.ui.viewmodel.TaskUiState
import com.example.circularplanner.ui.viewmodel.UserInput
import com.example.circularplanner.utils.TaskDialUtils.square
import java.time.LocalDate
import kotlin.math.sqrt
@Composable
fun TestTaskDial(
dayState: DayState,
userInput: UserInput,
onSetDate: (LocalDate) -> Unit
) {
// The width and height of the Canvas
var width by remember { mutableStateOf(0) }
var height by remember { mutableStateOf(0) }
var touchInsideTheDial by remember { mutableStateOf(false) }
var center by remember { mutableStateOf(Offset.Zero) }
// Basically the width of the finger touch on the screen
var touchStroke: Float = 50f
// The radius of the dial (from the center to the end of the clock steps)
var outerRadius by remember { mutableStateOf(0f) }
Log.i("DDselectedDate", userInput.selectedDate.toString())
Log.i("DDdate", dayState.date.toString())
Log.i("DDtasks", dayState.tasks.joinToString())
fun distance(first: Offset, second: Offset): Float {
return sqrt((first.x - second.x).square() + (first.y - second.y).square())
}
fun checkIfTouchInsideDial(distance: Float, radius: Float, touchStroke: Float): Boolean {
if (distance
val distance = distance(offset, center)
touchInsideTheDial = checkIfTouchInsideDial(
distance,
outerRadius,
touchStroke
)
if (touchInsideTheDial) {
Log.i("TaskDial", "onTap")
Log.i("DDselectedDate", userInput.selectedDate.toString())
Log.i("DDdate", dayState.date.toString())
Log.i("DDtasks", dayState.tasks.joinToString())
}
}
)
}
) {
outerRadius = min(width, height) / 2f * 0.8f
// Draw dial
drawCircle(
color = Color.Cyan,
center = center,
radius = outerRadius,
)
}
Row(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(0.1f),
verticalAlignment = Alignment.Bottom,
horizontalArrangement = Arrangement.SpaceBetween
) {
Button(onClick = { onSetDate(LocalDate.parse("2025-06-26")) }) {
Text("26th June")
}
Button(onClick = { onSetDate(LocalDate.parse("2025-06-27")) }) {
Text("27th June")
}
}
Row (
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(0.1f),
verticalAlignment = Alignment.Bottom,
horizontalArrangement = Arrangement.Center
) {
Text(text = userInput.selectedDate.toString())
}
}
}
< /code>
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.CreationExtras
import com.example.circularplanner.data.Task
import com.example.circularplanner.data.Time
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import java.time.LocalDate
import java.util.UUID
import kotlin.String
typealias Tasks = List
data class DayState (
val date: LocalDate = LocalDate.now(),
val activeTimeStart: Time = Time(6, 0),
val activeTimeEnd: Time = Time(22, 0),
val tasks: Tasks = emptyList()
)
data class UserInput(
val selectedDate: LocalDate = LocalDate.parse("2025-06-26"),
)
data class Day(
val date: LocalDate,
val activeTimeStart: Time,
val activeTimeEnd: Time,
)
data class Time(
var hour: Int = 0,
var minute: Int = 0
)
data class Task (
val date: LocalDate,
var title: String,
var startTime: Time,
var endTime: Time,
var description: String = "",
val id: UUID = UUID.randomUUID()
)
class TestViewModel() : ViewModel() {
companion object {
private const val MILLS = 5_000L
val Factory: ViewModelProvider.Factory = object : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun create(
modelClass: Class,
extras: CreationExtras
): T {
return TestViewModel() as T
}
}
}
val days = mapOf(
LocalDate.parse("2025-06-26") to Day(
date = LocalDate.parse("2025-06-26"),
activeTimeStart = Time(6,0),
activeTimeEnd = Time(22,0)
),
LocalDate.parse("2025-06-27") to Day(
date = LocalDate.parse("2025-06-27"),
activeTimeStart = Time(6,0),
activeTimeEnd = Time(20,30)
)
)
val tasks = mapOf(
LocalDate.parse("2025-06-26") to listOf(
Task(
date = LocalDate.parse("2025-06-26"),
title = "Bis Dahin",
startTime = Time(11,3),
endTime = Time(13,0),
description = "Willkommen bei Gboard! Texte, die Sie kopieren, werden hier gespeichert.",
id = UUID.fromString("b8d9b09b-d18a-4e00-a347-9d388b5c779a")
),
Task(
date = LocalDate.parse("2025-06-26"),
title = "No Let's Go",
startTime = Time(14,56),
endTime = Time(16,55),
description = "Programming Android with Kotlin",
id = UUID.fromString("c68ee93c-7100-4020-9006-c48b8402488d")
)
),
LocalDate.parse("2025-06-27") to listOf(
Task(
date = LocalDate.parse("2025-06-27"),
title = "Hallo Herr Schmidt",
startTime = Time(15,34),
endTime = Time(20,0),
description = "Willkommen bei Gboard! Texte, die Sie kopieren, werden hier gespeichert.",
id = UUID.fromString("14873472-8bb4-43a8-9f5d-a0265a5f8eda")
)
)
)
val userInput = MutableStateFlow(UserInput())
@OptIn(ExperimentalCoroutinesApi::class)
val dayState = userInput.flatMapLatest { input: UserInput ->
Log.i("TaskViewModel", "loading dayState")
val dayFlow = flow {
emit(days.get(input.selectedDate))
}
val tasksFlow = flow {
emit(tasks.get(input.selectedDate))
}
combine(
flow = dayFlow,
flow2 = tasksFlow
) { day, tasks ->
DayState(
date = input.selectedDate,
activeTimeStart = day?.activeTimeStart ?: Time(6, 0),
activeTimeEnd = day?.activeTimeEnd ?: Time(22, 0),
tasks = tasks!!
)
}
}
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = 5000L),
initialValue = DayState()
)
fun setSelectedDate(date: LocalDate) {
Log.i("setSelectedDate", date.toString())
userInput.update {
it.copy(
selectedDate = date
)
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/796 ... ious-value
Указатель в холсте сбрасывает состояние ViewModel до его предыдущего значения ⇐ Android
Форум для тех, кто программирует под Android
1751243401
Anonymous
У меня есть композитный, который использует холст для рисования задач на часовом циферблате. Задачи считываются из состояния ViewModel, которое, в свою очередь, загружает их из базы данных. Список задач варьируется в зависимости от выбранной даты. Когда вы выбираете дату (например, 26 июня) на компоненте календаря, ViewModel загружает задачи на 26 июня и рисует их (рисунок задачи не показан в примере ниже). < /P>
Когда я нажимаю на холм, журнал показывает данные для 26 июня. Если я выберу новую дату (например, 27 июня), задачи для 27 июня загружаются должным образом. Журналы LogCat показывают данные 26 июня (первоначальная загрузка данных), 26 июня данных (после нажатия на холст), 27 июня данных (после выбора 27 июня), а затем снова 26 июня данных (после нажатия на холст), даже если я не выбрал эту дату снова - циферблат определенно был нанесен с правильными данными (для 27 -го июня). < /P>
факт, что является фактом, что это затрудняет. Я ожидаю, что он останется 27 июня, пока я не выберу другую дату. Эта проблема с датой датой, дату, возникает только тогда, когда я нажимаю на циферблат, а затем выбираю другую дату. Если я продолжаю выбирать разные даты без , нажав на циферблат между выбором даты, данные не возвращаются к предыдущей дате самостоятельно.
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.onGloballyPositioned
import kotlin.math.min
import android.util.Log
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.ui.Alignment
import com.example.circularplanner.ui.viewmodel.DayState
import com.example.circularplanner.ui.viewmodel.TaskUiState
import com.example.circularplanner.ui.viewmodel.UserInput
import com.example.circularplanner.utils.TaskDialUtils.square
import java.time.LocalDate
import kotlin.math.sqrt
@Composable
fun TestTaskDial(
dayState: DayState,
userInput: UserInput,
onSetDate: (LocalDate) -> Unit
) {
// The width and height of the Canvas
var width by remember { mutableStateOf(0) }
var height by remember { mutableStateOf(0) }
var touchInsideTheDial by remember { mutableStateOf(false) }
var center by remember { mutableStateOf(Offset.Zero) }
// Basically the width of the finger touch on the screen
var touchStroke: Float = 50f
// The radius of the dial (from the center to the end of the clock steps)
var outerRadius by remember { mutableStateOf(0f) }
Log.i("DDselectedDate", userInput.selectedDate.toString())
Log.i("DDdate", dayState.date.toString())
Log.i("DDtasks", dayState.tasks.joinToString())
fun distance(first: Offset, second: Offset): Float {
return sqrt((first.x - second.x).square() + (first.y - second.y).square())
}
fun checkIfTouchInsideDial(distance: Float, radius: Float, touchStroke: Float): Boolean {
if (distance
val distance = distance(offset, center)
touchInsideTheDial = checkIfTouchInsideDial(
distance,
outerRadius,
touchStroke
)
if (touchInsideTheDial) {
Log.i("TaskDial", "onTap")
Log.i("DDselectedDate", userInput.selectedDate.toString())
Log.i("DDdate", dayState.date.toString())
Log.i("DDtasks", dayState.tasks.joinToString())
}
}
)
}
) {
outerRadius = min(width, height) / 2f * 0.8f
// Draw dial
drawCircle(
color = Color.Cyan,
center = center,
radius = outerRadius,
)
}
Row(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(0.1f),
verticalAlignment = Alignment.Bottom,
horizontalArrangement = Arrangement.SpaceBetween
) {
Button(onClick = { onSetDate(LocalDate.parse("2025-06-26")) }) {
Text("26th June")
}
Button(onClick = { onSetDate(LocalDate.parse("2025-06-27")) }) {
Text("27th June")
}
}
Row (
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(0.1f),
verticalAlignment = Alignment.Bottom,
horizontalArrangement = Arrangement.Center
) {
Text(text = userInput.selectedDate.toString())
}
}
}
< /code>
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.CreationExtras
import com.example.circularplanner.data.Task
import com.example.circularplanner.data.Time
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import java.time.LocalDate
import java.util.UUID
import kotlin.String
typealias Tasks = List
data class DayState (
val date: LocalDate = LocalDate.now(),
val activeTimeStart: Time = Time(6, 0),
val activeTimeEnd: Time = Time(22, 0),
val tasks: Tasks = emptyList()
)
data class UserInput(
val selectedDate: LocalDate = LocalDate.parse("2025-06-26"),
)
data class Day(
val date: LocalDate,
val activeTimeStart: Time,
val activeTimeEnd: Time,
)
data class Time(
var hour: Int = 0,
var minute: Int = 0
)
data class Task (
val date: LocalDate,
var title: String,
var startTime: Time,
var endTime: Time,
var description: String = "",
val id: UUID = UUID.randomUUID()
)
class TestViewModel() : ViewModel() {
companion object {
private const val MILLS = 5_000L
val Factory: ViewModelProvider.Factory = object : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun create(
modelClass: Class,
extras: CreationExtras
): T {
return TestViewModel() as T
}
}
}
val days = mapOf(
LocalDate.parse("2025-06-26") to Day(
date = LocalDate.parse("2025-06-26"),
activeTimeStart = Time(6,0),
activeTimeEnd = Time(22,0)
),
LocalDate.parse("2025-06-27") to Day(
date = LocalDate.parse("2025-06-27"),
activeTimeStart = Time(6,0),
activeTimeEnd = Time(20,30)
)
)
val tasks = mapOf(
LocalDate.parse("2025-06-26") to listOf(
Task(
date = LocalDate.parse("2025-06-26"),
title = "Bis Dahin",
startTime = Time(11,3),
endTime = Time(13,0),
description = "Willkommen bei Gboard! Texte, die Sie kopieren, werden hier gespeichert.",
id = UUID.fromString("b8d9b09b-d18a-4e00-a347-9d388b5c779a")
),
Task(
date = LocalDate.parse("2025-06-26"),
title = "No Let's Go",
startTime = Time(14,56),
endTime = Time(16,55),
description = "Programming Android with Kotlin",
id = UUID.fromString("c68ee93c-7100-4020-9006-c48b8402488d")
)
),
LocalDate.parse("2025-06-27") to listOf(
Task(
date = LocalDate.parse("2025-06-27"),
title = "Hallo Herr Schmidt",
startTime = Time(15,34),
endTime = Time(20,0),
description = "Willkommen bei Gboard! Texte, die Sie kopieren, werden hier gespeichert.",
id = UUID.fromString("14873472-8bb4-43a8-9f5d-a0265a5f8eda")
)
)
)
val userInput = MutableStateFlow(UserInput())
@OptIn(ExperimentalCoroutinesApi::class)
val dayState = userInput.flatMapLatest { input: UserInput ->
Log.i("TaskViewModel", "loading dayState")
val dayFlow = flow {
emit(days.get(input.selectedDate))
}
val tasksFlow = flow {
emit(tasks.get(input.selectedDate))
}
combine(
flow = dayFlow,
flow2 = tasksFlow
) { day, tasks ->
DayState(
date = input.selectedDate,
activeTimeStart = day?.activeTimeStart ?: Time(6, 0),
activeTimeEnd = day?.activeTimeEnd ?: Time(22, 0),
tasks = tasks!!
)
}
}
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(stopTimeoutMillis = 5000L),
initialValue = DayState()
)
fun setSelectedDate(date: LocalDate) {
Log.i("setSelectedDate", date.toString())
userInput.update {
it.copy(
selectedDate = date
)
}
}
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79683934/pointerinput-in-canvas-resets-viewmodels-state-to-its-previous-value[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия