1

I am new to Android Compose and am working on a maintenance project.

The following block of code is where the error is occurring:

@ExperimentalMaterialNavigationApi
@ExperimentalAnimationApi
@ExperimentalMaterialApi
@ExperimentalComposeUiApi
@Composable
fun BottomSheetContent() {
    BaseBottomSheetComposable(showBar = true) {
        Column {
            val otpCtaEnabled = remember { mViewModel.enabledOtpCtaState }
            Text(
                text = stringResource(id = R.string.text_login_otp_title)
                    .plus(" ")
                    .plus(mViewModel.getMobileNumber()),
                style = typography.body1.copy(fontSize = 14.sp, color = angrezi),
                modifier = Modifier.padding(top = 24.dp, start = 16.dp, end = 16.dp)
            )
            val focusRequester = remember { FocusRequester() }
            val editValue = remember { mViewModel.loginOtp }
            val keyboard = LocalSoftwareKeyboardController.current
            TextField(
                value = editValue.value,
                onValueChange = {
                    if (it.length <= OTP_LENGTH) {
                        editValue.value = it
                        mViewModel.onOtpTextChanged(it)
                    }
                    if (it.length == OTP_LENGTH) {
                        keyboard?.hide()
                    }
                },
                modifier = Modifier
                    .size(0.dp)
                    .focusRequester(focusRequester),
                keyboardOptions = KeyboardOptions.Default.copy(
                    keyboardType = KeyboardType.Number
                )
            )
            LaunchedEffect(true) {
                focusRequester.requestFocus()
            }
            Row(
                modifier = Modifier.padding(start = 12.dp, end = 12.dp, top = 8.dp),
                horizontalArrangement = Arrangement.Center
            ) {
                (0 until OTP_LENGTH).map { index ->
                    OtpCell(
                        modifier = Modifier
                            .width(56.dp)
                            .height(56.dp)
                            .padding(horizontal = 4.dp)
                            .clip(RoundedCornerShape(12.dp))
                            .background(MonetGray0)
                            .focusRequester(focusRequester)
                            .clickable {
                                focusRequester.requestFocus()
                                keyboard?.show()
                            },

                        value = editValue.value.getOrNull(index)?.toString() ?: "",
                        isCursorVisible = editValue.value.length == index
                    )
                }
            }
            ButtonPrimary(text = stringResource(id = R.string.text_otp_cta), state = otpCtaEnabled,
                onCtaClick = {
                    mViewModel.onOtpCtaClicked()
                })
            Row(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.Center
            ) {
                OtpRetryText()
                CircularProgressTimer(percentage = 100f, animDuration = COUNT_DOWN_TIME_IN_MILLIS)
            }
        }
    }
}

...

When I run the code, the portion

LaunchedEffect(true) {
                focusRequester.requestFocus()
}

throws a runtime exception with the following stack trace:

AndroidRuntime   E  FATAL EXCEPTION: main
Process: in.myapp.crew, PID: 32709
java.lang.IllegalStateException: Expected BringIntoViewRequester to not be used before parents are placed.
    at androidx.compose.foundation.gestures.ContentInViewModifier.calculateRectForParent(ContentInViewModifier.kt:117)
    at androidx.compose.foundation.relocation.BringIntoViewResponderNode$bringChildIntoView$parentRect$1.invoke(BringIntoViewResponder.kt:160)
    at androidx.compose.foundation.relocation.BringIntoViewResponderNode$bringChildIntoView$parentRect$1.invoke(BringIntoViewResponder.kt:160)
    at androidx.compose.foundation.relocation.BringIntoViewResponder_androidKt$defaultBringIntoViewParent$1.bringChildIntoView(BringIntoViewResponder.android.kt:31)
    at androidx.compose.foundation.relocation.BringIntoViewResponderNode$bringChildIntoView$2$2.invokeSuspend(BringIntoViewResponder.kt:179)
    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@86a65ab, androidx.compose.runtime.BroadcastFrameClock@d899408, StandaloneCoroutine{Cancelling}@4dea7a1, AndroidUiDispatcher@1669dc6]
Process   I  Sending signal. PID: 32709 SIG: 9
---------------------------- PROCESS ENDED (32709) for package in.myapp.crew ----------------------------
---------------------------- PROCESS STARTED (1138) for package in.myapp.crew ----------------------------
---------------------------- PROCESS STARTED (1390) for package in.myapp.crew ----------------------------
---------------------------- PROCESS ENDED (1390) for package in.myapp.crew ----------------------------

I don't see BringIntoViewRequester configured in the program, and the exception doesn't point to any specific line of code or section of the program. There's also no designated "caused by" section in this stack trace.

The app is using the following versions:

  • Gradle: gradle-7.5
  • Kotlin version: 1.8.21
  • Android Gradle plugin: 7.4.2
  • Compose version:
    • androidx.constraintlayout:constraintlayout-compose:1.0.0-rc1
    • androidx.activity:activity-compose:1.3.1
    • androidx.compose.runtime:runtime:1.4.3
    • androidx.compose.ui:ui:1.4.3
    • androidx.compose.foundation:foundation:1.4.3
    • androidx.compose.foundation:foundation-layout:1.4.3
    • androidx.compose.material:material:1.4.3
    • androidx.compose.runtime:runtime-livedata:1.4.3
    • androidx.compose.ui:ui-tooling:1.4.3
    • androidx.compose.ui:ui-viewbinding:1.4.3

Does anyone know what "to not be used before parents are placed" means? Has anyone experienced this before. Any idea why focusRequester does this?

  • You are reusing the same focus requestor in multiple places, that could be a probable reason. – Abhimanyu Jun 17 '23 at 05:07
  • @Abhimanyu I suspected as much. However. Even using that particular FocusRequest method and its function as prescribed by the existing documentation gives me this exception. Which seems very strange to me. Have you perhaps seen this exception before by any chance? – Nitinraj Vallyedath Jun 19 '23 at 05:17

2 Answers2

0

Remove

LaunchedEffect(true) {
  focusRequester.requestFocus()
}

and add

 modifier = Modifier
            ...
            .clickable {
              focusRequester.requestFocus()
              keyboard?.show()
            }
            .onGloballyPositioned { focusRequester.requestFocus() }

it should work!

  • Hi Kumar, I did try out your suggestion. How ever it still crashes. Do you have any idea what does this exception really mean? – Nitinraj Vallyedath Jun 19 '23 at 05:16
  • Okay found your bug! you are using single focus request in many places, first in `TextField` and other in `OtpCell` that is causing this error! you need to add separate focusRequest for each TextFields – Kumar Shashi Jun 19 '23 at 07:04
0

I face the same issue :

In my case, I removed this

implementation 'androidx.compose.foundation:foundation:1.4.3

dependency.Now it works fine.