Search code examples
androidmvvmdata-bindingandroid-databindingandroid-binding-adapter

Cusom event attributes in android bindings app:onMyEvent


Is there any way to wire up custom onSomeEventListener to the attribute using binding library? Examples provided for onClick are simple and they all use 'on' prefix and single-method interface listeners, and what about 'add' prefix and more complicated scenarios?

Imagine I want to use custom wire up logic on RecyclerView.addOnItemTouchListener, determining the child view was touched from SimpleOnItemTouchListener.onTouchEvent and passing it to my view model, how can I achieve this?

I want to end up with something like this:

<RecyclerView
    app:onItemTouch="@{handlers::recyclerViewOnItemTouch}"/>

public class Handlers {
    public void recyclerViewOnItemTouch(View view) { ... }
}

Is there something similar to approach when notifying binding framework about your custom property update using BindingAdapter and InverseBindingListener?

@BindingAdapter("app:someAttrChanged") 
public static void setListener(View view, InverseBindingListener listener)

Solution

  • After some investigation and trial and error, I found a solution.

    Of course, you'll need to activate the Binding in your Activity or Fragment and set an instance of the ClickHandler to it, and have a variable for it in your xml for the ClickHandler. Assuming that you already know that, I'll continue:

    One part of the magic is using app:addOnItemTouchListener for the RecyclerView:

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rec_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:addOnItemTouchListener="@{clickHandler.touchListener}"/>
    

    The other part is the ClickHandler.class:

    public class ClickHandler {
    
        public RecyclerView.OnItemTouchListener touchListener;
    
        public ClickHandler(){
            //initialize the instance of your touchListener in the constructor
            touchListener = new RecyclerView.SimpleOnItemTouchListener(){
                @Override
                public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e)     {
                    //allow clicks
                    return true;
                }
    
                @Override
                    public void onTouchEvent(RecyclerView rv, MotionEvent e) {
                    //check if it is working / check if we get the touch event:
                    Log.d("onTouchEvent", "RecView: " + rv.getId() + "\nMotionEvent: "+ e.getAction());
                }
            };
        }
    
        /* last but not least: a method which returns the touchlistener. 
           You can rename the method, but don't forget to rename the attribute in the xml, too. */
        public RecyclerView.OnItemTouchListener touchListener(){
            return touchListener;
        }
    }