how to show textfield using focusRequester in lazycolumn?
The screen is composed of Lazycholumn, and the list part shown at the bottom of the capture picture shows the lists using LazyListScope. The boolean value shows the textfield, which is shown at the bottom of the lists shown by LazyListScope. There is no error when there is no LazyListScope or there is a space at the bottom, but this error occurs when the screen at the bottom is full with LazyListScope
when i try to apply this, i have a issue
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.todo_android, PID: 8769
java.lang.IllegalStateException:
FocusRequester is not initialized. Here are some possible fixes:
1. Remember the FocusRequester: val focusRequester = remember { FocusRequester() }
2. Did you forget to add a Modifier.focusRequester() ?
3. Are you attempting to request focus during composition? Focus requests should be made in
response to some event. Eg Modifier.clickable { focusRequester.requestFocus() }
at androidx.compose.ui.focus.FocusRequester.focus$ui_release(FocusRequester.kt:218)
at androidx.compose.ui.focus.FocusRequester.requestFocus(FocusRequester.kt:63)
at com.example.todo_android.screen.CalendarScreenKt$CalendarScreen$2$1.invokeSuspend(CalendarScreen.kt:244)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at androidx.compose.ui.platform.AndroidUiDispatcher.performTrampolineDispatch(AndroidUiDispatcher.android.kt:81)
at androidx.compose.ui.platform.AndroidUiDispatcher.access$performTrampolineDispatch(AndroidUiDispatcher.android.kt:41)
at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.run(AndroidUiDispatcher.android.kt:57)
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7872)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [androidx.compose.ui.platform.MotionDurationScaleImpl@5912b30, androidx.compose.runtime.BroadcastFrameClock@11833a9, StandaloneCoroutine{Cancelling}@4c1ad2e, AndroidUiDispatcher@8cef0cf]
I/Process: Sending signal. PID: 8769 SIG: 9
i did those, that is :
1. val focusRequester = remember { FocusRequester() }
2. Modifier.focusRequester()
3. Modifier.clickable { focusRequester.requestFocus() }
and this is my code
(Except for LazyListScope, I selected only the parts with TextField and brought them.)
LazyColumn(
modifier = Modifier
.fillMaxSize()
.background(Color(0xfff0f0f0)),
verticalArrangement = Arrangement.spacedBy(8.dp),
state = rememberLazyListState()
) {
item {
Column(
modifier = Modifier
.fillMaxSize()
) {
Column(
modifier = Modifier
.shadow(
shape = RoundedCornerShape(bottomStart = 30.dp, bottomEnd = 30.dp),
elevation = 7.dp,
spotColor = Color(0xffB0B0B0),
ambientColor = Color(0xffB0B0B0)
),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
CalendarTitle(yearMonth = selectedDate.yearMonth)
CalendarHeader(daysOfWeek = daysOfWeek)
CalendarContent(
selectedDate = selectedDate,
weekState = weekState,
monthState = monthState,
isMonthMode = animateState.value,
onSelectedDate = {
selectedDate = it
val dayOfWeek =
LocalDate.of(it.year, it.monthValue, it.dayOfMonth).dayOfWeek
dayString = when (dayOfWeek.value) {
1 -> "월요일"
2 -> "화요일"
3 -> "수요일"
4 -> "목요일"
5 -> "금요일"
6 -> "토요일"
7 -> "일요일"
else -> null.toString()
}
scope.launch {
vm.readTodo(token, it.year, it.monthValue, it.dayOfMonth)
}
}
)
}
Row(
modifier = Modifier
.fillMaxWidth()
.padding(start = 21.dp, end = 21.dp, top = 30.dp),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = if (
selectedDate.dayOfMonth.toString().length == 1
) {
"0${selectedDate.dayOfMonth}"
} else {
"${selectedDate.dayOfMonth}"
},
fontSize = 26.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(end = 6.dp)
)
Text(
fontSize = 14.sp,
fontWeight = FontWeight.Medium,
lineHeight = 18.sp,
color = Color(0xff9E9E9E),
text = dayString
)
Divider(
modifier = Modifier
.fillMaxWidth()
.padding(start = 6.dp, top = 1.dp),
color = Color(0xffdddbdb)
)
}
}
}
TodoItem(
vm = vm,
token = token,
categoryList = categoryList,
categoryTodoList = categoryTodoList,
scope = scope
)
item {
LaunchedEffect(isVisibility) {
if (isVisibility) {
focusRequester.requestFocus()
}
}
if (isVisibility) {
Card(
modifier = Modifier
.fillMaxWidth()
.height(45.dp)
.padding(start = 21.dp, end = 21.dp),
colors = CardDefaults.cardColors(Color.White),
shape = RoundedCornerShape(8.dp),
) {
Row(
modifier = Modifier
.padding(
start = 12.dp,
top = 13.dp,
bottom = 13.dp
),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Image(
painter = painterResource(id = R.drawable.blankcheckbox),
contentDescription = null
)
BasicTextField(
modifier = Modifier
.wrapContentWidth()
.wrapContentHeight()
.padding(start = 16.dp)
.imePadding(),
value = todoTitle,
onValueChange = { text ->
vm.setTodoTitle(text)
},
textStyle = androidx.compose.material3.LocalTextStyle.current.copy(
fontSize = 13.sp,
fontStyle = FontStyle.Normal,
color = Color.Black,
lineHeight = 31.sp
),
singleLine = true,
maxLines = 1,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text,
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(onDone = {
scope.launch {
vm.createTodo(
token,
CreateTodo(
todoYear,
todoMonth,
todoDay,
todoTitle,
todoColor
)
)
vm.setTodoTitle("")
isVisibility = !isVisibility
}
})
)
}
}
}
if (todoList.isEmpty() && !isVisibility) {
Row {
BlankTodoItem()
}
}
}
}
and this is a FAB and Card Composable for that is changing valuable(isVisiblity) and showing textfield
@Composable
fun AddTodoFloatingButton(
multiFloatingState: FloatingStateType,
onMultiFloatingStateChange: (FloatingStateType) -> Unit,
backgroundColor: Color,
onButtonClick: (String) -> Unit,
focusRequester: FocusRequester,
) {
val transition = updateTransition(targetState = multiFloatingState, label = null)
val rotate by animateFloatAsState(
targetValue = if (multiFloatingState == FloatingStateType.Expanded) 45f else 0f,
animationSpec = tween(durationMillis = 400) // 여기서 애니메이션 지속 시간을 설정할 수 있습니다.
)
val NextButtonArrowTint = when (multiFloatingState) {
FloatingStateType.Expanded -> {
Color(0xFFFFFFFF).copy(alpha = 1f)
}
FloatingStateType.Collapsed -> {
Color(0xFF424242).copy(alpha = 1f)
}
}
Column(
modifier = Modifier.padding(
end = 20.dp,
bottom = 150.dp
),
horizontalAlignment = Alignment.End
) {
AnimatedVisibility(
visible = (multiFloatingState == FloatingStateType.Expanded),
enter = fadeIn(
animationSpec = tween(500)
) + slideInVertically(
animationSpec = tween(500),
initialOffsetY = {
it / 8
}
),
exit = fadeOut(
animationSpec = tween(500)
) + slideOutVertically(
animationSpec = tween(500),
targetOffsetY = {
it / 8
}
)
) {
FloatingActionButtonMenus(
onMultiFloatingStateChange,
onButtonClick,
focusRequester
)
}
FloatingActionButton(
modifier = Modifier
.padding(bottom = 18.dp)
.size(65.dp)
.shadow(
elevation = 4.dp,
shape = CircleShape,
spotColor = Color(0xff9E9E9E),
ambientColor = Color(0xffACACAC)
),
containerColor = backgroundColor,
shape = CircleShape,
onClick = {
onMultiFloatingStateChange(
if (transition.currentState == FloatingStateType.Expanded) {
FloatingStateType.Collapsed
} else {
FloatingStateType.Expanded
}
)
}) {
Icon(
modifier = Modifier
.rotate(rotate)
.size(32.dp)
.background(Color.Transparent),
painter = painterResource(id = R.drawable.todolistaddemogi),
contentDescription = null,
tint = NextButtonArrowTint
)
}
}
}
@Composable
fun FloatingActionButtonMenus(
onMultiFloatingStateChange: (FloatingStateType) -> Unit,
onButtonClick: (String) -> Unit,
focusRequester: FocusRequester,
) {
Surface(
modifier = Modifier
.width(155.dp)
.height(110.dp)
.padding(bottom = 10.dp)
.shadow(
shape = RoundedCornerShape(20.dp),
elevation = 5.dp,
spotColor = Color(0xff9E9E9E),
ambientColor = Color(0xffACACAC)
)
.background(Color.White)
) {
Column(
modifier = Modifier
.wrapContentSize()
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly
) {
Button(modifier = Modifier.size(width = 25.dp, height = 25.dp),
colors = ButtonDefaults.buttonColors(Color(0xffFFB4B4)),
onClick = {
onButtonClick("1")
onMultiFloatingStateChange(FloatingStateType.Collapsed)
focusRequester.requestFocus()
},
content = {})
Button(modifier = Modifier.size(width = 25.dp, height = 25.dp),
colors = ButtonDefaults.buttonColors(Color(0xffFFDCA8)),
onClick = {
onButtonClick("2")
onMultiFloatingStateChange(FloatingStateType.Collapsed)
focusRequester.requestFocus()
},
content = {})
Button(modifier = Modifier.size(width = 25.dp, height = 25.dp),
colors = ButtonDefaults.buttonColors(Color(0xffB1E0CF)),
onClick = {
onButtonClick("3")
onMultiFloatingStateChange(FloatingStateType.Collapsed)
focusRequester.requestFocus()
},
content = {})
}
Spacer(modifier = Modifier.padding(vertical = 7.dp))
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly
) {
Button(modifier = Modifier.size(width = 25.dp, height = 25.dp),
colors = ButtonDefaults.buttonColors(Color(0xffB7D7F5)),
onClick = {
onButtonClick("4")
onMultiFloatingStateChange(FloatingStateType.Collapsed)
focusRequester.requestFocus()
},
content = {})
Button(modifier = Modifier.size(width = 25.dp, height = 25.dp),
colors = ButtonDefaults.buttonColors(Color(0xffFFB8EB)),
onClick = {
onButtonClick("5")
onMultiFloatingStateChange(FloatingStateType.Collapsed)
focusRequester.requestFocus()
},
content = {})
Button(modifier = Modifier.size(width = 25.dp, height = 25.dp),
colors = ButtonDefaults.buttonColors(Color(0xffB6B1EC)),
onClick = {
onButtonClick("6")
onMultiFloatingStateChange(FloatingStateType.Collapsed)
focusRequester.requestFocus()
},
content = {})
}
}
}
}