Как передать данные в ModalBottomSheet из AppState?Android

Форум для тех, кто программирует под Android
Ответить Пред. темаСлед. тема
Anonymous
 Как передать данные в ModalBottomSheet из AppState?

Сообщение Anonymous »

Я использую модель приложения NowInAndroid для создания собственного приложения.
В верхней панели у меня есть кнопка, и я хочу, чтобы при нажатии на нее открывался ModalBottomSheet для воспроизведения текста, связанного с содержимым, которое в данный момент отображается на экране.
Моя проблема в том, что я не знаю, как получить этот текст или где лучше всего это сделать это, применяя чистую архитектуру.
Прошу прощения за многословие, но я хочу объяснить контекст как можно яснее.
Изначально , я показываю, как получается в ViewModel путем вызова UseCase:

Код: Выделить всё

@HiltViewModel
class UniversalisViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle,
val userDataRepository: UserDataRepository,
getTopicWithDate: GetUniversalisUseCase,
) : ViewModel() {

//...

val uiState: StateFlow = combine(
selectedTopicId,
getTopicWithDate(
sortBy = HomeSortField.ID,
date = Utils.hoy.toInt(),
topicId = selectedTopicId.value!!.toInt()
),
UniversalisUiState::UniversalisData,
).stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = UniversalisUiState.Loading,
)

//...
}

sealed interface UniversalisUiState {
data object Loading : UniversalisUiState
data object Error : UniversalisUiState

data class UniversalisData(
val selectedTopicId: String?,
val topics: List,
) : UniversalisUiState

data object Empty : UniversalisUiState
}
Я передаю ViewModel в качестве параметра маршрута, чтобы затем работать с UiState:

Код: Выделить всё

fun UniversalisRoute(
showBackButton: Boolean,
onBackClick: () -> Unit,
modifier: Modifier = Modifier,
viewModel: UniversalisViewModel = hiltViewModel(),
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
UniversalisScreen(
uiState = uiState,
modifier = modifier,
onReaderClick = viewModel::onReaderClick,
onBackClick = onBackClick,
)

//
}

Код: Выделить всё

UniversalisScreen
— это экран, отвечающий за отображение контента, видимого пользователю. Следует отметить, что этот контент хоть и совпадает с тем, который необходимо читать голосом в TTS, но имеет другой формат на экране, например, применение стилей, размеров текста и т. д. То есть тот же контент обрабатывается двумя разными способами: один для отображения на экране с форматированием, а другой для чтения голосом без формата и применения в этом случае некоторых замен символов для адаптации к голосовому чтению.
Это часть UniversalisScreen, которая отображает данные на экране:

Код: Выделить всё

if (uiState.topics.isNotEmpty()) {
universalisBody(
name = Utils.capitalize(LiturgyHelper.liturgyByType(uiState.selectedTopicId!!.toInt())),
description = uiState.topics[0].data[0].fecha,
universalis = uiState,
)
}
В UniversalisBody у меня есть следующее:

Код: Выделить всё

private fun LazyListScope.universalisBody(
name: String,
description: String,
universalis: UniversalisUiState.UniversalisData,

) {
item {
UniversalisHeader(name, description)
}
universalisResourceCards(universalis)
}
И в UniversalisResourceCards:

Код: Выделить всё

private fun LazyListScope.universalisResourceCards(
universalis: UniversalisUiState,
) {
when (universalis) {
is UniversalisUiState.UniversalisData -> {
universalisResourceCardItems(
items = universalis.topics,
topicId = universalis.selectedTopicId,
itemModifier = Modifier.padding(24.dp),
)
}
// ...
}
}
Из UniversalisResourceCardItems я вызываю одну функцию UniversalisResourceCardExpanded, в которой необходимо провести дифференциацию данных, которые были получены в репозитории.

Код: Выделить всё

@Composable
fun UniversalisResourceCardExpanded(
universalisResource: List,
modifier: Modifier = Modifier,
topicId: String?,
) {
Card(
shape = RoundedCornerShape(16.dp),
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface),
) {
Column {
Box(
modifier = Modifier.padding(16.dp),
) {
Column {
Spacer(modifier = Modifier.height(12.dp))
Row {
var title: String
topicId!!.toInt().let {
title = when {
it == 20 -> {
val sancti = universalisResource[0].data[0].liturgia!!.liturgiaTypus as Alteri.Sancti
sancti.sanctus.monthName
}

else -> {
universalisResource[0].data[0].liturgia!!.tempus!!.externus.toString()
}
}
}
UniversalisResourceTitle(
title,
modifier = Modifier.fillMaxWidth((.8f)),
)
Spacer(modifier = Modifier.weight(1f))
}
Spacer(modifier = Modifier.height(14.dp))
Row(verticalAlignment = Alignment.CenterVertically) {
UniversalisResourceMetaData(universalisResource[0].data[0].liturgia!!.nomen)
}
Spacer(modifier = Modifier.height(14.dp))
var data = universalisResource[0].data[0]
Universalis(data, topicId = topicId, universalisResource[0].dynamic)
}
}
}
}
}
Как видите, после дифференцирования для получения заголовка я вызываю компонуемый элемент Universalis, в котором будут вызываться разные экраны, в зависимости от класса данных параметра< /код>

Код: Выделить всё

Universalis(data, topicId = topicId, universalisResource[0].dynamic)
Чтобы получить представление о том, что есть в Universalis:

Код: Выделить всё

@Composable
fun Universalis(data: Universalis, topicId: String?, userData: UserDataDynamic) {
val itemId = topicId!!.toInt()
val onTap = { point: Offset -> }
if (data.liturgia!!.liturgiaTypus is Sortable) {
data.liturgia!!.liturgiaTypus?.sort()
}

/*
This is a test, which works.
What I need is to call the screen that will read TTS
in a ModalBottomSheet, when the button that is loaded
from the start in AppState is pressed.
*/

if (userData.useVoiceReader) {
TextToSpeechScreen(data.getAllForRead())
}

/*
These are the different screens that the user will see,
depending on the type of data parameter
*/

when (itemId) {
1 -> MixtusScreen(
data = data.liturgia!!.liturgiaTypus as LHMixtus,
calendarTime = data.timeFK,
userData = userData,
onTap = onTap
)

2 -> OfficiumScreen(
data = data.liturgia!!.liturgiaTypus as LHOfficium,
calendarTime = data.timeFK,
userData = userData,
onTap = onTap
)
//
}
}
Извините за длинное объяснение, цель состоит в том, чтобы максимально прояснить контекст.
Попытка, которую я предпринял, чтобы отобразить ModalBottomSheet< /code> при нажатии на кнопку действие с событием onReaderClick передавалось на верхнюю панель.

Код: Выделить всё

NiaTopAppBar(
// ...
readerIcon = NiaIcons.Reader,
onReaderClick = {
showBottomSheet = true
appState.textToRead //I can see "Lorem ipsum" here
},
)
В качестве теста я передал репозиторий в качестве параметра классу NiaAppState и создал переменную textToRead

Код: Выделить всё

@Stable
class NiaAppState(
val navController: NavHostController,
coroutineScope: CoroutineScope,
val windowSizeClass: WindowSizeClass,
networkMonitor: NetworkMonitor,
universalisRepository: UniversalisRepository,
timeZoneMonitor: TimeZoneMonitor,
) {
//...
val shouldRead = universalisRepository.getReader()
}
Мой тест работает, если я помещу в репозиторий такой метод:

Код: Выделить всё

override fun getReader():String{
return "Lorem ipsum"
}
Но мне нужно подготовить данные для голосового чтения из экземпляра, уже созданного в компоновке Universalis, вызвав метод getAllForRead() этого экземпляра.
Моя проблема в том, что я не знаю, как это сделать, применяя чистую архитектуру в стиле Compose.

Подробнее здесь: https://stackoverflow.com/questions/789 ... m-appstate
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Android»