Przykład FloatingActionButton z biblioteką obsługi


129

Ostatnio czytałem te posty:

Ale żaden z nich nie daje mi szczegółowego przykładu tworzenia nowego FloatingActionButton. Tak trudno to zrozumieć, dlatego zadaję to pytanie.

Czy ktoś może mi dać przykład na ten temat?

EDYTOWAĆ

Właśnie znalazłem kilka problemów w FloatingActionButton(FAB) i chcę poprawić inną odpowiedź. Zobacz moją odpowiedź poniżej.


Odpowiedzi:


274

Więc w swoim build.gradlepliku dodaj to:

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

Uwaga AndroidX: Google wprowadza nowe biblioteki rozszerzeń AndroidX, aby zastąpić starsze biblioteki obsługi. Aby korzystać z AndroidX, najpierw upewnij się , że zaktualizowałeś gradle.propertiesplik , wyedytowałeś build.gradlego compileSdkVersionna 28(lub wyższy) i użyj następującego wiersza zamiast poprzedniego compile.

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

Następnie, w swoim themes.xmllub styles.xmlczymkolwiek innym , upewnij się, że ustawiłeś to - jest to kolor akcentu twojej aplikacji - i kolor twojego FAB, chyba że go zastąpisz (patrz poniżej):

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

W kodzie XML układu:

<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>

Lub jeśli korzystasz z biblioteki materiałów AndroidX powyżej, zamiast tego użyj tego:

<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>

Możesz zobaczyć więcej opcji w dokumentach ( dokumenty materialne tutaj) ( setRippleColoritp.), Ale jedną z ważnych informacji jest:

    app:fabSize="mini"

Kolejny interesujący - aby zmienić kolor tła tylko jednego FAB, dodaj:

    app:backgroundTint="#FF0000"

(na przykład, aby zmienić kolor na czerwony) do pliku XML powyżej.

W każdym razie w kodzie po zawyżeniu widoku Aktywności / fragmentu ....

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

Obserwacje:

  • Jeśli masz jeden z tych przycisków, który znajduje się na „szwie” dzielącym dwa widoki (na przykład przy użyciu układu RelativeLayout) z, powiedzmy, ujemnym dolnym marginesem układu nakładającym się na obramowanie, zauważysz problem: rozmiar FAB jest w rzeczywistości bardzo różni się na Lollipop i Pre-Lollipop. W rzeczywistości możesz to zobaczyć w edytorze układu graficznego AS, gdy przełączasz się między interfejsami API - nagle "wydycha", gdy przełączasz się na pre-lollipop. Wydaje się, że przyczyną dodatkowego rozmiaru jest to, że cień rozszerza rozmiar widoku w każdym kierunku. Musisz więc to uwzględnić, dostosowując marginesy FAB, jeśli jest blisko innych rzeczy.
  • Oto sposób na usunięcie lub zmianę wypełnienia, jeśli jest za dużo:

    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);
    }
    
  • Zamierzałem również programowo umieścić FAB na „szwie” między dwoma obszarami w układzie względnym, chwytając wysokość FAB, dzieląc ją przez dwa i używając tego jako przesunięcia marginesu. Ale myFab.getHeight () zwróciło zero, wydawało się, że nawet po zawyżeniu widoku. Zamiast tego użyłem ViewTreeObserver, aby uzyskać wysokość dopiero po jej rozłożeniu, a następnie ustawieniu pozycji. Zobacz tę wskazówkę tutaj . Wyglądało to tak:

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

    Nie jestem pewien, czy to właściwy sposób, ale wydaje się, że działa.

  • Wygląda na to, że możesz zmniejszyć przestrzeń cienia przycisku, zmniejszając wysokość.
  • Jeśli chcesz FAB na „szwie”, możesz użyć layout_anchori layout_anchorGravityoto przykład:

    <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"/>
    

Pamiętaj, że możesz automatycznie sprawić, by przycisk wyskoczył z drogi, gdy pojawi się Snackbar , owijając go w CoordinatorLayout .

Jeszcze:


1
Pewnie. Po prostu dodaj android:backgroundTint="#FF0000"na przykład to do FloatingActionBar w kodzie XML. (dodając do odpowiedzi)
fattire

1
Hmm. W porządku, zmienię to powyżej. Dzięki! Dark Leonhart - nie widziałem nic na temat wbudowanego szybkiego powrotu, ale są przykłady robienia tego w innym miejscu w przepływie stosu, które, jak przypuszczam, nadal będą działać. Ponadto dostępne są biblioteki, które również to robią.
fattire

1
Moim zdaniem ten komponent od 22.2.0 nie jest gotowy do produkcji. Btw, może być literówką, ale nie używaj spwe właściwości evelation. Powinno byćapp:elevation="4dp"
Joao Sousa

1
Uwaga, jeśli dodajesz a FloatingActionButtondo a CoordinatorLayout, możesz użyć app:layout_anchor="element_with_seam"i app:layout_anchorGravity="bottom|right|end"prawidłowo ustawić FAB nad szewem
ianhanniballake.

2
@DarkLeonhart - zobacz mój przykład pokazywania / ukrywania FAB-a na przewijaniu poprzez rozszerzenie jego zachowania.
ianhanniballake

49

Właśnie znalazłem kilka problemów na FAB i chcę ulepszyć inną odpowiedź.


setRippleColor problem

Tak więc problem pojawi się po programowym ustawieniu koloru tętnienia (kolor FAB po naciśnięciu) setRippleColor. Ale nadal mamy alternatywny sposób, aby to ustawić, tj. Dzwoniąc:

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

Twój projekt musi mieć taką strukturę:

/res/color/fab_ripple_color.xml

wprowadź opis obrazu tutaj

A kod z fab_ripple_color.xmlto:

<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>

Na koniec nieznacznie zmień 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 -->

W przypadku poziomu API 21 i wyższych ustaw margines prawy i dolny na 24 dp:

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

Przewodniki projektowe FloatingActionButton

Jak widać na powyższym kodzie FAB xml, ustawiłem:

        ...
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        app:elevation="6dp"
        app:pressedTranslationZ="12dp"
        ...
  • Ustawiając te atrybuty, nie musisz ustawiać layout_marginTopi layout_marginRightponownie (tylko w wersjach wcześniejszych niż Lollipop). Android umieści go automatycznie po prawej stronie ekranu, tak samo jak normalny FAB w Androidzie Lollipop.

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

Lub możesz użyć tego w CoordinatorLayout:

        android:layout_gravity="end|bottom"
  • Musisz mieć 6dp elevationi 12dp pressedTranslationZ, zgodnie z tym przewodnikiem Google.

Zasady FAB


5
kciuki w górę za badania. plus 1 za pressedTranslationZ. Nie wiedziałem tego.
Joao Sousa

app: elevation = "6dp" app: pressTranslationZ = "12dp" radzi sobie z pre-lollipopem, ale mój fab jest dosłownie na rogu ekranu w Lollipop
Thiago

1
Używasz nieprawidłowej wartości dla „pressTranslationZ”. To nie jest wartość podniesienia w stanie wciśniętym. PressedElevation = elewacja + pressTranslationZ. Więc poprawne wartości to app: elevation = "6dp" app: pressTranslationZ = "6dp"
e.shishkin.

3
Właściwie nie musisz ustawiać wartości app:elevationi app:pressedTranslationZ. Ich wartością domyślną jest ta określona w wytycznych dotyczących projektowania materiałów. W każdym razie e.shishkin ma rację, wartości są app:elevation:6dpi pressedTranslationZ:6dp. Możesz to sprawdzić w kodzie źródłowym
Christian García

12

FloatingActionButtonrozciąga się ImageView. Jest to więc proste, jak wprowadzenie do ImageViewukładu. Oto przykład 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" jest dodawany jako obejście problemów związanych z podniesieniem uprawnień.


4

dla AndroidX użyj takich jak

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

1

Jeśli dodałeś już wszystkie biblioteki i nadal nie działa, użyj:

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

zamiast:

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

I wszystko będzie dobrze :)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.