Android Design Support Library – FAB e Snackbar (Parte 2)

Aqui estamos novamente com mais um tutorial da biblioteca Android Design Support, dessa vez para apresentar dois outros componentes: Floating Action Button [1] (popularmente conhecido como FAB) e Snackbar [2]. Com o uso desses dois novos componentes, mais a Navigation Drawer (apresentado no post anterior [3]), você caminha para um aplicativo cada vez mais próximo de uma identidade visual voltada para o padrão Material Design [4] estabelecido pela Google.

Para os ansiosos, segue abaixo o resultado

Figura 1 - FAB e Snackbar em ação
Figura 1 – FAB e Snackbar em ação

Pré-requisito

  • Android Studio
  • Um Smartphone Android ou um AVD (Android Virtual Device) para testar o projeto.

O código deste projeto já está compartilhado no GitHub [5]. Dentro do projeto há inúmeros arquivos. Não vou entrar no mérito de explicar todos os arquivos, pois o foco é apenas no FAB e na Snackbar.

Adicionar dependência

Bem, se você possui alguma experiência com desenvolvimento, sabe que quando precisamos utilizar uma biblioteca em um projeto, é necessário adicionar uma nova dependência ao projeto. O Android utiliza o Gradle [6] para gerenciar as dependências. Sem mais delongas, altere o arquivo build.gradle (do módulo) incluindo a linha abaixo em dependencies

compile 'com.android.support:design:23.2.1'

Floating Action Button (FAB)

O FAB é um componente oriundo do Material Design que tem como objetivo fornecer um acesso rápido a principal funcionalidade do aplicativo. É fácil reconhecer um FAB em uma interface: um botão circular com um ícone dentro representando a ação, comumente localizado no canto inferior direito da tela, visivelmente sobressaindo à interface. Do Material Design, esse é um dos componentes mais utilizado. Na figura 2 podemos ver 3 exemplos.

Aplicativos Inbox, Sheets e Google+ utilizando FAB (canto inferior direito)
Figura 2 – Aplicativos Inbox, Sheets e Google+ utilizando FAB (canto inferior direito)

A implementação é bastante simples, uma vez que a biblioteca esteja importada, é só incluir no XML o trecho abaixo:

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@android:drawable/ic_input_add"
    android:tint="@android:color/white"
    android:layout_gravity="bottom|end"
    android:layout_margin="@dimen/fab_margin" />

Entendendo o código acima

  • O componente está sendo buscando da biblioteca, como podemos ver com o código android.support.design.widget.FloatingActionButton.
  • Logo em seguida, definimos um id, que mais pra frente utilizaremos no Java.
  • O valor do width e do height vai como wrap content para utilizar apenas o espaço necessário pelos componentes internos.
  • Em src estamos colocando a imagem que irá dentro do FAB, no caso, um botão de soma (que está localizado nas imagens nativas do Android).
  • A propriedade tint define a cor do botão dentro da FAB, que neste caso, é a cor branca.
  • Estamos também definindo que a posição do botão é no canto inferior direito ao incluir os valores bottom e end na propriedade layout gravity.
  • Para finalizar, estamos definindo a margem do FAB com uma variável que está definida no arquivo /values/dimens.xml com o valor 16p.

Com o uso da biblioteca, o comportamento da interação entre FAB e Snackbar (próximo tópico) já vem implementado nativamente. É possível incluir mais comportamentos no FAB, mas vamos deixar isso para um futuro post.

Snackbar

Snackbar é outro componente do Material Design que veio para ser uma alternativa mais completa às mensagens Toast  [7]. Em suma, Snackbar é um componente para apresentar feedback para usuário sobre determinada operação que ele realizou. Caso não se lembre das mensagens Toast, segue abaixo na Figura 3 um exemplo.

Figura 2 - Mensagem Toast
Figura 3 – Mensagem Toast

A implementação básica é praticamente idêntica, porém o Snackbar pode conter um “botão” na mensagem, como por exemplo, um botão que desfaz a ação que usuário acabou de realizar. Fica a cargo do desenvolvedor escolher qual ação que o botão da Snackbar irá realizar. Na figura 4 podemos ver um exemplo da Snackbar no Android.

Figura 3 - Snackbar
Figura 4 – Snackbar

Abaixo segue uma utilização básica do Snackbar. Lembrando que, como o Toast, a Snackbar também não possui implementação no XML, apenas no código Java.

FloatingActionButton fab = (FloatingActionButton)findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Snackbar.make(view, "Esta é uma Snackbar", Snackbar.LENGTH_LONG).setAction("Mostrar um Toast", new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this, "Este é um Toast", Toast.LENGTH_LONG).show();
            }
        }).show();
    }
});

Entendendo o código acima

  • A Snackbar irá aparecer na tela quando o usuário clicar na FAB que criamos no tópico anterior.
  • Para isso, estamos instanciando um objeto do tipo FloatinActionButton com a referencia do componente XML (lembra que criamos o componente no XML com o id fab?)
  • Com o objeto em mãos, estamos definindo um comportamento para quando o botão FAB for clicado, sobrescrevendo o método onClick.
  • Dentro do onClick, eis que aparece a tão esperada Snackbar. Implementação bastante simples: chamamos o método make da Snackbar passando o layout a qual a mesma será desenhada, no caso, o drawer_layout, a mensagem que irá dentro da Snackbar e por fim passamos a duração que o Snackbar vai ter, que no caso, é uma duração curta.
  • Depois, temos algo que é opcional: definir a ação de um “botão” na Snackbar. Através do método setAction, passando o nome do “botão” e logo em seguida sobrescrevendo o método onClick deste.
  • Dentro do método onClick, estamos criando uma mensagem Toast com o texto “Snackbar Action” e uma duração longa.

Por fim, é necessário chamar o método show, tanto para o Snackbar quanto para a mensagem Toast, se não eles não aparecem na tela.

REFERENCIAS

[1] http://developer.android.com/intl/pt-br/reference/android/support/design/widget/FloatingActionButton.html

[2] http://developer.android.com/reference/android/support/design/widget/Snackbar.html

[3] http://www.matera.com/br/2016/01/21/android-design-support-library-navigation-drawer-parte-1/

[4] https://www.google.com/design/spec/material-design/introduction.html

[5] https://github.com/materasystems/fab-snackbar-tutorial

[6] http://gradle.org/getting-started-android/

[7] http://developer.android.com/intl/pt-br/reference/android/widget/Toast.html

 

Android Design Support Library – Navigation Drawer (Parte 1)

Se você é um usuário do Android, deve ter percebido umas mudanças no visual dos aplicativos em geral, mas principalmente, nos aplicativos do Google. Se você for um observador, pode até mesmo ter notado que há um padrão neste visual. Este padrão não é a nova moda (mas espero que torne-se!) para criar aplicativos, mas sim a nova diretriz de design descrita pela Google: Material Design. O objetivo deste post não é explicar sobre Material Design, para isto, recomendo fortemente a leitura da documentação oficial do Material Design [1]. A documentação é bem rica e, até mesmo para quem não entende nada de design, pode se surpreender com alguns conceitos apresentados em forma de animações para melhor entendimento.

Dentro da documentação do Material Design, há uma seção exclusiva para componentes. Essa seção aborda os componentes do Material Design e como criar eles. Apesar da documentação ser bem rica, é bastante trabalhoso criar componentes na mão. Em vista desse problema, a Google lançou recentemente a biblioteca Android Design Support Library que tem como objetivo facilitar o uso dos componentes do Material Design em aplicativos Android.

Fazendo um paralelo com a parte Web, essa biblioteca seria o equivalente ao Twitter Bootstrap para desenvolvedores Web. Uma total revolução: sem muito trabalho, é possível ter uma aplicação bonita. Bem, chega de papo! Vamos a parte interessante: código!

Para não ficar cansativo, irei criar uma série com 4 posts aqui no Blog da MATERA, sendo este o primeiro. Nesta primeira parte, será abordado o componente Navigation Drawer.

Para os ansiosos, segue abaixo como irá ficar:

Figura 1 - Navigation Drawer em ação
Figura 1 – Navigation Drawer em ação

Pré-requisito

  • Android Studio
  • Um Smartphone Android ou um AVD (Android Virtual Device) para testar o projeto.

O código deste projeto já está compartilhado no GitHub [2]. Dentro do projeto há inúmeros arquivos. Não vou entrar no mérito de explicar todos os arquivos, pois o foco é apenas no Navigation Drawer.

Adicionar dependência

Bem, se você possui alguma experiência com desenvolvimento, sabe que quando precisamos utilizar uma biblioteca em um projeto, é necessário adicionar uma nova dependência ao projeto. O Android utiliza o Gradle [3] para gerenciar as dependências. Sem mais delongas, altere o arquivo build.gradle (do módulo) incluindo a linha abaixo em dependencies

compile 'com.android.support:design:23.0.0'

Navigation Drawer

Provavelmente você já deve ter visto aqueles três tracinhos no canto superior esquerdo de um aplicativo, o qual se você clicar (ou deslizar da esquerda para a direita) aparece um menu lateral. Pois bem, este menu é o famoso Navigation Drawer [4]!

Em res/layout tem o arquivo activity_main.xml com o seguinte código:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <!-- Você pode incluir qualquer componente aqui -->
    <include
        layout="@layout/app_bar_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer" />

</android.support.v4.widget.DrawerLayout>

Entendendo o código acima

Temos um Drawer Layout [5] envolvendo todo o código. O Drawer Layout é um Layout que permite que views surjam das bordas da tela (comumente da esquerda para direita).

Logo em seguida, há um espaço em que você pode colocar qualquer componente de Layout (botão, campo de texto, etc). Neste exemplo, estamos apenas incluindo (include) do arquivo app_bar_main.

Por fim, há um Navigation View [6], o componente responsável por desenhar um menu, nos padrões do Android. Nele, há duas propriedades importantes: headerLayout e menu. A propriedade headerLayout é responsável por obter, de um XML de layout, o cabeçalho do menu. A propriedade menu é responsável por obter, de um xml de menu, uma lista de opções.

Unindo toda a informação, nós temos um Layout que permite que um menu apareça da borda da tela e logo em seguida temos o componente menu que irá surgir da borda da tela.

Em res/layout, tem o arquivo nav_header_main.xml com o conteúdo abaixo:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/nav_header_height"
    android:background="@drawable/side_nav_bar"
    android:gravity="bottom"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:theme="@style/ThemeOverlay.AppCompat.Dark">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        android:src="@drawable/logo_matera" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        android:text="MATERA Systems"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="comercial@www.matera.com" />

</LinearLayout>

Entendendo o código acima

Temos um LinearLayout [7] com orientação vertical, logo, os componentes serão dispostos um sob o outro. Os componentes que compõe esse Linear Layout são: 1 ImageView e 2 TextView. Como podemos ver na Figura 2, o ImageView representa o logo da MATERA Systems, o primeiro TextView representa o texto “MATERA Systems” e o segundo o e-mail “comercial@www.matera.com”.

Figura 2 - Header do Navigation Drawer
Figura 2 – Header do Navigation Drawer

Em res/menu tem o arquivo drawer_menu.xml com o seguinte código:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_solucoes"
            android:icon="@drawable/ic_weekend_black_24dp"
            android:title="Soluções" />
        <item
            android:id="@+id/nav_servicos"
            android:icon="@drawable/ic_business_center_black_24dp"
            android:title="Serviços" />
        <item
            android:id="@+id/nav_empresa"
            android:icon="@drawable/ic_business_black_24dp"
            android:title="Empresa" />
        <item
            android:id="@+id/nav_carreira"
            android:icon="@drawable/ic_bookmark_black_24dp"
            android:title="Carreira" />
        <item
            android:id="@+id/nav_blog"
            android:icon="@drawable/ic_web_black_24dp"
            android:title="Blog" />
        <item
            android:id="@+id/nav_webinars"
            android:icon="@drawable/ic_personal_video_black_24dp"
            android:title="Webinars" />
        <item
            android:id="@+id/nav_contato"
            android:icon="@drawable/ic_settings_phone_black_24dp"
            android:title="Contato" />
    </group>
</menu>

Entendendo o código acima

Esse arquivo possui 7 itens, cada qual com o seu id, ícone e título. O id irá servir para quando estivermos no Java, verificando se o item foi clicado. O ícone é apresentado antes do título. Abaixo como ficou:

Figura 3 - Opções do Navigation Drawer
Figura 3 – Opções do Navigation Drawer

Com isso, nós já temos o Navigation Drawer feito, porém, sem ações. Agora, é tratar os eventos de clique nas opções do menu através do Java. É simples! No MainActivity.java, há o código abaixo:

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == R.id.nav_solucoes) {
        } else if (id == R.id.nav_servicos) {

        } else if (id == R.id.nav_empresa) {

        } else if (id == R.id.nav_carreira) {

        } else if (id == R.id.nav_blog) {

        } else if (id == R.id.nav_webinars) {

        } else if (id == R.id.nav_contato) {

        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }
}

Entendendo o código acima

A classe MainActivity está implementando a interface OnNavigationItemSelectedListener da classe NavigationView permitindo-nos sobrescrever os métodos onBackPressed e onNavigationItemSelected, ou seja, métodos que definem o comportamento de quando o usuário clicar no botão voltar do android e o comportamento de quando o usuário selecionar uma das opções do navigation drawer (Soluções, Serviços, Empresa, etc).

No onBackPressed, ele simplesmente verifica se o Navigation Drawer está aberto e, caso estiver, fecha-o. No onNavigationItemSelected, é verificado o id do item clicado (que definimos lá no drawer_menu, lembra?) e definido um comportamento ao clicar em determinado item. No caso dessa classe, não há nenhum comportamento, mas é comum atribuir a inclusão de um fragment à activity ou abrir uma nova activity. E para finalizar, após clicar em uma das opções, o Navigation Drawer é fechado.

REFERÊNCIAS

[1] https://www.google.com/design/spec/material-design/introduction.html

[2] https://github.com/materasystems/navigation-drawer-tutorial

[3] http://gradle.org/

[4] http://www.google.com/design/spec/patterns/navigation-drawer.html

[5] http://developer.android.com/intl/pt-br/reference/android/support/v4/widget/DrawerLayout.html

[6] http://developer.android.com/intl/pt-br/reference/android/support/design/widget/NavigationView.html

[7] http://developer.android.com/intl/pt-br/reference/android/widget/LinearLayout.html