webentwicklung-frage-antwort-db.com.de

Android Design Library - Floating Action Button Padding / Margin Issues

Ich verwende den neuen FloatingActionButton aus der Google Design Library und bekomme seltsame Probleme beim Auffüllen/Rand. Dieses Bild (mit aktivierten Entwicklerlayoutoptionen) stammt aus API 22.

enter image description here

Und von API 17.

enter image description here

Dies ist das XML

<Android.support.design.widget.FloatingActionButton
        Android:id="@+id/fab"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_alignParentEnd="true"
        Android:layout_gravity="bottom|right"
        Android:layout_marginLeft="16dp"
        Android:layout_marginRight="20dp"
        Android:layout_marginTop="-32dp"
        Android:src="@drawable/ic_action_add"
        app:fabSize="normal"
        app:elevation="4dp"
        app:borderWidth="0dp"
        Android:layout_below="@+id/header"/>

Warum ist der FAB in API 17 in Bezug auf die Polsterung/den Rand so viel größer?

108
hitch.united

pdate (Okt 2016):

Die richtige Lösung besteht nun darin, app:useCompatPadding="true" in Ihren FloatingActionButton. Dadurch wird das Auffüllen zwischen verschiedenen API-Versionen konsistent. Dies scheint jedoch die Standardränder ein wenig zu verringern, so dass Sie diese möglicherweise anpassen müssen. Zumindest sind keine API-spezifischen Stile mehr erforderlich.

Vorherige Antwort:

Sie können dies einfach mit API-spezifischen Stilen erreichen. In deinem normalen values/styles.xml, setze so etwas:

<style name="floating_action_button">
    <item name="Android:layout_marginLeft">0dp</item>
    <item name="Android:layout_marginTop">0dp</item>
    <item name="Android:layout_marginRight">8dp</item>
    <item name="Android:layout_marginBottom">0dp</item>
</style>

verwenden Sie dann unter values-v21/styles.xml Folgendes:

<style name="floating_action_button">
    <item name="Android:layout_margin">16dp</item>
</style>

und wende den Stil auf deinen FloatingActionButton an:

<Android.support.design.widget.FloatingActionButton
...
style="@style/floating_action_button"
...
/>

Wie andere angemerkt haben, wird in API <20 durch die Schaltfläche ein eigener Schatten gerendert, der zur logischen Gesamtbreite der Ansicht beiträgt, während in API> = 20 die neuen Höhenparameter verwendet werden, die nicht zur Ansichtsbreite beitragen.

128
Dmitry Brant

Nie mehr fummeln mit styles.xml oder mit .Java Dateien. Lass es mich einfach machen.

Sie können app:useCompatPadding="true" und entfernen Sie benutzerdefinierte Ränder, um gleiche Ränder für verschiedene Android-Versionen beizubehalten

Der zusätzliche Rand/Abstand, den Sie auf dem FAB in Ihrem zweiten Bild gesehen haben, ist auf diese compatPadding on pre-Lollipop Geräte zurückzuführen. Wenn diese Eigenschaft nicht festgelegt ist, wird sie auf pre-lollopop Geräten und NOT in Lollipop + Geräten angewendet.

Android studio code

Konzeptioneller Beweiß

design view

nach ein paar Such- und Testläufen behebe ich mein Problem, indem ich diese Zeile nur zu meinem XML-Layout hinzufüge:

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

und das ist mein ganzes float button layout

<Android.support.design.widget.FloatingActionButton
        Android:id="@+id/fab"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_alignParentBottom="true"
        Android:layout_alignParentRight="true"
        Android:layout_marginRight="16dp"
        Android:layout_marginBottom="16dp"
        Android:src="@drawable/ic_add"
        app:elevation="0dp"
        app:pressedTranslationZ="0dp"
        app:fabSize="normal" />
30
Mostafa Rostami

In der Design Support Library ist ein Problem aufgetreten. Verwenden Sie die folgende Methode, um dieses Problem zu beheben, bis die Bibliothek aktualisiert wurde. Fügen Sie diesen Code zu Ihrer Aktivität oder Ihrem Fragment hinzu, um das Problem zu beheben. Behalten Sie Ihre XML-Datei bei. Auf Lollipop und darüber gibt es keinen Rand, aber darunter gibt es einen Rand von 16 dpi.

pdate Working Example

XML - FAB befindet sich in einem RelativeLayout

<Android.support.design.widget.FloatingActionButton
    Android:id="@+id/fab"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:layout_alignParentBottom="true"
    Android:layout_alignParentRight="true"
    Android:layout_marginBottom="16dp"
    Android:layout_marginRight="16dp"
    Android:src="@mipmap/ic_add"
    app:backgroundTint="@color/accent"
    app:borderWidth="0dp"
    app:elevation="4sp"/>

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

Konvertiere dp zu 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().getDisplayMetrics().density;
    return (int) ((dp * scale) + 0.5f);
}

Lutscher

enter image description here

Pre Lollipop

enter image description here

21
Eugene H

Vor Lollipop ist FloatingActionButton für das Zeichnen seines eigenen Schattens verantwortlich. Daher muss die Ansicht etwas größer sein, um Platz für den Schatten zu schaffen. Um ein konsistentes Verhalten zu erzielen, können Sie Ränder festlegen, um den Unterschied in Höhe und Breite zu berücksichtigen. Ich benutze derzeit die folgenden Klasse :

import Android.content.Context;
import Android.content.res.TypedArray;
import Android.support.design.widget.FloatingActionButton;
import Android.util.AttributeSet;
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, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomFloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.obtainStyledAttributes(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);
        }
    }
}

Update: Android Support Libraries v23 umbenannt in fab_size dimens in:

import static Android.support.design.R.dimen.design_fab_size_normal;
import static Android.support.design.R.dimen.design_fab_size_mini;
8
Markus Rubey

Markus 'Antwort hat gut funktioniert, nachdem ich auf v23.1.0 aktualisiert und einige Anpassungen an den Importen vorgenommen habe (mit dem aktuellen Gradle-Plugin verwenden wir unsere App R anstelle des R der Designbibliothek). Hier ist der Code für 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, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    @SuppressLint("PrivateResource")
    public CustomFloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.obtainStyledAttributes(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);
        }
    }
}
5
Learn OpenGL ES

Setzen Sie in der Layoutdatei das Attribut elevation auf 0., da es die Standardhöhe annimmt.

app:elevation="0dp"

Überprüfen Sie jetzt in der Aktivität, ob der API-Level größer als 21 ist, und stellen Sie bei Bedarf die Höhe ein.

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