DEV Community

Cover image for Exemplo Navigation Drawer com Jetpack Compose
Gilber
Gilber

Posted on

Exemplo Navigation Drawer com Jetpack Compose

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()
                }
            }
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

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")
                        }
                    }

                }
            }
        }
    )
}
Enter fullscreen mode Exit fullscreen mode

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")
    }
}
Enter fullscreen mode Exit fullscreen mode

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
    }
}
Enter fullscreen mode Exit fullscreen mode

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
)
Enter fullscreen mode Exit fullscreen mode

Resultado final

Image description

Top comments (0)