alav alav - 3 months ago 5
Android Question

How do I provide a custom Android Button with rounded corners that allows users to change the background colours?

I'm writing an Android UI library that features a button.
The button has rounded corners, a default text size and a lowercase title.

These attributes can be considered fixed, but I would like users to be able to specify their own background colours for normal, pressed and disabled states.

I have a style in my library that sets the following attributes:

<style name="LibraryButtonStyle">
<item name="android:textAllCaps">false</item>
<item name="android:textSize">18sp</item>
<item name="android:background">@drawable/LibraryButtonBackground</item>
</style>


My selector in
LibraryButtonBackground.xml
implements the rounded corners:

<?xml version="1.0" encoding="UTF-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_enabled="false">
<shape android:shape="rectangle" >
<corners android:radius="10dp" />
<!-- <solid android:color="#DDDDDD" /> User should set this -->
</shape>
</item>
<item android:state_pressed="true">
<shape android:shape="rectangle" >
<corners android:radius="10dp" />
<!-- <solid android:color="#DDDDDD" /> User should set this -->
</shape>
</item>
<item>
<shape android:shape="rectangle" >
<corners android:radius="10dp" />
<!-- <solid android:color="#DDDDDD" /> User should set this -->
</shape>
</item>




I want the user to be able to set the colours without them having to write their own selector and having to define the rounded corners themselves.

The below user-implemented style is no use as obviously overriding the background drawable means the corners will no longer be rounded unless the user does this themselves.

<style name="UserButtonStyle" parent="LibraryButtonStyle">
<item name="android:background">@drawable/UserButtonBackground</item>
</style>


Can anyone suggest how I could achieve this?

Answer

Start by defining some custom attributes. This would typically be in attrs.xml in resources:

    <declare-styleable name="LibraryButton">
        <attr name="libButtonColor" format="color"/>
        <attr name="libButtonColorPressed" format="color"/>
        <attr name="libButtonColorDisabled" format="color"/>
    </declare-styleable>

I assume you have a library theme that your client will use (styles.xml).

You want to have some default values:

<style name="Theme.Library" parent="Theme.AppCompat">
    <item name="libButtonColor">@color/default_button_color</item>
    <item name="libButtonColorPressed">@color/default_button_color_pressed</item>
    <item name="libButtonColorDisabled">@color/default_button_color_disabled</item>
    .
    .
    .
</style>

The client will do something like this in their project (styles.xml):

<style name="Theme.Client" parent="Theme.Library">
    <item name="libButtonColor">@color/client_button_color</item>
    <item name="libButtonColorPressed">@color/client_button_color_pressed</item>
    <item name="libButtonColorDisabled">@color/client_button_color_disabled</item>
    .
    .
    .
</style>

And here's what your LibraryButtonBackground.xml resource file will be:

<?xml version="1.0" encoding="UTF-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="false">
        <shape android:shape="rectangle" >
            <corners android:radius="10dp" />
            <solid android:color="?attr/libButtonColorDisabled" />
        </shape>
    </item>
    <item android:state_pressed="true">
        <shape android:shape="rectangle" >
            <corners android:radius="10dp" />
            <solid android:color="?attr/libButtonColorPressed" />
        </shape>
    </item>
    <item>
        <shape android:shape="rectangle" >
            <corners android:radius="10dp" />
            <solid android:color="?attr/libButtonColor" />
        </shape>
    </item>
</selector>