web-dev-qa-db-ja.com

Android Design Library-フローティングアクションボタンのパディング/マージンの問題

Googleデザインライブラリの新しいFloatingActionButtonを使用していますが、奇妙なパディング/マージンの問題が発生しています。この画像(開発者レイアウトオプションがオン)は、API 22のものです。

enter image description here

API 17から。

enter image description here

これは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"/>

API 17のFABのパディング/マージンが非常に大きいのはなぜですか?

106
hitch.united

更新(2016年10月):

正しい解決策は、app:useCompatPadding="true"をFloatingActionButtonに入れることです。これにより、異なるAPIバージョン間でパディングの一貫性が保たれます。ただし、これはまだデフォルトのマージンを少しオフにするようですので、それらを調整する必要があるかもしれません。ただし、少なくともAPI固有のスタイルは必要ありません。

前の回答:

これは、API固有のスタイルを使用して簡単に実現できます。通常のvalues/styles.xmlに、次のようなものを入れます。

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

そして、values-v21/styles.xmlの下で、これを使用します:

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

そして、FloatingActionButtonにスタイルを適用します。

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

他の人が指摘したように、API <20では、ボタンは独自の影をレンダリングし、ビューの全体的な論理幅を追加しますが、API> = 20では、ビューの幅に寄与しない新しいElevationパラメーターを使用します。

126
Dmitry Brant

これ以上いじる必要はありませんstyles.xmlまたは.Javaファイル。私はそれを簡単にしてみましょう。

app:useCompatPadding="true"を使用し、カスタムマージンを削除して、Androidの異なるバージョン間で同じマージンを維持できます。

2番目の写真のFABで見た余分なマージン/パディングは、これが原因ですcompatPadding onpre-Lollipopデバイス。このプロパティが設定されていない場合、pre-lollopopデバイスおよびLollipop +デバイスのNOTに適用されます。

Android studio code

コンセプトの証明

design view

数回の検索とテストソリューションの後、私はこの行を私のXMLレイアウトにのみ追加することで私の問題を修正します:

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

これはフロートボタンの全体レイアウトです

<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" />
28
Mostafa Rostami

Design Support Library内に問題があります。以下の方法を使用して、ライブラリが更新されるまでこの問題を修正します。このコードをアクティビティまたはフラグメントに追加して、問題を解決してください。 xmlを同じにしてください。 Lollipop以上ではマージンはありませんが、下では16dpのマージンがあります。

作業例の更新

XML-FABは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);
}

Dpから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);
}

ロリポップ

enter image description here

Pre Lollipop

enter image description here

21
Eugene H

事前にLollipop FloatingActionButtonは独自の影を描画します。したがって、影用のスペースを確保するには、ビューを少し大きくする必要があります。一貫した動作を実現するために、高さと幅の違いを考慮してマージンを設定できます。現在、次の class を使用しています。

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

更新:Android Support Libraries v23はfab_size dimensの名前を次のように変更しました:

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の答え v23.1.0に更新し、インポートを調整した後(デザインライブラリのRではなくアプリRを使用する最近のgradleプラグインを使用)、私にとってはうまくいきました。 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

レイアウトファイルでは、属性の標高を0に設定します。デフォルトの標高を使用するためです。

app:elevation="0dp"

アクティビティで21を超えるapiレベルをチェックし、必要に応じて高度を設定します。

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