2
respostas

Desafio aceito ;D !

Fala galera beleza ?, aceitei o desafio e fiz um pouco diferente da proposta do professor.

Segue GIF com a animação:

https://gifyu.com/image/Sqfq4

Basicamente eu queria remover totalmente a AppBar e deixar somente o campo de busca, então segue ai o codigo (acredito que pode ter tecnicas para melhorar como todo código rsss ....)

O arquivo ContatoDao ficou igual o da busca do professor

@Query("SELECT * FROM Contato where nome like :entrada || '%'")
    fun buscaContato(entrada:String): Flow<List<Contato>>

Dentro da tela de ListaContatosTela eu adicionei uma lógica para verificar o que deve ser exibido no topo e inseri dois novos metodos para pesquisar e para mostrar a pesquisa...


@Composable
fun ListaContatosTela(
    state: ListaContatosUiState,
    modifier: Modifier = Modifier,
    onClickDesloga: () -> Unit = {},
    onClickAbreDetalhes: (Long) -> Unit = {},
    onClickAbreCadastro: () -> Unit = {},
    onClickPesquisa: (String) -> Unit = {},
    onClickShowPesquisa: () -> Unit = {}
) {
    Scaffold(
        topBar = {
            if (state.isShowPesquisa) {
                PesquisaDadosTopBar(
                    textoDePesquisa = state.textoPesquisa,
                    onClickPesquisa = onClickPesquisa,
                    onClickShowPesquisa = onClickShowPesquisa
                )
            } else {
                AppBarListaContatos(onClickDesloga = onClickDesloga, onClickShowPesquisa)
            }
        },....

Criei também um composable para esse campo de busca...


@Composable
fun PesquisaDadosTopBar(
    textoDePesquisa: String,
    onClickPesquisa: (String) -> Unit,
    onClickShowPesquisa: () -> Unit = {},
    modifier: Modifier = Modifier,
) {
    Row(
        modifier
            .fillMaxWidth()
            .background(color = MaterialTheme.colors.background),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.Center
    ) {
        OutlinedTextField(
            value = textoDePesquisa,
            onValueChange = { newValue ->
                onClickPesquisa(newValue)
            },
            modifier = modifier
                .padding(10.dp),
            shape = RoundedCornerShape(100),
            leadingIcon = {
                Icon(Icons.Default.Search, contentDescription = "Icone de Lupa")
            },
            label = { Text("Pesquisar") },
            placeholder = {
                Text("Digite o nome do contato ...")
            },
        )
        IconButton(
            onClick = onClickShowPesquisa
        ) {
            Icon(
                imageVector = Icons.Default.Close,
                tint = Color.Black,
                contentDescription = "Sair do modo de pesquisa"
            )
        }

    }
}

@Preview
@Composable
fun PesquisaDadosTopBarPreview() {
    HelloAppTheme {
        PesquisaDadosTopBar(
            textoDePesquisa = "Clau",
            onClickPesquisa = {},
        )
    }
}

Dentro do composable AppBarListaContatos eu inseri um novo icone conforme o gif acima e também passei o metodo para mostrar a pesquisa ou não!

@Composable
fun AppBarListaContatos(
    onClickDesloga: () -> Unit,
    onClickShowPesquisa: () -> Unit = {},
) {
    TopAppBar(
        title = { Text(text = stringResource(id = R.string.nome_do_app)) },
        actions = {
            IconButton(
                onClick = onClickShowPesquisa
            ) {
                Icon(
                    imageVector = Icons.Default.Search,
                    tint = Color.White,
                    contentDescription = stringResource(R.string.pesquisar)
                )
            }

Dentro do data class ListaContatosUiState eu inseri dois novos campos

data class ListaContatosUiState(
    val contatos: List<Contato> = emptyList(),
    val logado: Boolean = true,
    val isShowPesquisa: Boolean = false,
    val textoPesquisa: String = ""
)

Também deleguei ao meu HomeGraphNavigation as chamadas das funções responsaveis por tratar a exibição e busca ...

composable(route = DestinosHelloApp.ListaContatos.rota) {
            val viewModel = hiltViewModel<ListaContatosViewModel>()
            val state by viewModel.uiState.collectAsState()

            ListaContatosTela(
                state = state,
                onClickShowPesquisa = {
                    viewModel.showPesquisa()
                },
                onClickPesquisa = {
                    viewModel.buscaContato(it)
                },
2 respostas

Continuando...

Dentro da ListaContatosViewModel então eu inseri o tratamento dos dados e como se trata do objeto stateFlow mantive os dados dentro dele mesmo para verificar as mudanças de dados...


    init {
        buscaTodosContatos()
    }

    private fun buscaTodosContatos(){
        viewModelScope.launch {
            val contatos = contatoDao.buscaTodos()

            contatos.collect() { contatosBuscados ->
                _uiState.value = _uiState.value.copy(
                    contatos = contatosBuscados
                )
            }
        }
    }

    fun showPesquisa(){
        buscaTodosContatos()
        _uiState.value = _uiState.value.copy(
            isShowPesquisa = !_uiState.value.isShowPesquisa,
            textoPesquisa = ""
        )
    }

    fun buscaContato(entrada: String) {
        viewModelScope.launch {

            _uiState.value = _uiState.value.copy(
                textoPesquisa = entrada
            )

            contatoDao.buscaContato(entrada).collect{
                _uiState.value = _uiState.value.copy(
                    contatos = it,
                )
            }
        }
    }

Daria para melhorar alguns pontos como talvez guardar todas as buscas e computar um filtro somente, ou algo do genero, mas segue ai o projeto...

Olá Pablo, tudo bem?

Parabéns por aceitar e cumprir o desafio. Ficou muito legal o jeito que você descreveu cada decisão tomada no código, incentivamos que faça isso para cada vez mais ficar evidente seu progresso :)

Pode ter certeza que seu post será usado como referência para soluções alternativas das do instrutor.