Android Tasarım Kitaplığı - Kayan İşlem Düğmesi Doldurma / Kenar Boşluğu Sorunları


109

Google Tasarım Kitaplığından yeni FloatingActionButton'ı kullanıyorum ve bazı garip dolgu / kenar boşluğu sorunları alıyorum. Bu görüntü (geliştirici düzeni seçenekleri açıkken) API 22'den alınmıştır.

görüntü açıklamasını buraya girin

Ve API 17'den.

görüntü açıklamasını buraya girin

Bu 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'deki FAB neden bu kadar büyük dolgu / kenar boşluğu açısından akıllıca?


1
CoordinatorLayoutDikey olarak hizalamanızı ve ekstra dolgulu ön lolipop göz küresini kullanmanızı öneririm . Derlenmiş FAB kaynaklarından bunu çözebilirsiniz, ancak Google'ın yaptığı gibi düzeltmesini beklemeyi tercih ederim CardView.
DariusL

Yanıtlar:


129

Güncelleme (Ekim 2016):

Şimdi doğru çözüm app:useCompatPadding="true"FloatingActionButton'unuza koymaktır . Bu, dolguyu farklı API sürümleri arasında tutarlı hale getirecektir. Ancak, bu hala varsayılan marjları biraz düşürüyor gibi görünüyor, bu yüzden bunları ayarlamanız gerekebilir. Ancak en azından API'ye özgü stillere artık gerek yok.

Önceki cevap:

API'ye özgü stilleri kullanarak bunu kolayca başarabilirsiniz. Normalde şöyle bir values/styles.xmlşey koy:

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

ve daha sonra values-v21 / styles.xml altında şunu kullanın:

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

ve stili FloatingActionButton'ınıza uygulayın:

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

Diğerlerinin de belirttiği gibi, API <20'de düğme, görünümün genel mantıksal genişliğini artıran kendi gölgesini oluştururken, API> = 20'de görünüm genişliğine katkıda bulunmayan yeni Yükseklik parametrelerini kullanır.


19
buggy Android .. :(
Abdullah Shoaib

3
gülünç derecede çirkin görünüyor, ancak başka bir çözüm yok gibi görünüyor
on bir

3
Güzel cevap, teşekkürler. Düzenlemenizi ve tablet için de bir stil eklemenizi önerebilir miyim? API> = 20 için marj 24dp'dir; API <20 için <item name = "android: layout_marginRight"> 12dp </item> <item name = "android: layout_marginBottom"> 6dp </item> 'ye ihtiyacınız olduğunu fark ettim . Bunları kendim hesaplamak zorunda kaldım çünkü uygulamam için buna ihtiyacım vardı. Stil yerine dimens kaynağını da kullanabilirsiniz .
JJ86

Marjin sayıları elevation, FAB'da ayarladığınız şeye bağlı olarak farklı olacaktır .
Jarett Millard

kullanımapp:useCompatPadding="true"
Kishan Vaghela

51

Artık işe yaramaz ile styles.xmlveya .javadosyalar. Bunu basitleştirmeme izin verin.

Android'in farklı sürümlerinde aynı kenar boşluklarınıapp:useCompatPadding="true" korumak için özel kenar boşluklarını kullanabilir ve kaldırabilirsiniz .

Eğer ikinci resimde FAB gördüğümüz ekstra marjı / doldurma buna bağlı olan compatPadding üzerinde önceden lolipop cihazlar. Bu özellik ayarlanmazsa, bu uygulanan alır öncesi lollopop cihazlar ve DEĞİL lolipop + cihazlarda.

android stüdyo kodu

Kavramın ispatı

tasarım görünümü


Ebeveyn düzeni kart görünümü ise, fab için "card_view: useCompatPadding =" true "kullanmamız gerekir.
Amit Tumkur

Bu, destek kitaplığını 23.2 sürümüne yükselttikten sonra benim için çalışıyor. Teşekkürler!
Pablo

PoC'nizde marjlar görüyorum.
Pedro Oliveira

@PedroOliveira Evet, Android'in tüm sürümlerinde aynı marjı göreceksiniz, bu aslında amaçtır.
Saravanabalagi Ramachandran

1
Özel kenar boşluklarını kaldırmak için "xxx" yi kullanabileceğini söylüyorsunuz, ancak yine de konsept kanıtınız, OP'nin nedenini sorduğu gibi tüm marjları gösteriyor.
Pedro Oliveira

31

Birkaç kez arama ve test çözümünden sonra bu satırı yalnızca xml düzenime ekleyerek sorunumu düzelttim:

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

ve bu benim tüm kayan düğme düzenim

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

2
Harika, benim için çalıştı. Ne useCompatPaddingne de başka hiçbir şey aynı sonucu alamaz.
bgplaya

1
Ben bu cevabı birleştirmek ettik Vikram en
ingkevin

22

Tasarım Destek Kitaplığı'nda bir sorun var. Kitaplık güncellenene kadar bu sorunu çözmek için aşağıdaki yöntemi kullanın. Sorunu çözmek için bu kodu faaliyetinize veya parçanıza eklemeyi deneyin. Xml'nizi aynı tutun. Lolipopta ve üstünde marj yoktur, ancak altında 16dp'lik bir marj vardır.

Çalışma Örneğini Güncelleme

XML - FAB bir RelativeLayout içinde

<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'yi piksele dönüştür

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

Lolipop

görüntü açıklamasını buraya girin

Lolipop Öncesi

görüntü açıklamasını buraya girin


Bu doğru cevap olmalı. Bununla birlikte, dolgu da kararsız olduğundan sorunu% 100 çözmez.
JohnnyLambada

@JohnnyLambada Sanmıyorum. RelativeLayout.LayoutParamsartığını edilemez LayoutParamsait FloatingActionButtonve ben ön Lollipop 16dp herhangi marjlarını görmüyorum. FloatingActionButtonLollipop öncesi genişliği 56dp yerine 84dp ve yüksekliği 98dp'dir.
Markus Rubey

@MarkusRubey Cevabımı çalışan bir örnek ve lolipop öncesi ve lolipop versiyonunu gösteren resimlerle güncelleyeceğim.
Eugene H

1
@MarkusRubey - içinde olduğu türden View.getLayoutParamsbir döndürür - Eugene'nin durumunda bu bir . LayoutParamsViewRelativeLayout.LayoutParams
JohnnyLambada

1
@EugeneH RelativeLayout.LayoutParams'ı ViewGroup.MarginLayoutParams olarak değiştirdim. Bu, kodun daha birçok durumda çalışmasını sağlayacak ve MarkusRubey'in ortaya çıkardığı sorunu çözecektir.
JohnnyLambada

8

Lollipop öncesi FloatingActionButtonkendi gölgesini çizmekten sorumludur. Bu nedenle, gölgeye yer açmak için görüşün biraz daha büyük olması gerekir. Tutarlı bir davranış elde etmek için, yükseklik ve genişlik farkını hesaba katmak için kenar boşlukları ayarlayabilirsiniz. Şu anda aşağıdaki sınıfı kullanıyorum :

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

Güncelleme: Android Support Libraries v23, fab_size dimens adını şu şekilde yeniden adlandırdı:

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

Projemi AndroidX'e yeniden düzenledim ve sizin örneğinizden 3. kurucuyu oluşturamıyorum. AndroidX kitaplıklarını kullanarak bunu nasıl yapabilirim?
Alon Shlider

5

Markus'un cevabı , v23.1.0'a güncelledikten ve içe aktarmalarda bazı ayarlamalar yaptıktan sonra benim için iyi çalıştı (son gradle eklentisiyle, tasarım kitaplığının R yerine uygulamamız R'yi kullanıyoruz). İşte v23.1.0 kodu:

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

Bu örneği AndroidX'e yeniden düzenleme yaptıktan sonra kullanamıyorum - 3. kurucu artık derlemiyor. Neyin yanlış olduğunu biliyor musun?
Alon Shlider

3

Düzen dosyasında, varsayılan yükseltmeyi aldığı için yükseklik özelliğini 0 olarak ayarlayın.

app:elevation="0dp"

Şimdi aktivitede 21'den büyük api seviyesini kontrol edin ve gerekirse yüksekliği ayarlayın.

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

Eğer kullanıyorsanız compat kütüphane kullanım setCompatElevation . Doğrudan pikseller yerine dipler kullanmak daha iyi olacaktır.
ingkevin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.