Exemplo de FloatingActionButton com biblioteca de suporte

129

Recentemente, li esses posts:

Biblioteca de suporte do Android Design

Biblioteca de suporte do Android, revisão 22.2.0

FloatingActionButton

Mas nenhum deles me fornece um exemplo detalhado de como criar um novo FloatingActionButton. Tão difícil de entender, eu faço essa pergunta.

Alguém pode me dar um exemplo disso?

Qualquer ajuda será muito apreciada. Desde já, obrigado.

EDITAR

Acabei de encontrar alguns problemas no FloatingActionButton(FAB) e quero melhorar outra resposta. Veja minha resposta abaixo.

Anggrayudi H
fonte

Respostas:

274

Então, no seu build.gradlearquivo, adicione isto:

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

AndroidX Nota: o Google está introduzindo novas bibliotecas de extensão AndroidX para substituir as bibliotecas de suporte mais antigas. Para usar o AndroidX, primeiro verifique se você atualizou seu gradle.propertiesarquivo , edite build.gradlepara definir compileSdkVersioncomo 28(ou superior) e use a linha a seguir, em vez da linha anterior compile.

implementation 'com.google.android.material:material:1.0.0'

Em seguida, no seu themes.xmlou no que styles.xmlfor, certifique-se de definir isso - é a cor de destaque do seu aplicativo - e a cor do seu FAB, a menos que você o substitua (veja abaixo):

        <item name="colorAccent">@color/floating_action_button_color</item>

No XML do layout:

<RelativeLayout
 ...
 xmlns:app="http://schemas.android.com/apk/res-auto">

       <android.support.design.widget.FloatingActionButton
            android:id="@+id/myFAB"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_plus_sign"
            app:elevation="4dp"
            ... />

</RelativeLayout>

Ou, se você estiver usando a biblioteca de materiais AndroidX acima, use o seguinte:

<RelativeLayout
 ...
 xmlns:app="http://schemas.android.com/apk/res-auto">

       <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/myFAB"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:srcCompat="@drawable/ic_plus_sign"
            app:elevation="4dp"
            ... />

</RelativeLayout>

Você pode ver mais opções nos documentos ( documentos materiais aqui) ( setRippleColor, etc.), mas uma das notas é:

    app:fabSize="mini"

Outro interessante - para alterar a cor de fundo de apenas um FAB, adicione:

    app:backgroundTint="#FF0000"

(por exemplo, para alterá-lo para vermelho) no XML acima.

De qualquer forma, no código, após a exibição da Atividade / Fragmento ser inflada ....

    FloatingActionButton myFab = (FloatingActionButton)  myView.findViewById(R.id.myFAB);
    myFab.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            doMyThing();
        }
    });

Observações:

  • Se você tiver um desses botões em uma "costura" que divide duas visualizações (usando um RelativeLayout, por exemplo) com, digamos, uma margem de layout inferior negativa para sobrepor a borda, você notará um problema: o tamanho da FAB é realmente muito diferente no pirulito vs. pré-pirulito. Na verdade, você pode ver isso no editor de layout visual do AS quando você alterna entre APIs - de repente "se esvai" quando você muda para o pré-pirulito. A razão para o tamanho extra parece ser que a sombra expande o tamanho da visualização em todas as direções. Portanto, você deve levar isso em conta quando estiver ajustando as margens da FAB se estiver perto de outras coisas.
  • Aqui está uma maneira de remover ou alterar o preenchimento se houver muito:

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) myFab.getLayoutParams();
        p.setMargins(0, 0, 0, 0); // get rid of margins since shadow area is now the margin
        myFab.setLayoutParams(p);
    }
  • Além disso, eu colocaria programaticamente a FAB na "costura" entre duas áreas em um RelativeLayout agarrando a altura da FAB, dividindo por duas e usando-a como deslocamento de margem. Mas myFab.getHeight () retornou zero, mesmo depois que a exibição foi inflada, parecia. Em vez disso, usei um ViewTreeObserver para obter a altura somente após o layout e depois definir a posição. Veja esta dica aqui . Parecia assim:

        ViewTreeObserver viewTreeObserver = closeButton.getViewTreeObserver();
        if (viewTreeObserver.isAlive()) {
            viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                        closeButton.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    } else {
                        closeButton.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    }
                    // not sure the above is equivalent, but that's beside the point for this example...
                    RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) closeButton.getLayoutParams();
                    params.setMargins(0, 0, 16, -closeButton.getHeight() / 2); // (int left, int top, int right, int bottom)
                    closeButton.setLayoutParams(params);
                }
            });
        }

    Não tenho certeza se esse é o caminho certo para fazê-lo, mas parece funcionar.

  • Parece que você pode diminuir o espaço de sombra do botão diminuindo a elevação.
  • Se você deseja o FAB em uma "costura", pode usar layout_anchore layout_anchorGravityaqui está um exemplo:

    <android.support.design.widget.FloatingActionButton
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        app:layout_anchor="@id/appbar"
        app:layout_anchorGravity="bottom|right|end"
        android:src="@drawable/ic_discuss"
        android:layout_margin="@dimen/fab_margin"
        android:clickable="true"/>

Lembre-se de que você pode fazer com que o botão salte automaticamente quando um Snackbar aparecer, envolvendo-o em um CoordinatorLayout .

Mais:

fattire
fonte
1
Certo. Basta adicionar, android:backgroundTint="#FF0000"por exemplo, ao FloatingActionBar no XML. (adicionando a resposta)
fattire
1
Hmm. Ok, eu vou mudar isso acima então. Obrigado! Dark Leonhart-- Eu não vi nada sobre retorno rápido embutido, mas há exemplos de fazê-lo em outro lugar no stackoverflow que, presumo, ainda funcionará. Além disso, algumas bibliotecas também estão disponíveis.
fattire
1
Este componente, a partir de 22.2.0, na minha opinião, não está pronto para produção. Btw, pode ser um erro de digitação, mas não use spna propriedade evelation. Deveria serapp:elevation="4dp"
Joao Sousa
1
Nota Se você estiver adicionando um FloatingActionButtona um CoordinatorLayout, você pode usar app:layout_anchor="element_with_seam"e app:layout_anchorGravity="bottom|right|end"para posicionar a FAB corretamente sobre uma costura - ver a disposição activity_detail de cheesesquare
ianhanniballake
2
@ DarkLeonhart - veja meu exemplo de exibição / ocultação da FAB no scroll estendendo seu comportamento.
Ianhanniballake
49

Acabei de encontrar alguns problemas na FAB e quero melhorar outra resposta.


Problema setRippleColor

Portanto, o problema surgirá assim que você definir a cor de ondulação (cor FAB pressionada) programaticamente setRippleColor. Mas, ainda temos uma maneira alternativa de configurá-lo, ou seja, chamando:

FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
ColorStateList rippleColor = ContextCompat.getColorStateList(context, R.color.fab_ripple_color);
fab.setBackgroundTintList(rippleColor);

Seu projeto precisa ter esta estrutura:

/res/color/fab_ripple_color.xml

insira a descrição da imagem aqui

E o código de fab_ripple_color.xmlé:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:color="@color/fab_color_pressed" />
    <item android:state_focused="true" android:color="@color/fab_color_pressed" />
    <item android:color="@color/fab_color_normal"/>
</selector>

Por fim, altere ligeiramente o seu FAB:

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/ic_action_add"
    android:layout_alignParentBottom="true"
    android:layout_alignParentRight="true"
    app:fabSize="normal"
    app:borderWidth="0dp"
    app:elevation="6dp"
    app:pressedTranslationZ="12dp"
    app:rippleColor="@android:color/transparent"/> <!-- set to transparent color -->

Para o nível 21 da API e superior, defina a margem direita e inferior como 24dp:

...
android:layout_marginRight="24dp"
android:layout_marginBottom="24dp" />

Guias de design do FloatingActionButton

Como você pode ver no meu código xml da FAB acima, defino:

        ...
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        app:elevation="6dp"
        app:pressedTranslationZ="12dp"
        ...
  • Ao definir esses atributos, você não precisa set layout_marginTope layout_marginRightnovamente (apenas na pré-Lollipop). O Android o colocará automaticamente no lado direito da tela, o mesmo que o FAB normal no Android Lollipop.

        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"

Ou você pode usar isso em CoordinatorLayout:

        android:layout_gravity="end|bottom"
  • Você precisa ter 6dp elevatione 12dp pressedTranslationZ, de acordo com este guia do Google.

Regras FAB

Anggrayudi H
fonte
5
perfeito para a pesquisa envolvida. mais 1 para o pressedTranslationZ. Eu não sabia disso.
Joao Sousa
app: elevação = "6DP" app: pressedTranslationZ = "12DP" faz o truque para pré-pirulito, mas meu fab é literalmente na esquina da tela no Lollipop
Thiago
1
Você está usando um valor incorreto para "selectedTranslationZ". Não é o valor da elevação no estado pressionado. PressedElevation = elevação + pressionadoTranslationZ. Valores tão correto é app: elevação = app "6DP": pressedTranslationZ = "6DP"
e.shishkin
3
Na verdade você não precisa para definir os app:elevatione app:pressedTranslationZvalores. Seu valor padrão é o definido nas diretrizes de design de materiais. Enfim, e.shishkin está certo, os valores são app:elevation:6dpe pressedTranslationZ:6dp. Você pode verificá-lo no código fonte
Christian García
12

FloatingActionButtonse estende ImageView. Portanto, é simples como introduzir um ImageViewno seu layout. Aqui está uma amostra XML.

<android.support.design.widget.FloatingActionButton   xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/somedrawable"
    android:layout_gravity="right|bottom"
    app:borderWidth="0dp"
    app:rippleColor="#ffffff"/>

app:borderWidth="0dp" é adicionado como uma solução alternativa para problemas de elevação.

siriscac
fonte
4

para AndroidX use como

<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@drawable/ic_add" />
Dan Alboteanu
fonte
1

Se você já adicionou todas as bibliotecas e ainda não funciona, use:

<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@drawable/ic_add" 
/>

ao invés de:

<android.support.design.widget.FloatingActionButton
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   app:srcCompat="@drawable/ic_add"
 />

E tudo vai funcionar bem :)

Max Shwed
fonte