Weiß jemand, wie die erweiterte Fab-Menübibliothek implementiert wird, wie die Fab on Inbox-App, nachdem die Android Design Support Library veröffentlicht wurde?
Sollte so aussehen:
Weiß jemand, wie die erweiterte Fab-Menübibliothek implementiert wird, wie die Fab on Inbox-App, nachdem die Android Design Support Library veröffentlicht wurde?
Sollte so aussehen:
Antworten:
Derzeit ist in der Designbibliothek kein Widget verfügbar. Nur so geht das schnell und einfach ist die Verwendung von Bibliotheken von Drittanbietern.
Sie können dies natürlich auch mit der Designbibliothek tun, aber es wird eine große Arbeit sein und viel Zeit erfordern. Ich habe einige nützliche Bibliotheken erwähnt, die Ihnen dabei helfen können.
Ich benutze den 4..
Ich habe einen besseren Ansatz erhalten, um das animierende FAB-Menü ohne Verwendung einer Bibliothek zu implementieren oder großen XML-Code für Animationen zu schreiben. Ich hoffe, dies wird in Zukunft jemandem helfen, der einen einfachen Weg benötigt, dies umzusetzen.
Mit der animate().translationY()
Funktion können Sie jede Ansicht nach oben oder unten animieren, wie ich es in meinem folgenden Code getan habe . Überprüfen Sie den vollständigen Code in Github . Wenn Sie in Kotlin nach demselben Code suchen, können Sie das Kotlin-Code-Repo- Animations-FAB-Menü auschecken .
Definieren Sie zuerst alle Ihre FABs an derselben Stelle, damit sie sich überlappen. Denken Sie daran, dass das FAB oben sein sollte, dass Sie klicken und andere anzeigen möchten. z.B:
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab3"
android:layout_width="@dimen/standard_45"
android:layout_height="@dimen/standard_45"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/standard_21"
app:srcCompat="@android:drawable/ic_btn_speak_now" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab2"
android:layout_width="@dimen/standard_45"
android:layout_height="@dimen/standard_45"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/standard_21"
app:srcCompat="@android:drawable/ic_menu_camera" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab1"
android:layout_width="@dimen/standard_45"
android:layout_height="@dimen/standard_45"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/standard_21"
app:srcCompat="@android:drawable/ic_dialog_map" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@android:drawable/ic_dialog_email" />
Definieren Sie jetzt in Ihrer Java-Klasse einfach alle Ihre FABs und führen Sie den Klick wie unten gezeigt aus:
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab1 = (FloatingActionButton) findViewById(R.id.fab1);
fab2 = (FloatingActionButton) findViewById(R.id.fab2);
fab3 = (FloatingActionButton) findViewById(R.id.fab3);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(!isFABOpen){
showFABMenu();
}else{
closeFABMenu();
}
}
});
Verwenden Sie das animation().translationY()
, um Ihr FAB zu animieren. Ich bevorzuge, dass Sie das Attribut dieser Methode in DP verwenden, da nur die Verwendung eines int die Anzeigekompatibilität mit höherer oder niedrigerer Auflösung beeinträchtigt. Wie nachfolgend dargestellt:
private void showFABMenu(){
isFABOpen=true;
fab1.animate().translationY(-getResources().getDimension(R.dimen.standard_55));
fab2.animate().translationY(-getResources().getDimension(R.dimen.standard_105));
fab3.animate().translationY(-getResources().getDimension(R.dimen.standard_155));
}
private void closeFABMenu(){
isFABOpen=false;
fab1.animate().translationY(0);
fab2.animate().translationY(0);
fab3.animate().translationY(0);
}
Definieren Sie nun die oben genannte Dimension in res-> values-> dimension.xml wie folgt:
<dimen name="standard_55">55dp</dimen>
<dimen name="standard_105">105dp</dimen>
<dimen name="standard_155">155dp</dimen>
Das ist alles Hoffnung, dass diese Lösung den Menschen in Zukunft helfen wird, die nach einer einfachen Lösung suchen.
BEARBEITET
Wenn Sie eine Beschriftung über dem FAB hinzufügen möchten, nehmen Sie einfach ein horizontales LinearLayout und fügen Sie das FAB mit der Textansicht als Beschriftung ein. Animieren Sie die Layouts, wenn Sie Probleme damit haben. Sie können meinen Beispielcode in github überprüfen. Ich habe die gesamte Abwärtskompatibilität behandelt Probleme in diesem Beispielcode. Überprüfen Sie meinen Beispielcode für FABMenu in Github
Um das FAB bei Backpress zu schließen, überschreiben Sie onBackPress () wie unten gezeigt:
@Override
public void onBackPressed() {
if(!isFABOpen){
this.super.onBackPressed();
}else{
closeFABMenu();
}
}
Der Screenshot hat auch den Titel mit dem FAB, da ich ihn aus meiner Beispiel-App ingithub nehme
Erstellen Sie zunächst die Menülayouts in der XML-Datei Ihres Aktivitätslayouts. Zum Beispiel ein lineares Layout mit horizontaler Ausrichtung und einer Textansicht für die Beschriftung und einer schwebenden Aktionsschaltfläche neben der Textansicht.
Erstellen Sie die Menülayouts nach Bedarf und Nummer.
Erstellen Sie eine schwebende Basisaktionsschaltfläche und ändern Sie durch Klicken darauf die Sichtbarkeit der Menülayouts.
Bitte überprüfen Sie den folgenden Code als Referenz und für weitere Informationen überprüfen Sie mein Projekt von Github
<android.support.constraint.ConstraintLayout
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.app.fabmenu.MainActivity">
<android.support.design.widget.FloatingActionButton
android:id="@+id/baseFloatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:clickable="true"
android:onClick="@{FabHandler::onBaseFabClick}"
android:tint="@android:color/white"
app:fabSize="normal"
app:layout_constraintBottom_toBottomOf="@+id/activity_main"
app:layout_constraintRight_toRightOf="@+id/activity_main"
app:srcCompat="@drawable/ic_add_black_24dp" />
<LinearLayout
android:id="@+id/shareLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="invisible"
app:layout_constraintBottom_toTopOf="@+id/createLayout"
app:layout_constraintLeft_toLeftOf="@+id/createLayout"
app:layout_constraintRight_toRightOf="@+id/activity_main">
<TextView
android:id="@+id/shareLabelTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:background="@drawable/shape_fab_label"
android:elevation="2dp"
android:fontFamily="sans-serif"
android:padding="5dip"
android:text="Share"
android:textColor="@android:color/white"
android:typeface="normal" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/shareFab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:onClick="@{FabHandler::onShareFabClick}"
android:tint="@android:color/white"
app:fabSize="mini"
app:srcCompat="@drawable/ic_share_black_24dp" />
</LinearLayout>
<LinearLayout
android:id="@+id/createLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="invisible"
app:layout_constraintBottom_toTopOf="@+id/baseFloatingActionButton"
app:layout_constraintRight_toRightOf="@+id/activity_main">
<TextView
android:id="@+id/createLabelTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:background="@drawable/shape_fab_label"
android:elevation="2dp"
android:fontFamily="sans-serif"
android:padding="5dip"
android:text="Create"
android:textColor="@android:color/white"
android:typeface="normal" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/createFab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:onClick="@{FabHandler::onCreateFabClick}"
android:tint="@android:color/white"
app:fabSize="mini"
app:srcCompat="@drawable/ic_create_black_24dp" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>
Dies sind die Animationen
Eröffnungsanimation des FAB-Menüs:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<scale
android:duration="300"
android:fromXScale="0"
android:fromYScale="0"
android:interpolator="@android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1" />
<alpha
android:duration="300"
android:fromAlpha="0.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="1.0" />
</set>
Abschlussanimation des FAB-Menüs:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<scale
android:duration="300"
android:fromXScale="1"
android:fromYScale="1"
android:interpolator="@android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0.0"
android:toYScale="0.0" />
<alpha
android:duration="300"
android:fromAlpha="1.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="0.0" />
</set>
Dann habe ich in meiner Aktivität einfach die obigen Animationen verwendet, um das FAB-Menü ein- und auszublenden:
Fab-Menü anzeigen:
private void expandFabMenu() {
ViewCompat.animate(binding.baseFloatingActionButton).rotation(45.0F).withLayer().setDuration(300).setInterpolator(new OvershootInterpolator(10.0F)).start();
binding.createLayout.startAnimation(fabOpenAnimation);
binding.shareLayout.startAnimation(fabOpenAnimation);
binding.createFab.setClickable(true);
binding.shareFab.setClickable(true);
isFabMenuOpen = true;
}
Fab-Menü schließen:
private void collapseFabMenu() {
ViewCompat.animate(binding.baseFloatingActionButton).rotation(0.0F).withLayer().setDuration(300).setInterpolator(new OvershootInterpolator(10.0F)).start();
binding.createLayout.startAnimation(fabCloseAnimation);
binding.shareLayout.startAnimation(fabCloseAnimation);
binding.createFab.setClickable(false);
binding.shareFab.setClickable(false);
isFabMenuOpen = false;
}
Hier ist die Aktivitätsklasse -
package com.app.fabmenu;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.view.ViewCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.OvershootInterpolator;
import com.app.fabmenu.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private Animation fabOpenAnimation;
private Animation fabCloseAnimation;
private boolean isFabMenuOpen = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setFabHandler(new FabHandler());
getAnimations();
}
private void getAnimations() {
fabOpenAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_open);
fabCloseAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_close);
}
private void expandFabMenu() {
ViewCompat.animate(binding.baseFloatingActionButton).rotation(45.0F).withLayer().setDuration(300).setInterpolator(new OvershootInterpolator(10.0F)).start();
binding.createLayout.startAnimation(fabOpenAnimation);
binding.shareLayout.startAnimation(fabOpenAnimation);
binding.createFab.setClickable(true);
binding.shareFab.setClickable(true);
isFabMenuOpen = true;
}
private void collapseFabMenu() {
ViewCompat.animate(binding.baseFloatingActionButton).rotation(0.0F).withLayer().setDuration(300).setInterpolator(new OvershootInterpolator(10.0F)).start();
binding.createLayout.startAnimation(fabCloseAnimation);
binding.shareLayout.startAnimation(fabCloseAnimation);
binding.createFab.setClickable(false);
binding.shareFab.setClickable(false);
isFabMenuOpen = false;
}
public class FabHandler {
public void onBaseFabClick(View view) {
if (isFabMenuOpen)
collapseFabMenu();
else
expandFabMenu();
}
public void onCreateFabClick(View view) {
Snackbar.make(binding.coordinatorLayout, "Create FAB tapped", Snackbar.LENGTH_SHORT).show();
}
public void onShareFabClick(View view) {
Snackbar.make(binding.coordinatorLayout, "Share FAB tapped", Snackbar.LENGTH_SHORT).show();
}
}
@Override
public void onBackPressed() {
if (isFabMenuOpen)
collapseFabMenu();
else
super.onBackPressed();
}
}
Hier sind die Screenshots
Eine weitere Bibliothek, die die Kurzwahl gemäß den Richtlinien für das Materialdesign implementiert :
Als ich versuchte, etwas zu erstellen, das der schwebenden Aktionsschaltfläche im Posteingang ähnelt, dachte ich darüber nach, eine eigene benutzerdefinierte Komponente zu erstellen.
Es wäre ein einfaches Rahmenlayout mit fester Höhe (um ein erweitertes Menü zu enthalten), das die FAB-Schaltfläche und 3 weitere unter dem FAB enthält. Wenn Sie auf FAB klicken, animieren Sie einfach andere Schaltflächen, um sie unter dem FAB zu übersetzen.
Es gibt einige Bibliotheken, die das tun (zum Beispiel https://github.com/futuresimple/android-floating-action-button ), aber es macht immer mehr Spaß, wenn Sie es selbst erstellen :)
layout_anchor
und layout_anchorGravity
arbeiten nicht für mich
Sie können die FloatingActionMenu-Bibliothek verwenden oder hier klicken, um eine schrittweise Anleitung zu erhalten. Ausgabe des Tutorials:
Ich benutze diese Bibliothek, um dies zu tun: https://github.com/futuresimple/android-floating-action-button
Ziemlich einfach zu bedienen;)
layout_anchor
und layout_anchorGravity
arbeiten nicht für mich
Eine weitere Option für dasselbe Ergebnis mit ConstraintSet-Animation:
1) Fügen Sie alle animierten Ansichten in ein ConstraintLayout ein
2) Animieren Sie es aus Code wie diesem (wenn Sie weitere Effekte wünschen, liegt es an Ihnen ... dies ist nur ein Beispiel)
menuItem1 und menuItem2 sind die ersten und zweiten FABs im Menü, descriptionItem1 und descriptionItem2 ist die Beschreibung links vom Menü. parentConstraintLayout ist das Stamm-ConstraintLayout, das alle animierten Ansichten enthält. isMenuOpened ist eine Funktion zum Ändern des offenen / geschlossenen Flags im Status
Ich habe Animationscode in die Erweiterungsdatei eingefügt, aber es ist nicht notwendig.
fun FloatingActionButton.expandMenu(
menuItem1: View,
menuItem2: View,
descriptionItem1: TextView,
descriptionItem2: TextView,
parentConstraintLayout: ConstraintLayout,
isMenuOpened: (Boolean)-> Unit
) {
val constraintSet = ConstraintSet()
constraintSet.clone(parentConstraintLayout)
constraintSet.setVisibility(descriptionItem1.id, View.VISIBLE)
constraintSet.clear(menuItem1.id, ConstraintSet.TOP)
constraintSet.connect(menuItem1.id, ConstraintSet.BOTTOM, this.id, ConstraintSet.TOP, 0)
constraintSet.connect(menuItem1.id, ConstraintSet.START, this.id, ConstraintSet.START, 0)
constraintSet.connect(menuItem1.id, ConstraintSet.END, this.id, ConstraintSet.END, 0)
constraintSet.setVisibility(descriptionItem2.id, View.VISIBLE)
constraintSet.clear(menuItem2.id, ConstraintSet.TOP)
constraintSet.connect(menuItem2.id, ConstraintSet.BOTTOM, menuItem1.id, ConstraintSet.TOP, 0)
constraintSet.connect(menuItem2.id, ConstraintSet.START, this.id, ConstraintSet.START, 0)
constraintSet.connect(menuItem2.id, ConstraintSet.END, this.id, ConstraintSet.END, 0)
val transition = AutoTransition()
transition.duration = 150
transition.interpolator = AccelerateInterpolator()
transition.addListener(object: Transition.TransitionListener {
override fun onTransitionEnd(p0: Transition) {
isMenuOpened(true)
}
override fun onTransitionResume(p0: Transition) {}
override fun onTransitionPause(p0: Transition) {}
override fun onTransitionCancel(p0: Transition) {}
override fun onTransitionStart(p0: Transition) {}
})
TransitionManager.beginDelayedTransition(parentConstraintLayout, transition)
constraintSet.applyTo(parentConstraintLayout)
}