Android Design Library - Floating Action Button Padding/Margin Issues

后端 未结 7 2165
梦毁少年i
梦毁少年i 2020-12-02 05:14

I\'m using the new FloatingActionButton from the Google Design Library and I am getting some strange padding/margin problems. This image (with developer layout options on) i

相关标签:
7条回答
  • 2020-12-02 05:54

    On pre Lollipop FloatingActionButton is responsible for drawing its own shadow. Therefore the view has to be slightly bigger to make space for the shadow. To get a consistent behavior you can set margins to account for the difference in height and width. I am currently using the following 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);
            }
        }
    }
    

    Update: Android Support Libraries v23 renamed fab_size dimens to:

    import static android.support.design.R.dimen.design_fab_size_normal;
    import static android.support.design.R.dimen.design_fab_size_mini;
    
    0 讨论(0)
  • 2020-12-02 05:57

    No more fiddling with styles.xml or with .java files. Let me make it simple.

    You can use app:useCompatPadding="true" and remove custom margins to maintain same margins across different versions of android

    The extra margin/padding you saw on the FAB in your second picture is due to this compatPadding on pre-lollipop devices. If this property is not set, it gets applied on pre-lollopop devices and NOT in lollipop+ devices.

    Proof of concept

    0 讨论(0)
  • 2020-12-02 06:02

    In layout file set attribute elevation to 0. because it takes default elevation.

    app:elevation="0dp"
    

    Now in activity check api level greater than 21 and set elevation if needed.

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        fabBtn.setElevation(10.0f);
    }
    
    0 讨论(0)
  • 2020-12-02 06:03

    There is an issue within the Design Support Library. Use the method below to fix this issue until the library is updated. Try adding this code to your activity or fragment to solve the issue. Keep your xml the same. On lollipop and above there is no margin but below there is a margin of 16dp.

    Update Working Example

    XML - FAB is within a 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);
    }
    

    Convert dp to to 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

    0 讨论(0)
  • 2020-12-02 06:09

    Markus's answer worked well for me after updating to v23.1.0 and making some adjustments to the imports (with the recent gradle plugin we use our app R instead of the design library's R). Here is the code for 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);
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-02 06:11

    after a few time searching and test solution i fix my problem with add this line to my xml layout only:

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

    and this is my whole 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" />
    
    0 讨论(0)
提交回复
热议问题