Skip to content

Instantly share code, notes, and snippets.

@manuelvicnt
Last active September 29, 2020 07:14
Show Gist options
  • Save manuelvicnt/7e7c733797ceac9805780d6963b13ec9 to your computer and use it in GitHub Desktop.
Save manuelvicnt/7e7c733797ceac9805780d6963b13ec9 to your computer and use it in GitHub Desktop.
Compose BaseTextField crash
// SNAPSHOT used: 6868130
// Libraries used:
// androidx.compose.navigation:navigation:0.1.0-SNAPSHOT
// androidx.compose.material:material-icons-extended:1.0.0-SNAPSHOT
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.animate
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.spring
import androidx.compose.foundation.AmbientContentColor
import androidx.compose.foundation.BaseTextField
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Icon
import androidx.compose.foundation.Text
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.BackdropScaffold
import androidx.compose.material.BottomAppBar
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.MaterialTheme
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.AccountCircle
import androidx.compose.material.icons.outlined.Home
import androidx.compose.material.icons.outlined.Search
import androidx.compose.material.icons.outlined.ShoppingCart
import androidx.compose.navigation.NavHost
import androidx.compose.navigation.composable
import androidx.compose.navigation.navigate
import androidx.compose.navigation.rememberNavController
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.savedinstancestate.savedInstanceState
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.VectorAsset
import androidx.compose.ui.layout.positionInParent
import androidx.compose.ui.onGloballyPositioned
import androidx.compose.ui.platform.DensityAmbient
import androidx.compose.ui.platform.setContent
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.ui.tooling.preview.Preview
import java.lang.IllegalStateException
class MainActivity : ComponentActivity() {
@OptIn(ExperimentalFoundationApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
ApiReview()
}
}
}
}
data class BottomBarItem(val name: String, val icon: VectorAsset)
val screens = listOf("Home", "Search", "Shop", "Profile")
val bottomBarItems = screens.mapIndexed { index, screen ->
val icon = when (index) {
0 -> Icons.Outlined.Home
1 -> Icons.Outlined.Search
2 -> Icons.Outlined.ShoppingCart
3 -> Icons.Outlined.AccountCircle
else -> throw IllegalStateException()
}
BottomBarItem(screen, icon)
}
@ExperimentalFoundationApi
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun ApiReview() {
val navController = rememberNavController()
var tabSelected by savedInstanceState { 0 }
BackdropScaffold(
appBar = {
AnimatedTopBar(tabSelected) { newScreen ->
tabSelected = newScreen
navController.navigate(screens[newScreen])
}
},
backLayerContent = {
Box(Modifier.fillMaxSize()) {
val scaffoldModifier = Modifier.padding(4.dp)
NavHost(navController, startDestination = screens[0]) {
composable(screens[0]) { Home(scaffoldModifier) }
composable(screens[1]) { Search(scaffoldModifier) }
composable(screens[2]) { Shop(scaffoldModifier) }
composable(screens[3]) { Profile(scaffoldModifier) }
}
}
}
) {
Text("Hi there!")
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun Home(modifier: Modifier = Modifier) {
Column {
var textFieldState by remember { mutableStateOf(TextFieldValue(text = "hint")) }
BaseTextField(
value = textFieldState,
onValueChange = {
textFieldState = it
}
)
Text("Home", modifier)
}
}
@Composable
fun Search(modifier: Modifier = Modifier) {
Text("Search", modifier)
}
@Composable
fun Shop(modifier: Modifier = Modifier) {
Text("Shop", modifier)
}
@Composable
fun Profile(modifier: Modifier = Modifier) {
Text("Profile", modifier)
}
@OptIn(ExperimentalAnimationApi::class)
@Composable
fun AnimatedTopBar(selectedTab: Int, onTabChanged: (Int) -> Unit) {
var borderSize by remember { mutableStateOf(IntSize(0, 0)) }
var selectedXPosition by remember { mutableStateOf(0f) }
TopAppBar {
Box(Modifier.align(Alignment.CenterVertically), alignment = Alignment.Center) {
with(DensityAmbient.current) {
Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
val padding = 20.dp
Spacer(
Modifier.padding(
start = animate(
(selectedXPosition.toDp() - padding).coerceAtLeast(0.dp),
spring(stiffness = 130f)
)
)
)
Box(
Modifier
.border(
BorderStroke(2.dp, AmbientContentColor.current),
RoundedCornerShape(16.dp)
)
.size(
borderSize.width.toDp() + padding * 2,
borderSize.height.toDp() + 12.dp
).animateContentSize(spring(stiffness = 130f))
)
}
}
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically
) {
bottomBarItems.mapIndexed { index, item ->
val isSelected = selectedTab == index
val alpha = if (isSelected) 1f else 0.6f
Row(Modifier
.clickable {
onTabChanged(index)
}
.padding(horizontal = if (isSelected) 32.dp else 0.dp)
.onGloballyPositioned { coordinates ->
if (isSelected) {
borderSize = coordinates.size
selectedXPosition = coordinates.positionInParent.x
}
}
.animateContentSize()
) {
Icon(
item.icon,
tint = AmbientContentColor.current.copy(alpha = alpha)
)
AnimatedVisibility(isSelected) {
Text(item.name, Modifier.padding(horizontal = 8.dp))
}
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment