androidxmlandroid-studioandroid-layoutandroid-button

Android - cannot set button border as expected


I just started learning Android a few days ago. When I am playing around with Button today, I noticed that I am not able to set border as expected.

xml files below:
Button partin activity_main.xml:

<Button
    android:layout_width="200sp"
    android:layout_height="100dp"
    android:background="@drawable/start_button_selector"
    app:backgroundTint="@color/start_button_color_selector"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias=".4" />

start_button_selector.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/arrow_button">
        <shape android:shape="rectangle">
            <solid android:color="@color/transparent" />
            <corners android:radius="12sp" />
            <stroke android:width="10sp" android:color="@color/start_button_color_selector"/>
        </shape>
    </item>
</selector>

start_button_color_selector

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/black" android:state_pressed="true"/>
    <item android:color="@color/gray"/>
</selector>

however, neither the preview nor the emulator gives the expected result.
the preview does not show any border, and the emulator shows a purple border\

expected (and all color becomes black when clicked):
expected

but here is the preview in xml Design mode:
preview

and here is what it is showing in the emulator (API 30):
emulator

also tried:
changing Button to androidx.appcompat.widget.AppCompatButton
removing color inside stroke tag
Any help would be great!

Edit: Sorry if I didn't make it clear. The problem is not changing color when pressed, with the above xml file, the button is already able to change its color when pressed. The problem I have is that the border is transparent in preview and purple in emulator, which is not gray/black as I expected.


Solution

  • You can achieve this using a Material Button. There is a lot of useful attributes you can use to make the button based on your needs, like app:strokeWidth, app:strokeColor, app:cornerRadius, app:backgroundTint, app:icon, app:iconSize and much more where you can find them in the above link.

    Below is a sample of your Button using the above Material Button attributes:

    <com.google.android.material.button.MaterialButton
            android:id="@+id/button"
            android:layout_width="200dp"
            android:layout_height="100dp"
            android:padding="0dp"
            android:insetLeft="0dp"
            android:insetTop="0dp"
            android:insetRight="0dp"
            android:insetBottom="0dp"
            app:cornerRadius="12dp"
            app:strokeWidth="10dp"
            app:strokeColor="@color/start_button_color_selector"
            app:backgroundTint="@android:color/white"
            app:icon="@drawable/button_selector"
            app:iconTint="@null"
            app:iconSize="80dp"
            app:iconGravity="textStart"
            app:iconPadding="0dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"/>
    

    where @color/start_button_color_selector.xml will be like below to set the stroke color based on selected/unselected state:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:color="@android:color/black" android:state_pressed="true"/>
        <item android:color="#969292"/>
    </selector>
    

    and @drawable/button_selector will be like below to set the correct vector icon based on selected/unselected state:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/ic_arrow_black_right_24dp" android:state_pressed="true"/>
        <item android:drawable="@drawable/ic_arrow_gray_right_24dp"/>
    </selector>
    

    and @drawable/ic_arrow_black_right_24dp is a sample black selected arrow:

    <vector android:autoMirrored="true" android:height="24dp"
        android:tint="@android:color/black" android:viewportHeight="24"
        android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
        <path android:fillColor="@android:color/black" android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z"/>
    </vector>
    

    and @drawable/ic_arrow_gray_right_24dp is a sample gray unselected arrow:

    <vector android:autoMirrored="true" android:height="24dp"
        android:tint="#969292" android:viewportHeight="24"
        android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
        <path android:fillColor="#969292" android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z"/>
    </vector>
    

    Final result for unselected state will be:

    enter image description here

    and final result for selected/clicked state will be:

    enter image description here