为样式中的子类定义layout_width和layout_height属性的默认值

wuj*_*jek 5 android android-custom-view android-styles

最小和目标 SDK 为 21 (Lollipop),不使用支持库。

我正在尝试创建一个浮动操作按钮。到目前为止一切顺利,它确实有效(基于其他一些 SO 线程),代码如下:

  • attrs.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
        <attr name="fabStyle" format="reference"/>
    
    </resources>
    
    Run Code Online (Sandbox Code Playgroud)
  • 样式.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
        <style name="MyTheme" parent="android:Theme.Material.Light.NoActionBar">
            <item name="floatingActionButtonStyle">@style/FabStyle</item>
        </style>
    
        <style name="FabStyle" parent="android:Widget.ImageButton">
            <item name="android:background">@drawable/ripple</item>
            <item name="android:elevation">4dp</item>
        </style>
    
    Run Code Online (Sandbox Code Playgroud)

(我希望按钮继承默认的 ImageButton 特性,并且看起来工作正常,这是正确的方法吗?)

  • 视图代码(注意第二个构造函数中自定义样式属性的用法):

    public class FloatingActionImageButton extends ImageButton {
    
        public FloatingActionImageButton(Context context) {
            this(context, null);
        }
    
        public FloatingActionImageButton(Context context, AttributeSet attrs) {
            this(context, attrs, R.attr.floatingActionButtonStyle);
        }
    
        public FloatingActionImageButton(Context context, AttributeSet attrs, int defStyleAttr) {
            this(context, attrs, defStyleAttr, 0);
        }
    
        public FloatingActionImageButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
    
            setOutlineProvider(new ViewOutlineProvider() {
    
                @Override
                public void getOutline(View view, Outline outline) {
                    int width = view.getMeasuredWidth();
                    int height = view.getMeasuredHeight();
                    outline.setOval(0, 0, width, height);
                }
            });
            setClipToOutline(true);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 波纹.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <ripple xmlns:android="http://schemas.android.com/apk/res/android"
            android:color="?android:attr/colorPrimary">
    
        <item android:drawable="?android:attr/colorAccent"/>
    
    </ripple>
    
    Run Code Online (Sandbox Code Playgroud)
  • XML 中的用法:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                    xmlns:tools="http://schemas.android.com/tools"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    tools:context="com.test.TestActivity">
    
        <com.test.FloatingActionImageButton
            android:id="@+id/refresh_button"
            android:layout_width="@dimen/fab_size"
            android:layout_height="@dimen/fab_size"
            android:layout_alignParentBottom="true"
            android:layout_alignParentEnd="true"
            android:layout_marginBottom="@dimen/padding_big"
            android:layout_marginEnd="@dimen/padding_big"
            android:src="@drawable/ic_action_restart"/>
    
    </RelativeLayout>
    
    Run Code Online (Sandbox Code Playgroud)

(@dimen/fab_size 为 56dp)

结果是一个看起来很漂亮的高架 FAB,具有按预期发挥作用的连锁反应:

很棒的

  1. 由于这是我第一次在 Android 中尝试样式等,我想问一下我所做的是否是“canon”。如果我想发布我自己的 Fab-ulous 库,我该怎么做?样式代码现在是否已准备好供我的库的潜在客户在其 styles.xml 中以某种方式(如何?)定义 fabStyle,并且我的视图将使用这些设置?

  2. 我对我的解决方案不满意的是,尽管我希望所有 FAB 均为 56dp(正如 Google 在上面链接的文档中建议的那样),但每当在 XML 中使用 fab 时,我都必须定义大小。由于我希望按钮默认为 56dp,我尝试将layout_width 和 _height 放入 FabStyle 中并从 XML 中删除,但 AndroidStudio 说我应该设置它们,并且应用程序实际上在运行时崩溃,说需要设置这些值。

我尝试在 XML 中设置 @null(它崩溃了)和 0dp/px,这只是使按钮不可见......

是否可以为这些属性定义默认值,或者我在这里运气不好?