-
-
Notifications
You must be signed in to change notification settings - Fork 5
Android Jetpack Compose
Important
ВНИМАНИЕ!
ЭТОТ РАЗДЕЛ БОЛЬШЕ НЕ ПОДДЕРЖИВАЕТСЯ!
РОАДМАП ПЕРЕЕХАЛ В NOTION
Compose
Cовременный декларативный набор инструментов для создания Android UI. Упрощает проектирование, связанное с созданием и обновлением UI. Сразу в compile time отображается на preview, compose берет на себя отрисовку компонентов, если они поменялись
Accompanist
Группа библиотек, дополняющие Jetpack Compose функциями, которые требуются разработчикам, но пока недоступны
CompositionLocal
collectAsStateWithLifecycle()
Предоставляет последнее значение из StateFlow с учетом жизненного цикла.
Modifier
.padding(0.dp)
.fillMaxSize()
.fillMaxWidth()
.fillMaxHeight()
.verticalScroll(rememberScrollState())
.clip(MaterialTheme.shapes.small)
.background(MaterialTheme.colorScheme.background)
.statusBarsPadding()
.clickable {}
.width(0.dp)
.height(0.dp)
.wrapContentHeight()
.pointerInput(Unit) { detectTapGestures { offset -> } }
Scaffold(
modifier = Modifier,
scaffoldState = ,
topBar = {},
bottomBar = {},
snackbarHost = {},
floatingActionButton = {},
floatingActionButtonPosition = FabPosition.End,
isFloatingActionButtonDocked = false,
backgroundColor = MaterialTheme.colorScheme.background,
contentColor = MaterialTheme.colorScheme.content
) { paddingValues ->
}
TopAppBar(
title = {},
navigationIcon = {
IconButton(
onClick = {
onNavigationIconClick()
}
) {
Icon(
painter = painterResource(R.drawable.icon),
contentDescription = null,
)
}
},
actions = {},
backgroundColor = MaterialTheme.colorScheme.background,
contentColor = MaterialTheme.colorScheme.content,
elevation = 0.dp
)
Box(
modifier = Modifier,
contentAlignment = Alignment.Center,
propagateMinConstraints = false
) {
}
Row(
modifier = Modifier,
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically
) {
}
Column(
modifier = Modifier,
verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.CenterHorizontally
) {
}
LazyColumn(
modifier = Modifier,
state = rememberLazyListState(),
contentPadding = PaddingValues(0.dp),
reverseLayout = false,
verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.Start,
flingBehavior = ScrollableDefaults.flingBehavior(),
userScrollEnabled = true
) {
items()
}
Card(
modifier = Modifier,
shape = ,
backgroundColor = MaterialTheme.colors.background,
contentColor = MaterialTheme.colors.content,
border = ,
elevation = 1.dp
) {
}
Text(
text = stringResource(R.string.text),
modifier = Modifier,
color = MaterialTheme.colorScheme.primary,
fontSize = 16.sp,
fontStyle = FontStyle.Normal,
fontWeight = FontWeight.W400,
fontFamily = FontFamily.Serif,
textAlign = TextAlign.Center,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
style = MaterialTheme.typography.titleLarge
)
Текст фиксированной высоты + gravity center_vertical
Text(
text = "Text",
modifier = Modifier
.constrainAs(anyText) {
width = Dimension.wrapContent
height = Dimension.value(48.dp)
start.linkTo(parent.start)
top.linkTo(parent.top)
}
.wrapContentHeight(Alignment.CenterVertically)
)
var titleText: String by remember { mutableStateOf("") }
val focusManager: FocusManager = LocalFocusManager.current
val focusRequester: FocusRequester = remember { FocusRequester() }
val keyboardController: SoftwareKeyboardController? = LocalSoftwareKeyboardController.current
var passwordVisible: Boolean by rememberSaveable { mutableStateOf(false) }
TextField(
value = titleText,
onValueChange = { value: String ->
titleText = value.take(20)
},
modifier = Modifier
.focusRequester(focusRequester),
label = {
Text(
text = stringResource(R.string.label)
)
},
trailingIcon = {
AnimatedVisibility(
visible = password.isNotEmpty(),
enter = fadeIn(),
exit = fadeOut()
) {
IconButton(
onClick = {
passwordVisible = !passwordVisible
}
) {
Icon(
imageVector = if (passwordVisible) MoviesIcons.Visibility else MoviesIcons.VisibilityOff,
contentDescription = null
)
}
}
},
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text,
imeAction = ImeAction.Next
),
keyboardActions = KeyboardActions(
onDone = {
focusManager.moveFocus(FocusDirection.Down)
keyboardController?.hide()
}
),
maxLines = 1,
colors = TextFieldDefaults.textFieldColors(
textColor = MaterialTheme.colorScheme.primary,
backgroundColor = MaterialTheme.colorScheme.primary,
cursorColor = MaterialTheme.colorScheme.primary,
focusedIndicatorColor = MaterialTheme.colorScheme.primary,
unfocusedIndicatorColor = MaterialTheme.colorScheme.primary,
focusedLabelColor = MaterialTheme.colorScheme.primary,
unfocusedLabelColor = MaterialTheme.colorScheme.primary
)
)
Icon(
imageVector = Icons.Filled.Info,
contentDescription = null,
modifier = Modifier,
tint = Color.Unspecified
)
Icon(
painter = painterResource(R.drawable.icon),
contentDescription = null,
modifier = Modifier,
tint = Color.Unspecified
)
Image(
imageVector = Icons.Filled.Info,
contentDescription = null,
modifier = Modifier,
alignment = Alignment.Center,
contentScale = ContentScale.Fit,
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.primary)
)
Image(
painter = painterResource(R.drawable.icon),
contentDescription = null,
modifier = Modifier,
alignment = Alignment.Center,
contentScale = ContentScale.Fit,
alpha = 1F,
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.primary)
)
AsyncImage(
model = ImageRequest.Builder(context)
.data(imageUrl)
.crossfade(true)
.build(),
contentDescription = null,
modifier = Modifier
.size(24.dp)
.clip(CircleShape)
.border(
width = 1.dp,
color = MaterialTheme.colorScheme.onPrimaryContainer,
shape = CircleShape
),
onState = { state -> },
contentScale = ContentScale.Crop
)
Button(
onClick = {},
modifier = Modifier,
enabled = true,
colors = ButtonDefaults.buttonColors(
backgroundColor = MaterialTheme.colors.background,
contentColor = MaterialTheme.colors.content,
disabledBackgroundColor = MaterialTheme.colors.background,
disabledContentColor = MaterialTheme.colors.content
),
contentPadding = PaddingValues(
horizontal = 0.dp,
vertical = 0.dp
)
) {
Text(
text = stringResource(R.string.text).uppercase(),
)
}
OutlinedButton(
onClick = {},
modifier = Modifier,
enabled = true,
elevation = ,
shape = ,
border = ,
colors = ,
contentPadding = ,
) {
Text(
text = stringResource(R.string.text)
)
}
IconButton(
onClick = {},
modifier = Modifier,
enabled = true
) {
}
Switch(
checked = true,
onCheckedChange = null,
modifier = Modifier,
enabled = true,
colors =
)
RadioButton(
selected = true,
onClick = {},
colors = RadioButtonDefaults.colors(
selectedColor = MaterialTheme.colorScheme.primary,
unselectedColor = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.6F)
),
modifier = Modifier
)
Slider(
value = sliderPosition,
onValueChange = { position ->
sliderPosition = position
},
modifier = Modifier,
valueRange = 0F..10000F,
steps = 9,
onValueChangeFinished = {
onDelayChangeFinished(sliderPosition.roundToInt())
},
colors = SliderDefaults.colors(
inactiveTrackColor = MaterialTheme.colorScheme.outline,
inactiveTickColor = MaterialTheme.colorScheme.onPrimary
)
)
CircularProgressIndicator(
modifier = Modifier,
color = MaterialTheme.colorScheme.primary,
strokeWidth = 1.dp
)
Divider(
modifier = Modifier,
color = MaterialTheme.colorScheme.divider,
thickness = 1.dp,
startIndent = 0.dp
)
val dialog: MutableState<Boolean> = remember { mutableStateOf(false) }
AlertDialog(
onDismissRequest = {
dialog.value = false
},
confirmButton = {
TextButton(
onClick = {
dialog.value = false
},
) {
Text(
text = stringResource(R.string.cancel),
color = MaterialTheme.colorScheme.primary,
style = MaterialTheme.typography.labelLarge
)
}
},
icon = {
Icon(
painter = painterResource(R.drawable.icon),
contentDescription = null
)
},
title = {
Text(
text = stringResource(R.string.title),
color = MaterialTheme.colorScheme.onSurface,
style = MaterialTheme.typography.headlineSmall
)
},
text = {},
shape = RoundedCornerShape(28.dp),
containerColor = MaterialTheme.colorScheme.surface,
iconContentColor = MaterialTheme.colorScheme.secondary,
titleContentColor = MaterialTheme.colorScheme.onSurface,
properties = DialogProperties(
dismissOnBackPress = true,
dismissOnClickOutside = false
)
)
val confirmDialog: MutableState<Boolean> = remember { mutableStateOf(false) }
if (confirmDialog.value) {
AlertDialog(
onDismissRequest = {
confirmDialog.value = false
},
) {
Column(
modifier = Modifier.background(MaterialTheme.colorScheme.dialogBackground)
) {
Text(
text = stringResource(R.string.text),
modifier = Modifier.padding(16.dp)
)
Row(
modifier = Modifier
.fillMaxWidth()
.padding(end = 16.dp),
horizontalArrangement = Arrangement.End
) {
TextButton(
onClick = {
confirmDialog.value = false
},
textRes = R.string.button_positive
)
MainTextButton(
onClick = {
confirmDialog.value = false
},
textRes = R.string.button_negative
)
}
}
}
}
ConstraintLayout {
val (icon, text) = createRefs()
Icon(
painter = painterResource(R.drawable.ic_icon),
contentDescription = null,
modifier = Modifier
.constrainAs(icon) {
width = Dimension.value(16.dp)
height = Dimension.value(16.dp)
start.linkTo(parent.start, 16.dp)
top.linkTo(parent.top)
end.linkTo(parent.end, 16.dp)
bottom.linkTo(parent.bottom)
}
)
Text(
text = "Text",
modifier = Modifier
.constrainAs(text) {
width = Dimension.fillToConstraints
height = Dimension.wrapContent
start.linkTo(icon.end, 8.dp)
top.linkTo(icon.top)
end.linkTo(icon.end, 8.dp)
bottom.lintTo(icon.bottom)
}
)
}
Enforcing constraints
Stackoverflow question
ConstraintLayout {
val (row) = createRefs()
Row(
modifier = Modifier
.constrainAs(row) {
width = Dimension.fillToConstraints
height = Dimension.wrapContent
start.linkTo(parent.start, 8.dp)
top.linkTo(parent.top)
end.linkTo(parent.end, 8.dp)
bottom.linkTo(parent.bottom)
}
) {
Text(
text = "Text",
overflow = TextOverflow.Ellipsis,
maxLines = 1,
modifier = Modifier
.weight(
weight = 1F,
fill = false
)
)
Icon(
painter = painterResource(R.drawable.ic_icon),
contentDescription = null
)
}
}
Chain
ConstraintLayout {
val (icon, text) = createRefs()
createHorizontalChain(icon, text, chainStyle = ChainStyle.Packed)
Icon(
modifier = Modifier
.constrainAs(icon) {
width = Dimension.wrapContent
height = Dimension.wrapContent
start.linkTo(parent.start)
top.linkTo(parent.top)
end.linkTo(text.start)
bottom.linkTo(parent.bottom)
}
)
Text(
modifier = Modifier
.constrainAs(text) {
width = Dimension.wrapContent
height = Dimension.wrapContent
start.linkTo(icon.end)
top.linkTo(parent.top)
end.linkTo(parent.end)
bottom.linkTo(parent.bottom)
}
.padding(start = 8.dp)
)
}
AndroidView(
factory = { context ->
View(context)
},
modifier = Modifier
)
val dencity: Density = LocalDensity.current
var columnHeightPx: Float by remember { mutableStateOf(0F) }
var columnHeightDp: Dp by remember { mutableStateOf(0.dp) }
Box(
modifier = Modifier
.onGloballyPositioned { layoutCoordinates ->
columnHeightPx = layoutCoordinates.size.height.toFloat()
columnHeightDp = with(dencity) { layoutCoordinates.size.height.toDp() }
}
)
Home • Interviews • Android Architecture • Android Jetpack • Android Jetpack Compose • Android Releases • Android SDK • Android Views • Basic • Design • Git • GitHub • Gradle • Java • Kotlin • Kotlin Coroutines • RxJava