Reprator
08/24/2020, 7:48 PMAlthough i know the meaning of this error, @Composable invocations can only happen from the context of a @Composable function but not able to understand how should i sort this error, actually i try to show a snackbar, if input is invalid, but it is throwing me the above mentioned error, following is my code,package com.reprator.khatabook_android.ui.login
import android.app.Activity
import android.util.Log
import android.view.inputmethod.InputMethodManager
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.Text
import androidx.compose.foundation.contentColor
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ContextAmbient
import androidx.compose.ui.text.SoftwareKeyboardController
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import androidx.ui.tooling.preview.Preview
import com.reprator.khatabook_android.ui.snackbarAction
import kotlinx.coroutines.delay
@Preview(showBackground = true)
@Composable
fun DefaultPreviewLogin() {
LoginPage()
}
@Composable
fun LoginPage() {
val textValue = remember { mutableStateOf(TextFieldValue()) }
val submit: () -> Unit = {
Log.e("Hi", "Hi")
val text = textValue.value.text
val error: String? = when {
text.isEmpty() -> {
"Please enter phone number"
}
text.length < 10 -> {
"Phone number can't be less than 10"
}
else -> null
}
if (error.isNullOrBlank()) {
} else {
Stack {
ErrorSnackbar(
errorMessage = error,
modifier = Modifier.gravity(Alignment.BottomCenter)
)
}
}
}
Column(
modifier = Modifier.fillMaxSize().padding(15.dp),
verticalArrangement = Arrangement.Center
) {
MaterialTextInputComponent(textValue, submit)
Spacer(modifier = Modifier.preferredHeight(16.dp))
MaterialButtonComponent(submit)
}
}
@Composable
fun MaterialTextInputComponent(textValue: MutableState<TextFieldValue>, buttonClick: () -> Unit) {
OutlinedTextField(
value = textValue.value,
onValueChange = { textFieldValue -> textValue.value = textFieldValue },
keyboardType = KeyboardType.Phone,
imeAction = ImeAction.Done,
label = { Text("Enter Your Phone Number") },
placeholder = { Text(text = "9041866055") },
onImeActionPerformed = { imeAction: ImeAction,
softwareKeyboardController: SoftwareKeyboardController? ->
if (imeAction == ImeAction.Done) {
softwareKeyboardController?.hideSoftwareKeyboard()
buttonClick.invoke()
}
},
modifier = Modifier.fillMaxWidth()
)
}
@Composable
fun MaterialButtonComponent(buttonClick: () -> Unit) {
val context = ContextAmbient.current
Button(
onClick = {
val imm: InputMethodManager =
(context as Activity).getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0)
buttonClick.invoke()
},
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(16.dp),
elevation = 5.dp
) {
Text(text = "Submit", modifier = Modifier.padding(6.dp))
}
}
@OptIn(ExperimentalAnimationApi::class)
@Composable
private fun ErrorSnackbar(
errorMessage: String,
showError: Boolean = !errorMessage.isNullOrBlank(),
modifier: Modifier = Modifier,
onErrorAction: () -> Unit = { },
onDismiss: () -> Unit = { }
) {
launchInComposition(showError) {
delay(timeMillis = 5000L)
if (showError) {
onDismiss()
}
}
AnimatedVisibility(
visible = showError,
enter = slideInVertically(initialOffsetY = { it }),
exit = slideOutVertically(targetOffsetY = { it }),
modifier = modifier
) {
Snackbar(
modifier = Modifier.padding(16.dp),
text = { Text(errorMessage) },
action = {
TextButton(
onClick = {
onErrorAction()
onDismiss()
},
contentColor = contentColor()
) {
Text(
text = "Ok",
color = MaterialTheme.colors.snackbarAction
)
}
}
)
}
}