Androiddevise库 – 浮动操作button填充/保证金问题

我正在使用Googledevise库中的新FloatingActionButton,我收到了一些奇怪的填充/边距问题。 这个图像(与开发人员的布局选项)来自API 22。

在这里输入图像说明

并从API 17。

在这里输入图像说明

这是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有更大的填充/余量?

更新(2016年10月):

现在正确的解决scheme是将app:useCompatPadding="true"放入您的FloatingActionButton。 这将使不同的API版本之间的填充一致。 但是,这似乎仍然会使默认边距稍微偏离一些,因此您可能需要调整这些边距。 但至less不需要特定于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中,button呈现自己的阴影,这会增加视图的整体逻辑宽度,而在API> = 20中,它将使用不影响视图宽度的新Elevation参数。

没有更多的 styles.xml.java文件摆弄 。 让我简单说一下。

您可以使用app:useCompatPadding="true"并删除自定义边距,以在不同版本的Android中保持相同的边距

在第二张图片中,您在FAB上看到的额外的边距/填充是由于棒棒糖设备上的这个补丁 。 如果这个属性没有设置,它会应用在pre-lollopop设备上,而不是在棒棒糖+设备上。

android studio代码

概念validation

设计视图

经过几次search和testing解决scheme我解决了我的问题,只添加此行到我的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" /> 

devise支持库中存在一个问题。 使用下面的方法来解决这个问题,直到库更新。 尝试将此代码添加到您的活动或片段来解决问题。 保持你的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转换为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); } 

棒糖

在这里输入图像说明

前棒棒糖

在这里输入图像说明

在棒棒堂前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维度重命名为:

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

在更新到v23.1.0并对导入进行一些调整(最近的gradle插件使用我们的应用程序R而不是devise库的R)后, Markus的回答很好。 这里是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.因为它采用默认高程。

 app:elevation="0dp" 

现在在活动检查api级别大于21,如果需要设置高程。

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