androidandroid-motionlayoutmaterialbuttonconstraintset

Is there a way to set MotionLayout custom attribute for MaterialButton's iconTint?


According to this article

CustomAttribute are specified with the attributeName, which needs to match the getter/setter methods of an object such that: getter: getName (e.g. getBackgroundColor) setter: setName (e.g. setBackgroundColor)

(so motion:attributeName need to be backgroundColor)

I've tried bellow attribute names with material button, but none of them worked.

<CustomAttribute motion:attributeName="IconTintResource" motion:customColorValue="@color/keyTextColor" />

'IconTintResource', 'iconTintResource', 'IconTint', 'iconTint', 'ColorFilter'

any suggestions?

These are the errors I'm getting

E/TransitionLayout: Custom Attribute "IconTint" not found on com.google.android.material.button.MaterialButton

E/TransitionLayout: com.google.android.material.button.MaterialButton must have a method setIconTint

E/TransitionLayout: no method setIconTinton View "f_editor_image_view_terminal"


Solution

  • MotionLayout's CustomAttribute use reflection to setValues on Views (roughly based on the Java beans conventions)

    So if you say

    <CustomAttribute motion:attributeName="foo" motion:customColorValue="@color/keyTextColor" />
    

    It looks for a method setFoo(int value); Unfortunately even though MaterialButton parses the xml android:iconTint="#FFF" It does not have the method setIconTint(int color);

    MotionLayout will also check for setFoo(Drawable()) and use a ColorDrawable

    You can create a subclass of MaterialButton and implement the method needed setInconTint(int color)

    class MyButton extends MaterialButton {
    
        public MyButton(@NonNull Context context) {
            super(context);
        }
    
        public MyButton(@NonNull Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
        }
    
        public MyButton(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        void setIconTint(int color) {
            ColorStateList colorStateList = new ColorStateList(new int[1][0],new int[]{color});
            setIconTint(colorStateList);
        }
    }
    

    This would then work with MotionLayout. This will create many objects during animation but they will be short lived.