Search code examples
androidkotlinandroid-custom-viewandroid-databinding

Android onclick of XML doesnt work when OnClickListener is implemented in customview button


I need a small animation when user click a button and when the animation ends then it should perform the click action.

XML

<com.customview.CustomButton
            android:id="@+id/btn_submit"
            bind_fontStyle="@{@string/button_bold}"
            android:layout_width="@dimen/standard_button_width"
            android:layout_height="@dimen/standard_button_height"
            android:text="@{viewModel.btnText}"
            android:onClick="@{()->viewModel.onButtonClick(true)}"
            android:visibility="@{viewModel.isButtonVisible() ? View.VISIBLE : View.GONE}"
            />

custom class

class CustomButton : AppCompatButton, View.OnClickListener {

constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(
    context,
    attrs,
    defStyle
) {
    init()
}

constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
    init()
}

constructor(context: Context) : super(context) {
    init()
}

private fun init() {
    setOnClickListener(this)
}

override fun onClick(v: View) {
    v.post(Runnable {
        v.animate().scaleX(1.05f).scaleY(1.05f).setDuration(200).withEndAction {
            v.animate().scaleX(1f).scaleY(1f).setStartDelay(200)

        }
    })
}

}

i tried to override the OnClickListener in custom view and on the on click i have done the animation but the issue is it is not calling the android:onClick of xml.


Solution

  • This will not work because you are trying to set multiple click listeners on the view at these places:

    android:onClick="@{()->viewModel.onButtonClick(true)}"
    

    and

    setOnClickListener(this)
    

    If I understand your question correctly, once the user clicks on the button, an animation should take place first and then an action should be taken in the respective view model.

    You can implement an interface between your CustomButton class and your ViewModel

    interface CustomButtonClickListener {
    fun onClick()
    }
    

    Implement this interface in your ViewModel. With data binding, send this interface listener to your CustomButton with custom attributes. Something like this:

    <data>
    <variable name="vm"
              type="*path_vm*" />
    </data>
    

    And pass this vm to your CustomLabel

    app:listener="@{vm}"
    

    You can refer this to create custom attributes for your CustomLabel class

    Now after your button animation ends, you only need to call the interface method and the ViewModel's overriden method should get called

    listener.onClick()
    

    Let me know if you have any other questions :)