Skip to content

Instantly share code, notes, and snippets.

@gildor
Created August 25, 2020 07:39
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gildor/82ec960cc0c5873453f024870495eab3 to your computer and use it in GitHub Desktop.
Save gildor/82ec960cc0c5873453f024870495eab3 to your computer and use it in GitHub Desktop.
Jetpack Compose Scaffold with snackbar example
package ru.gildor.compose.sandbox
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.Modifier
import androidx.compose.ui.graphics.Color
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 kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterialApi::class)
@Preview(showBackground = true)
@Composable
fun DefaultPreviewLogin() {
val state = rememberScaffoldState()
Scaffold(
scaffoldState = state,
bodyContent = {
LoginPage(state)
},
)
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun LoginPage(state: ScaffoldState) {
val textValue = remember { mutableStateOf(TextFieldValue()) }
val scope = rememberCoroutineScope()
val submit: () -> Unit = {
scope.launch {
val error = when (textValue.value.text.length) {
0 -> "Please enter phone number"
in 0..10 -> "Phone number can't be less than 10"
else -> ""
}
if (error.isNotEmpty()) {
Log.d("AAAA", "Error!")
when (state.snackbarHostState.showSnackbar(error, actionLabel = "Ok")) {
SnackbarResult.Dismissed -> Log.d("AAAA", "Dismissed")
SnackbarResult.ActionPerformed -> Log.d("AAAA", "Action!")
}
} else {
Log.d("AAAA", "Success!")
}
}
}
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()
}
},
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()
},
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",
)
}
}
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment