Search code examples
androidfloating-action-button

Floating action button icon is not aligned centre when changed using selector


I toggle the icon in Floating action button using android selector when user touches the icon. Normally the icon was centre aligned in floating action button but after user touches the icon and the toggled image was not aligned properly. please help me.

Here's my code.

<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:id="@+id/btn_drive_mode"
    style="@style/Widget.MaterialComponents.FloatingActionButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:fabSize="mini"
    android:layout_margin="@dimen/dp_16"
    android:contentDescription="map_center_icon"
    app:srcCompat="@drawable/toggle_drive_mode_selector"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintBottom_toTopOf="@id/footer"
    app:backgroundTint="@color/green"
    app:tint="@color/white"/>

my selector file

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_location" android:state_activated="true" />
    <item android:drawable="@android:drawable/ic_dialog_map" />
</selector>

But the image looks like this,

Before tapped

enter image description here

After tapped

enter image description here


Solution

  • After digging into the FloatingActionButton source, you can see that the scale type of the superclass is set to ScaleType.MATRIX and the matrix for the image is set during the call to setImageDrawable(Drawable) as you would expect.

    However they don't seem to update the matrix during drawableStateChanged which I would presume is a subtle bug as opposed to intended behaviour.

    Therefore to fix this issue, you could do one of two things:


    Force the FloatingActionButton to use a different scale type

    They programmatically set the scale type on the last line of initialisation so it would either have to be reset with a subclass, posted after layout or set every time you flip the activated state.

    Use the same size icons

    The reason you're experiencing this bug whereas others probably haven't, is because you're using icons from different sources to switch between. If you take both icons from the Material Icons set, then the scaling won't cause an issue due to the icons requiring the same matrix.


    Personally I would recommend the second approach, using your own icons instead of platform ones would most likely be best practice anyway and changing the behaviour of FloatingActionButton without understanding why it exists might cause unintended consequences.