Bibliothèque de conception Android – Rembourrage des boutons d’action flottants / Problèmes de marge

J’utilise le nouveau FloatingActionButton de la bibliothèque de conception de Google et je ressens d’étranges problèmes de remplissage / marge. Cette image (avec les options de mise en page du développeur) provient de l’API 22.

entrer la description de l'image ici

Et de l’API 17.

entrer la description de l'image ici

Ceci est le XML

 

Pourquoi le FAB dans l’API 17 est-il tellement plus grand en termes de remplissage / marge?

Mise à jour (octobre 2016):

La solution correcte maintenant est de mettre app:useCompatPadding="true" dans votre FloatingActionButton. Cela rendra le remplissage cohérent entre les différentes versions de l’API. Cependant, cela semble encore réduire légèrement les marges par défaut, vous devrez donc peut-être les ajuster. Mais au moins, il n’y a plus besoin de styles spécifiques à l’API.

Réponse précédente:

Vous pouvez accomplir cela facilement en utilisant des styles spécifiques à l’API. Dans vos values/styles.xml normales values/styles.xml , mettez quelque chose comme ceci:

  

puis sous valeurs-v21 / styles.xml, utilisez ceci:

  

et appliquer le style à votre FloatingActionButton:

  

Comme d’autres l’ont noté, dans l’API <20, le bouton affiche sa propre ombre, ce qui ajoute à la largeur logique globale de la vue, alors que dans API> = 20, il utilise les nouveaux parameters Elevation qui ne consortingbuent pas à la largeur de la vue.

Plus styles.xml de styles.xml avec styles.xml ou avec les fichiers .java . Laissez-moi le rendre simple.

Vous pouvez utiliser app:useCompatPadding="true" et supprimer les marges personnalisées pour conserver les mêmes marges sur les différentes versions d’android

La marge / remplissage supplémentaire que vous avez vue sur le FAB dans votre deuxième image est due à ce compatPadding sur les périphériques pré-sucette . Si cette propriété n’est pas définie, elle est appliquée sur les périphériques pré-lollopop et non sur les périphériques sucette +.

code studio Android

Preuve de concept

vue de conception

Après quelques temps de recherche et de solution de test, je résous mon problème avec l’ajout de cette ligne à ma mise en page XML uniquement:

 app:elevation="0dp" app:pressedTranslationZ="0dp" 

et c’est ma disposition entière de bouton de flotteur

  

Il existe un problème au sein de la bibliothèque de support de conception. Utilisez la méthode ci-dessous pour résoudre ce problème jusqu’à ce que la bibliothèque soit mise à jour. Essayez d’append ce code à votre activité ou à votre fragment pour résoudre le problème. Gardez votre xml le même. Sur la sucette et au-dessus, il n’y a pas de marge mais en dessous, il y a une marge de 16dp.

Mettre à jour l’exemple de travail

XML – FAB est dans un RelativeLayout

  

Java

 FloatingActionButton mFab = (FloatingActionButton) v.findViewById(R.id.fab); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) mFab.getLayoutParams(); p.setMargins(0, 0, dpToPx(getActivity(), 8), 0); // get rid of margins since shadow area is now the margin mFab.setLayoutParams(p); } 

Convertir dp en px

 public static int dpToPx(Context context, float dp) { // Reference http://stackoverflow.com/questions/8309354/formula-px-to-dp-dp-to-px-android float scale = context.getResources().getDisplayMesortingcs().density; return (int) ((dp * scale) + 0.5f); } 

Sucette

entrer la description de l'image ici

Pré sucette

entrer la description de l'image ici

Sur Lollipop, FloatingActionButton est responsable de dessiner sa propre ombre. Par conséquent, la vue doit être légèrement plus grande pour faire de la place à l’ombre. Pour obtenir un comportement cohérent, vous pouvez définir des marges pour tenir compte de la différence de hauteur et de largeur. J’utilise actuellement la classe suivante:

 import android.content.Context; import android.content.res.TypedArray; import android.support.design.widget.FloatingActionButton; import android.util.AtsortingbuteSet; import android.view.ViewGroup.MarginLayoutParams; import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION_CODES.LOLLIPOP; import static android.support.design.R.styleable.FloatingActionButton; import static android.support.design.R.styleable.FloatingActionButton_fabSize; import static android.support.design.R.style.Widget_Design_FloatingActionButton; import static android.support.design.R.dimen.fab_size_normal; import static android.support.design.R.dimen.fab_size_mini; public class CustomFloatingActionButton extends FloatingActionButton { private int mSize; public CustomFloatingActionButton(Context context) { this(context, null); } public CustomFloatingActionButton(Context context, AtsortingbuteSet attrs) { this(context, attrs, 0); } public CustomFloatingActionButton(Context context, AtsortingbuteSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray a = context.obtainStyledAtsortingbutes(attrs, FloatingActionButton, defStyleAttr, Widget_Design_FloatingActionButton); this.mSize = a.getInt(FloatingActionButton_fabSize, 0); a.recycle(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); if (SDK_INT < LOLLIPOP) { int size = this.getSizeDimension(); int offsetVertical = (h - size) / 2; int offsetHorizontal = (w - size) / 2; MarginLayoutParams params = (MarginLayoutParams) getLayoutParams(); params.leftMargin = params.leftMargin - offsetHorizontal; params.rightMargin = params.rightMargin - offsetHorizontal; params.topMargin = params.topMargin - offsetVertical; params.bottomMargin = params.bottomMargin - offsetVertical; setLayoutParams(params); } } private final int getSizeDimension() { switch (this.mSize) { case 0: default: return this.getResources().getDimensionPixelSize(fab_size_normal); case 1: return this.getResources().getDimensionPixelSize(fab_size_mini); } } } 

Mise à jour: Les bibliothèques de support Android v23 renommées fab_size dimens pour:

 import static android.support.design.R.dimen.design_fab_size_normal; import static android.support.design.R.dimen.design_fab_size_mini; 

La réponse de Markus a bien fonctionné pour moi après avoir effectué la mise à jour vers la version 23.1.0 et apporté quelques modifications aux importations (avec le récent plug-in Gradle, nous utilisons notre application R au lieu de la bibliothèque de conception). Voici le code pour la v23.1.0:

 // Based on this answer: https://stackoverflow.com/a/30845164/1317564 public class CustomFloatingActionButton extends FloatingActionButton { private int mSize; public CustomFloatingActionButton(Context context) { this(context, null); } public CustomFloatingActionButton(Context context, AtsortingbuteSet attrs) { this(context, attrs, 0); } @SuppressLint("PrivateResource") public CustomFloatingActionButton(Context context, AtsortingbuteSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray a = context.obtainStyledAtsortingbutes(attrs, R.styleable.FloatingActionButton, defStyleAttr, R.style.Widget_Design_FloatingActionButton); mSize = a.getInt(R.styleable.FloatingActionButton_fabSize, 0); a.recycle(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { int size = this.getSizeDimension(); int offsetVertical = (h - size) / 2; int offsetHorizontal = (w - size) / 2; ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) getLayoutParams(); params.leftMargin = params.leftMargin - offsetHorizontal; params.rightMargin = params.rightMargin - offsetHorizontal; params.topMargin = params.topMargin - offsetVertical; params.bottomMargin = params.bottomMargin - offsetVertical; setLayoutParams(params); } } @SuppressLint("PrivateResource") private int getSizeDimension() { switch (mSize) { case 1: return getResources().getDimensionPixelSize(R.dimen.design_fab_size_mini); case 0: default: return getResources().getDimensionPixelSize(R.dimen.design_fab_size_normal); } } } 

Dans le fichier de présentation, définissez l’élévation de l’atsortingbut sur 0. car elle prend l’altitude par défaut.

 app:elevation="0dp" 

Maintenant, en activité, vérifiez le niveau d’API supérieur à 21 et définissez l’élévation si nécessaire.

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { fabBtn.setElevation(10.0f); }