Подтвердить что ты не робот

Android Design Library - Плавающая кнопка с кнопками ввода/маржи

Я использую новый FloatingActionButton из Библиотеки дизайна Google, и у меня возникают некоторые странные проблемы с заполнением/запасом. Это изображение (с вариантами макета разработчика) находится в 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"/>

Почему FAB в API 17 имеет гораздо больший размер/маржу?

4b9b3361

Ответ 1

Обновление (октябрь 2016):

Правильное решение теперь - положить 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>

а затем под значениями-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, которые не вносят вклад в ширина представления.

Ответ 2

Больше нет fidingling с styles.xml или с .java файлами. Позвольте мне сделать это простым.

Вы можете использовать app:useCompatPadding="true" и удалить настраиваемые поля для поддержки одинаковых полей в разных версиях android

Дополнительный запас/отступ, который вы видели на FAB на втором снимке, обусловлен этим compatPadding на устройствах с предварительным лечением. Если это свойство не установлено, оно применяется к устройствам с прелолопным приемом и NOT в устройствах с леденцом +.

код студии Android

Доказательство концепции

дизайн

Ответ 3

после нескольких поисковых и тестовых решений я исправлю свою проблему, добавив эту строку только в мой xml-макет:

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

и это все мое floatbutton layou

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

Ответ 4

В библиотеке поддержки дизайна есть проблема. Используйте этот метод, чтобы устранить эту проблему до тех пор, пока библиотека не будет обновлена. Попробуйте добавить этот код в свою деятельность или фрагмент, чтобы решить проблему. Храните свой xml так же. На леденец и выше нет разницы, но ниже есть маржа 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 в p 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);
}

Lollipop

enter image description here

Pre Lollipop

enter image description here

Ответ 5

В преддверии Lollipop FloatingActionButton отвечает за рисование собственной тени. Поэтому представление должно быть немного больше, чтобы создать пространство для тени. Чтобы получить согласованное поведение, вы можете установить поля для учета разницы в высоте и ширине. В настоящее время я использую следующий класс:

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

Ответ 6

Ответ Маркуса работал хорошо для меня после обновления до версии v.1.1.0 и внесения некоторых изменений в импорт (с недавним плагином gradle мы используем наше приложение R вместо библиотеки дизайна R). Вот код для v23.1.0:

// Based on this answer: /questions/59387/android-design-library-floating-action-button-paddingmargin-issues/412064#412064
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);
        }
    }
}

Ответ 7

В атрибуте атрибута набора макетов установите значение 0., поскольку оно принимает высоту по умолчанию.

app:elevation="0dp"

Теперь в действии проверьте уровень api, превышающий 21, и при необходимости установите высоту.

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