Last active
September 29, 2020 07:14
-
-
Save manuelvicnt/7e7c733797ceac9805780d6963b13ec9 to your computer and use it in GitHub Desktop.
Compose BaseTextField crash
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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