5

Min and target SDK are 21 (Lollipop), no support library is used.

I am trying to create a floating action button. So far so good, it does indeed work (based on a few other SO threads), here is the code:

  • attrs.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
        <attr name="fabStyle" format="reference"/>
    
    </resources>
    
  • styles.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>
    

(I want the button to inherit default ImageButton characteristics, and it seems to work fine, is this the correct way?)

  • the View code (notice the usage of the custom style attribute in the second constructor):

    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);
        }
    }
    
  • ripple.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>
    
  • usage in 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>
    

(@dimen/fab_size is 56dp)

The result is a nicely looking elevated FAB, with ripple effect working as intended:

fab

  1. As this is my first such attempt at styling etc. in Android, I would like to ask if what I'm doing is 'canon'. How would I go about it if I wanted to publish my very own Fab-ulous library? Is the styling code now ready for potential clients of my lib to just define the fabStyle somehow (how?) in their styles.xml and my View would use the settings?

  2. What I don't like about my solution is that although I would like all FABs to be 56dp, as suggested by the Google in the document linked above, I have to define the size whenever the fab is used in XML. As I would like the button to default to 56dp, I tried putting the layout_width and _height in the FabStyle and removing from the XML, but AndroidStudio says I should set them, and the application actually crashes at runtime saying the values need to be set.

I tried setting @null in the XML, which crashed, and 0dp/px, which just made the button, well, invisible...

Is it possible to define default values for these attributes, or am I out of luck here?

wujek
  • 10,112
  • 12
  • 52
  • 88
  • Not even custom-view can do that, **but custom-layout can**! (As said in [another post](https://stackoverflow.com/questions/41907874/custom-view-without-requiring-layout-width-in-xml/41908074#comment127724830_41908074)). – Top-Master May 19 '22 at 05:53
  • Does this answer your question? [Custom View without requiring layout\_width in xml](https://stackoverflow.com/questions/41907874/custom-view-without-requiring-layout-width-in-xml) – Top-Master May 19 '22 at 05:55

0 Answers0