Exemplo Navigation Drawer com Jetpack Compose
Gilber
Posted on January 6, 2023
Esta é uma IU de gaveta de navegação feita com o Android Jetpack Compose. Ele usa o layout Scaffold. O código-fonte está disponível gratuitamente abaixo.
MainActivity.kt
package br.com.gilbercs.exjetpackcompose
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material.*
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.platform.LocalContext
import br.com.gilbercs.exjetpackcompose.ui.MainContent
import br.com.gilbercs.exjetpackcompose.ui.components.MyButtonBar
import br.com.gilbercs.exjetpackcompose.ui.components.MyDrawer
import br.com.gilbercs.exjetpackcompose.ui.components.MyFabButton
import br.com.gilbercs.exjetpackcompose.ui.components.MyTopAppBar
import br.com.gilbercs.exjetpackcompose.ui.theme.ExJetpackComposeTheme
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ExJetpackComposeTheme {
//Declaração de variavel
val scaffoldState = rememberScaffoldState()
val coroutineScope = rememberCoroutineScope()
val context = LocalContext.current
//Create Scaffolf layout: Onde será adiconado itens como TopBar, BottomBar, FAB ou uma gaveta.
Scaffold(
scaffoldState = scaffoldState,
//Top App Bar principal da aplicação
topBar = {
MyTopAppBar(
onDrawerClick = {
coroutineScope.launch {
scaffoldState.drawerState.open()
}
}
)
},
drawerGesturesEnabled = scaffoldState.drawerState.isOpen,
//Drawer Navigation da aplicação
drawerContent = {
MyDrawer{menuTitle ->
Toast.makeText(context,menuTitle,Toast.LENGTH_LONG).show()
coroutineScope.launch {
delay(250)
scaffoldState.drawerState.close()
}
}
},
//Float button da aplicação
floatingActionButton = {
MyFabButton()
},
isFloatingActionButtonDocked = true,
//Button da aplicação
bottomBar = {
MyButtonBar()
}
) {
//Scaffold content main
MainContent()
}
}
}
}
}
MyTopAppBar
O componente TopAppBar é freqüentemente usado como cabeçalho para nossa tela — exibindo um título de navegação junto com componentes de menu ou qualquer outra decoração que o design de nosso aplicativo exija.
package br.com.gilbercs.exjetpackcompose.ui.components
import android.widget.Toast
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Call
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.List
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.runtime.*
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
@Composable
fun MyTopAppBar(
onDrawerClick: () -> Unit
){
val context = LocalContext.current
val dropDownMenuItems = listOf("Menu 01", "Menu 02", "Menu 03")
var isDropDownMenuExpanded by remember { mutableStateOf(false) }
TopAppBar(title = { Text(text = "Meu Aplication")},
navigationIcon = {
IconButton(onClick = { onDrawerClick()}) {
Icon(imageVector = Icons.Default.List, contentDescription = "Menu")
}
},
actions = {
IconButton(onClick = {
Toast.makeText(context,"Call",Toast.LENGTH_LONG).show()
}) {
Icon(imageVector = Icons.Default.Call, contentDescription = "Menu", tint = Color.White)
}
IconButton(onClick = {
Toast.makeText(context,"Favorito",Toast.LENGTH_LONG).show()
}) {
Icon(imageVector = Icons.Default.Favorite, contentDescription = "Favorite", tint = Color.White)
}
IconButton(onClick = {
isDropDownMenuExpanded = true
}) {
Icon(imageVector = Icons.Default.MoreVert, contentDescription = "Menu", tint = Color.White)
DropdownMenu(expanded = isDropDownMenuExpanded, onDismissRequest = { isDropDownMenuExpanded =! isDropDownMenuExpanded }) {
dropDownMenuItems.forEach { label->
DropdownMenuItem(onClick = {
Toast.makeText(context,"$label",Toast.LENGTH_LONG).show()
}) {
Text(text = "$label")
}
}
}
}
}
)
}
MyFabButton
Aqui você pode adicionar FloatingActionButton. Você pode definir qualquer Composable, mas FloatingActionButton já foi criado para este caso de uso.
import android.widget.Toast
import androidx.compose.material.FloatingActionButton
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
@Composable
fun MyFabButton() {
//Declaração de variavél
val context = LocalContext.current
FloatingActionButton(onClick = { Toast.makeText(context,"Adicionar",Toast.LENGTH_LONG).show()},
backgroundColor = MaterialTheme.colors.primaryVariant) {
Icon(imageVector = Icons.Default.Add,
contentDescription = "ADD")
}
}
MyButtonBar
Vai exibir os destinos na parte inferior da tela. Logo vamos usa o slot bottomBar e isFloatingActionButtonDocked para sobrepor o FAB com a barra de apps inferior.
BottomAppBar oferece suporte a cortes no FAB com o parâmetro cutoutShape, que aceita qualquer Shape. É recomendável fornecer o mesmo Shape usado pelo componente fixado. Por exemplo, FloatingActionButton usa MaterialTheme.shapes.small com um tamanho de canto de 50% como valor padrão para o parâmetro shape:
package br.com.gilbercs.exjetpackcompose.ui.components
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.material.BottomAppBar
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
@Composable
fun MyButtonBar() {
BottomAppBar(
cutoutShape = MaterialTheme.shapes.small.copy(
CornerSize(50)
)
) {
//Buttom Content
}
}
Navigation Drawer compose
E por fim MyDrawer da aplicação que vai ser menu deslizante para a esquerda usado para exibir o conteúdo do menu no Android.
Facilita a navegação entre diferentes telas.
A gaveta aparece quando o usuário toca no ícone do menu da gaveta na barra de aplicativos.
package br.com.gilbercs.exjetpackcompose.ui.components
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import br.com.gilbercs.exjetpackcompose.R
@Composable
fun MyDrawer(
bgGradientColos: List<Color> = listOf(Color(0xFF689F38),Color(0xFF8BC34A),Color(0xFFC5E1A5)),
onItemClick: (String) -> Unit
){
//declarar variavel
val itemMenu = prepareItemDrawer()
LazyColumn(modifier = Modifier
.fillMaxSize()
.background(brush = Brush.verticalGradient(bgGradientColos)),
horizontalAlignment = Alignment.CenterHorizontally,
contentPadding = PaddingValues(vertical = 36.dp)
){
item {
//Imagem
Image(
modifier = Modifier
.size(size = 150.dp)
.clip(CircleShape),
painter = painterResource(id = R.drawable.img_albert),
contentDescription = "Imagem Perfil")
//Text
Text(
modifier = Modifier.padding(top = 8.dp, bottom = 30.dp),
text = "gilbercs@hotmail.com",
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
color = Color.White
)
}
items(itemMenu){item ->
NavItemDrawer(itemDrawer = item) {
onItemClick(item.title)
}
}
}
}
@Composable
fun NavItemDrawer(
itemDrawer: ItemDrawer,
unredBubble: Color = Color(0XFF1976D2),
onClick: () -> Unit
){
Row(modifier = Modifier
.fillMaxWidth()
.clickable { onClick() }
.padding(24.dp, vertical = 10.dp),
verticalAlignment = Alignment.CenterVertically) {
Box {
//Menu: Icon
Icon(modifier = Modifier
.padding(all = if (itemDrawer.show && itemDrawer.title == "Messages") 5.dp else 2.dp)
.size(size = if (itemDrawer.show && itemDrawer.title == "Messages") 24.dp else 28.dp),
imageVector = itemDrawer.icon,
contentDescription = "Icon",
tint = Color.White)
//Unred bubble
if (itemDrawer.show){
Box(modifier = Modifier
.size(size = 8.dp)
.align(alignment = Alignment.TopCenter)
.background(color = unredBubble, shape = CircleShape))
}
//Menu: Title
Text(
modifier = Modifier
.padding(start = 40.dp),
text = itemDrawer.title,
fontSize = 20.sp,
fontWeight = FontWeight.Medium,
color = Color.White)
}
}
}
@Composable
private fun prepareItemDrawer(): List<ItemDrawer>{
val item = arrayListOf<ItemDrawer>()
//Adicionar Menu no Drawer: Home
item.add(
ItemDrawer(
icon = Icons.Default.Home,
title = "Home"
)
)
//Perfil
item.add(
ItemDrawer(
icon = Icons.Default.Person,
title = "Perfil"
)
)
//Favorite
item.add(
ItemDrawer(
icon = Icons.Default.Favorite,
title = "Favorito"
)
)
//Sobre
//Favorite
item.add(
ItemDrawer(
icon = Icons.Default.Info,
title = "Sobre"
)
)
//Sair
//Favorite
item.add(
ItemDrawer(
icon = Icons.Default.Close,
title = "Sair"
)
)
return item
}
data class ItemDrawer(
val icon: ImageVector,
val title: String,
val show: Boolean = false
)
Resultado final
Posted on January 6, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 29, 2024