Maintenant que la bibliothèque de support de conception Android est sortie, est-ce que quelqu'un sait comment implémenter le menu Fab étendu avec elle, comme le fab sur l'application Inbox?
Devrait ressembler à ceci:
Maintenant que la bibliothèque de support de conception Android est sortie, est-ce que quelqu'un sait comment implémenter le menu Fab étendu avec elle, comme le fab sur l'application Inbox?
Devrait ressembler à ceci:
Réponses:
Actuellement, aucun widget n'est fourni dans la bibliothèque de conception. La seule façon de le faire rapidement et facilement est d'utiliser des bibliothèques tierces.
Vous pouvez évidemment le faire en utilisant la bibliothèque de conception, mais ce sera un travail énorme et nécessitera beaucoup de temps. J'ai mentionné quelques bibliothèques utiles, qui peuvent vous aider à atteindre cet objectif.
J'utilise le 4ème.
Vous avez une meilleure approche pour implémenter le menu FAB animé sans utiliser de bibliothèque ou pour écrire un énorme code XML pour les animations. J'espère que cela aidera à l'avenir pour quelqu'un qui a besoin d'un moyen simple de le mettre en œuvre.
En utilisant simplement la animate().translationY()
fonction, vous pouvez animer n'importe quelle vue vers le haut ou vers le bas, comme je l'ai fait dans mon code ci-dessous, vérifiez le code complet dans github . Si vous recherchez le même code dans kotlin, vous pouvez consulter le menu d' animation FAB du repo de code kotlin .
définissez d'abord tous vos FAB au même endroit afin qu'ils se chevauchent, rappelez-vous en haut que le FAB doit être celui que vous voulez cliquer et en afficher les autres. par exemple:
<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" />
Maintenant, dans votre classe java, définissez simplement tous vos FAB et effectuez le clic comme indiqué ci-dessous:
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();
}
}
});
Utilisez le animation().translationY()
pour animer votre FAB, je préfère que vous utilisiez l'attribut de cette méthode dans DP car seule l'utilisation d'un int affectera la compatibilité d'affichage avec une résolution plus élevée ou une résolution inférieure. comme indiqué ci-dessous:
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);
}
Définissez maintenant la dimension mentionnée ci-dessus dans res-> values-> dimens.xml comme indiqué ci-dessous:
<dimen name="standard_55">55dp</dimen>
<dimen name="standard_105">105dp</dimen>
<dimen name="standard_155">155dp</dimen>
C'est tout l'espoir que cette solution aidera les gens à l'avenir, qui recherchent une solution simple.
ÉDITÉ
Si vous souhaitez ajouter une étiquette sur le FAB, prenez simplement un LinearLayout horizontal et placez le FAB avec textview comme étiquette, et animez les mises en page si vous rencontrez un problème en faisant cela, vous pouvez vérifier mon exemple de code dans github, j'ai géré toute la compatibilité descendante problèmes dans cet exemple de code. vérifier mon exemple de code pour FABMenu dans Github
pour fermer le FAB sur Backpress, remplacez onBackPress () comme indiqué ci-dessous:
@Override
public void onBackPressed() {
if(!isFABOpen){
this.super.onBackPressed();
}else{
closeFABMenu();
}
}
La capture d'écran a également le titre avec le FAB, car je le prends de mon exemple d'application présent dans
Commencez par créer les dispositions de menu dans le fichier xml de votre disposition d'activité. Par exemple, une mise en page linéaire avec une orientation horizontale et inclure un TextView pour l'étiquette puis un bouton d'action flottant à côté de TextView.
Créez les dispositions de menu selon vos besoins et votre numéro.
Créez un bouton d'action flottant de base et en cliquant dessus, modifiez la visibilité des dispositions de menu.
Veuillez vérifier le code ci-dessous pour la référence et pour plus d'informations, consultez mon projet depuis github
Commander un projet depuis 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>
Ce sont les animations-
Animation d'ouverture du menu FAB:
<?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>
Animation de fermeture du menu FAB:
<?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>
Ensuite, dans mon activité, j'ai simplement utilisé les animations ci-dessus pour afficher et masquer le menu FAB:
Afficher le menu Fab:
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;
}
Fermer le menu Fab:
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;
}
Voici la classe d'activité -
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();
}
}
Voici les captures d'écran
Une autre bibliothèque mettant en œuvre le numéro abrégé à partir des directives de conception de matériaux:
Lorsque j'ai essayé de créer quelque chose de similaire au bouton d'action flottant de la boîte de réception, j'ai pensé à créer mon propre composant personnalisé.
Ce serait une simple mise en page de cadre avec une hauteur fixe (pour contenir le menu développé) contenant le bouton FAB et 3 autres placés sous le FAB. lorsque vous cliquez sur FAB, vous animez simplement d'autres boutons à traduire sous le FAB.
Il existe des bibliothèques qui font cela (par exemple https://github.com/futuresimple/android-floating-action-button ), mais c'est toujours plus amusant si vous le créez vous-même :)
layout_anchor
et layout_anchorGravity
ne travaillent pas pour moi
Vous pouvez utiliser la bibliothèque FloatingActionMenu ou cliquer ici pour un didacticiel étape par étape. Sortie du tutoriel:
J'utilise cette bibliothèque pour ce faire: https://github.com/futuresimple/android-floating-action-button
Assez simple à utiliser;)
layout_anchor
et layout_anchorGravity
ne travaillent pas pour moi
Une autre option pour le même résultat avec l'animation ConstraintSet:
1) Mettez toutes les vues animées dans un seul ConstraintLayout
2) Animez-le à partir d'un code comme celui-ci (si vous voulez plus d'effets, c'est à vous de décider ... ce n'est qu'un exemple)
menuItem1 et menuItem2 sont les premier et deuxième FAB dans le menu, descriptionItem1 et descriptionItem2 est la description à gauche du menu, parentConstraintLayout est la racine ConstraintLayout qui contient toutes les vues animées, isMenuOpened est une fonction pour changer le drapeau ouvert / fermé dans l'état
J'ai mis le code d'animation dans le fichier d'extension mais ce n'est pas nécessaire.
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)
}