我试图在 Jetpack compose 中创建一个示例选项卡视图,因此结构将类似于在父选项卡行内部,我们正在迭代选项卡标题并创建选项卡可组合项。
更精确的代码将是这样的。
@OptIn(ExperimentalPagerApi::class)
@Composable
private fun MainApp() {
Scaffold(
topBar = {
TopAppBar(
title = { Text(stringResource(R.string.app_name)) },
backgroundColor = MaterialTheme.colors.surface
)
},
modifier = Modifier.fillMaxSize()
) { padding ->
Column(Modifier.fillMaxSize().padding(padding)) {
val pagerState = rememberPagerState()
val coroutineScope = rememberCoroutineScope()
val tabContents = listOf(
"Home" to Icons.Filled.Home,
"Search" to Icons.Filled.Search,
"Settings" to Icons.Filled.Settings
)
HorizontalPager(
count = tabContents.size,
state = pagerState,
contentPadding = PaddingValues(horizontal = 32.dp),
modifier = Modifier
.weight(1f)
.fillMaxWidth()
) { page ->
PagerSampleItem(
page …Run Code Online (Sandbox Code Playgroud) android kotlin android-jetpack-compose jetpack-compose-accompanist compose-recomposition
我正在尝试创建一个覆盖层并将视图附加到 WindowManager,我已经通过创建一个实现 Lifecycle/ViewModelStore/SavedStateRegistry Owner 的类来设法做到这一点。\n但由于某种原因,每当我尝试显示对话框/更改时以任何方式使用 MutableState 或 MutableStateFlow 重组的 UI 都不会触发。
\n有没有人尝试过做这样的事情并设法找到触发重组的解决方案?
\n这就是我尝试创建和插入视图的方式:
\n@SuppressLint("InflateParams")\nfun showOverlay() {\n synchronized(lock) {\n if (overlay != null || overlay?.parent != null) {\n return\n }\n val viewModel = OverlayViewModel(context.applicationContext as Application)\n var scope: CoroutineScope? = null\n overlay = ComposeView(context).apply {\n setContent {\n Overlay(viewModel)\n }\n }\n drawOverLifecycleOwner = DrawOverLifecycleOwner()\n drawOverLifecycleOwner?.attachToDecorView(overlay)\n val params =\n WindowManager.LayoutParams(\n WindowManager.LayoutParams.MATCH_PARENT,\n WindowManager.LayoutParams.MATCH_PARENT,\n WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,\n WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,\n PixelFormat.TRANSLUCENT\n )\n params.gravity = Gravity.TOP or Gravity.START\n Log.i("ScreenLocker", "Inserting overlay")\n ContextCompat.getMainExecutor(context).execute {\n …Run Code Online (Sandbox Code Playgroud) android kotlin android-jetpack-compose compose-recomposition
这是导致无限重组问题的代码
主要活动
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
val viewModel : MainViewModel by viewModel()
val state by viewModel.state.observeAsState()
NavHost(navController = navController, startDestination = "firstScreen") {
composable("firstScreen") { FirstScreen(
navigate = {
navController.navigate("secondScreen")
}, updateState = {
viewModel.getState()
},
state
)}
composable("secondScreen") { SecondScreen() }
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
视图模型
class MainViewModel : ViewModel() {
//var state = MutableStateFlow(0)
private val _state = MutableLiveData(0)
val state: LiveData<Int> = _state
fun …Run Code Online (Sandbox Code Playgroud) android kotlin android-jetpack-compose jetpack-compose-navigation compose-recomposition
我认为我在这里缺少 Jetpack Compose 的核心概念。non-constructor data class property当我尝试更改可组合项的内部且此可组合项是观察列表的一部分时,我遇到了问题。
不起作用:(sadProperty未在构造函数中声明)
data class IntWrapper(val actualInt: Int = 0) {
var sadProperty: Int = 0
}
@Preview
@Composable
fun test() {
var state by remember { mutableStateOf(listOf(IntWrapper(1), IntWrapper(2), IntWrapper(3),IntWrapper(4)))}
fun onClick(item: IntWrapper) {
val indexOf = state.indexOf(item)
val newState = state.minus(item).toMutableList()
val copy = item.copy()
copy.sadProperty = Random.nextInt()
newState.add(indexOf, copy)
state = newState
}
Column() {
for (item in state) {
Text("ac: ${item.actualInt} sad: ${item.sadProperty}", modifier = Modifier.clickable { onClick(item)}) …Run Code Online (Sandbox Code Playgroud) android kotlin data-class android-jetpack-compose compose-recomposition
假设我们有以下代码。它显示一个按钮,当用户单击它时,该按钮就会消失。
@Composable
fun ButtonThatDisappearsOnClick() {
var showButton by remember { mutableStateOf(true) }
if (showButton) {
Button(onClick = {
check(showButton) { "onClick shouldn't be called for a hidden button" } // !!!
showButton = false
}) {
Text("My button")
}
}
}
Run Code Online (Sandbox Code Playgroud)
我怀疑check如果用户快速单击按钮两次,上面的调用可能会失败:
shouldShowButton设置为false。由于可变状态下的值已更新,因此安排了重组。onClick函数将第二次触发,并且check调用将失败。我无法在实践中重现这一点,所以我想知道这种行为是否确实可能。
android race-condition kotlin android-jetpack-compose compose-recomposition
我有一个存储在Viewmodelvia内的列表Stateflow。
class FirstSettingViewModel : ViewModel() {
private val _mRoomList = MutableStateFlow<List<InitRoom>>(mutableListOf())
val mRoomList: StateFlow<List<InitRoom>> = _mRoomList
...
Run Code Online (Sandbox Code Playgroud)
我通过 观察流程collectAsState()。它LazyColumn由可以单击的框组成。
val roomList = mViewModel.mRoomList.collectAsState()
Dialog {
...
LazyColumn(...) {
items(roomList.value, key = { room -> room.room_seq}) { room ->
Box(Modifier.clickable {
**mViewModel.selectItem(room)**
}) {...}
}
}
}
Run Code Online (Sandbox Code Playgroud)
当单击事件发生时,viewModel 通过复制列表更改“isSelected”值,如下所示。
fun selectItem(room: InitRoom) = viewModelScope.launch(Dispatchers.IO) {
try {
val cpy = mutableListOf<InitRoom>()
mRoomList.value.forEach {
cpy.add(it.copy())
}
cpy.forEach {
it.isSelected = it.room_seq == room.room_seq
} …Run Code Online (Sandbox Code Playgroud) android android-jetpack-compose kotlin-stateflow lazycolumn compose-recomposition
我认为这是一个奇怪的情况。Textfields我正在显示a 中的列表LazyColoumn。用户可以删除每个文本字段,但这样做时,它会复制 REPLACE 文本字段中的值。
发生了什么:
我添加了 3 个人:第 1 人、第 2 人、第 3 人
我单击“删除人员 2”。
人员 3 现在位于人员 2 的位置(参见名称),但复制了人员 2 的 VALUE。
我这样管理状态:
private val peopleStateFlow = MutableStateFlow<List<Person>>()
Run Code Online (Sandbox Code Playgroud)
我像这样加载该列:
val peopleState = viewModel.peopleState.collectAsState()
LazyColumn {
val peopleStateSnap = peopleState.value
items(peopleStateSnap.size) { index ->
val person = peopleStateSnap[index]
ParticipantView(
person = person,
sharedOwed = sharedOwed.value,
onChangeListener = {
viewModel.updateOwed(person, it)
},
onRemoveClicked = {
viewModel.removePerson(person)
})
}
}
Run Code Online (Sandbox Code Playgroud)
我这样删除这个人:
fun removePerson(person: Person) {
val indexOf …Run Code Online (Sandbox Code Playgroud) android kotlin android-jetpack-compose lazycolumn compose-recomposition
在 Android 中,我经常想要导航以响应 ViewModel 的状态更改。(例如,成功的身份验证会触发导航到用户的主屏幕。)
最佳实践是从 ViewModel 内触发导航吗?是否有有意的机制来触发可组合项中的导航以响应 ViewModel 状态更改?
使用 Jetpack Compose 处理此用例的过程并不明显。如果我尝试类似以下示例的操作,将会发生导航,但我导航到的目的地将无法正常运行。我相信这是因为在调用导航之前不允许完成原始的可组合函数。
// Does not behave correctly.
@Composable fun AuthScreen() {
val screenState = viewModel.screenState.observeAsState()
if(screenState.value is ScreenState.UserAuthenticated){
navController.navigate("/gameScreen")
} else {
LoginScreen()
}
}
Run Code Online (Sandbox Code Playgroud)
如果我使用 LaunchedEffect ,我确实会观察到正确的行为,如下所示:
// Does behave correctly.
@Composable fun AuthScreen() {
val screenState = viewModel.screenState.observeAsState()
if(screenState.value is ScreenState.UserAuthenticated){
LaunchedEffect(key1 = "test") {
navController.navigate("$/gameScreen")
}
} else {
LoginScreen()
}
}
Run Code Online (Sandbox Code Playgroud)
它是否正确?LaunchedEffect 的文档说明如下,但我并不是 100% 清楚其含义:
当 LaunchedEffect 进入组合时,它将启动块到组合的 CoroutineContext 中。当 LaunchedEffect 用不同的 key1、key2 或 …
android android-jetpack-compose jetpack-compose-navigation compose-recomposition
@Composable
fun getData() {
var wordData = arrayListOf<Word>()
db.get().addOnSuccessListener { documents ->
for (document in documents) {
wordData.add(document.toObject(Word::class.java))
}
}
LazyColumn {
items(wordData) { word ->
WordCard(word = word)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我想使用 Lazy Column 显示我所有的单词数据,这些是我的 WordCard 代码。
@Composable
fun WordCard(word: Word) {
Text(text = word.word, color = Color.Black, modifier = Modifier.background(Color.Gray).padding(12.dp))
}
Run Code Online (Sandbox Code Playgroud) android kotlin android-jetpack-compose lazycolumn compose-recomposition
我有一个对话框,当我按下按钮时我无法关闭这是我的代码,我相信这是用于 if 循环的,但我需要它在这种情况下使其成为现实,有什么想法可以帮助我吗?
\n@Composable\n fun PopupWindowDialog(\n parentUiState: ParentHomeUiState,\n) {\n val openDialog = remember { mutableStateOf(false) }\n var sliderPosition by remember { mutableStateOf(0f) }\n\n if (!parentUiState.showInAppFeedback){\n openDialog.value = true\n }\n val recommend = sliderPosition.toInt()\n Column(\n ) {\n Box {\n if (openDialog.value) {\n Dialog(\n onDismissRequest = { openDialog.value = false },\n properties = DialogProperties(),\n ){\n Box(\n Modifier\n .fillMaxWidth()\n .fillMaxHeight()\n //.padding(vertical = 70.dp, horizontal = 10.dp)\n .padding(vertical = 70.dp )\n .background(Color.White, RoundedCornerShape(10.dp))\n //.border(1.dp, color = Color.Black, RoundedCornerShape(20.dp))\n .border(1.dp, color = Color.White, RoundedCornerShape(20.dp))\n …Run Code Online (Sandbox Code Playgroud) android kotlin android-jetpack-compose compose-recomposition