Search code examples
androiddata-bindingseekbar

Custom SeekBar listener databinding


I'm trying to set listener on custom SeekBar (https://github.com/warkiz/IndicatorSeekBar) using Android Databinding. In standard SeekBar I'm setting onProgressChanged listener this way:
fragment's XML:

<SeekBar
    ...
    android:onProgressChanged="@{viewModel::seekBarStopTracking}"
    ... 
/>

Fragment's ViewModel:

public void seekBarStopTracking(SeekBar view, int progress, boolean fromUser) {
       
}

I'm trying to do the same with IndicatorSeekBar, however it has a bit different listeners:
Example from github:

seekBar.setOnSeekChangeListener(new OnSeekChangeListener() {
    @Override
    public void onSeeking(SeekParams seekParams) {
    }

    @Override
    public void onStartTrackingTouch(IndicatorSeekBar seekBar) {
    }

    @Override
    public void onStopTrackingTouch(IndicatorSeekBar seekBar) {
    }
});

XML:

<com.warkiz.widget.IndicatorSeekBar
    ...
    app:onSeeking="@{viewModel::seeking}"
    ...
/>

ViewModel:

public void seeking(SeekParams params){
    
}

also tried:

public void seeking(IndicatorSeekBar seekBar, SeekParams params){
    
}

But result is the same:

[databinding] {"msg":"Could not resolve viewModel::seeking as a listener.

What I'm doing wrong? Thanks


Solution

  • This is a custom view, so you need to write your own Binding Adapters. Here is the solution:

    Step 1: Create a binding class

    IndicatorSeekBarBindingAdapter.java

    public class IndicatorSeekBarBindingAdapter {
    
        @BindingAdapter(value = {"app:onSeeking", "app:onStartTrackingTouch",
                "app:onStopTrackingTouch"}, requireAll = false)
        public static void setOnSeekBarChangeListener(IndicatorSeekBar seekBar,
                                                      final OnSeeking seeking,
                                                      final OnStartTrackingTouch start,
                                                      final OnStopTrackingTouch stop) {
            if (seeking != null || start != null || stop != null) {
                seekBar.setOnSeekChangeListener(new OnSeekChangeListener() {
                    @Override
                    public void onSeeking(SeekParams seekParams) {
                        if (seeking != null) {
                            seeking.onSeeking(seekBar, seekParams);
                        }
                    }
    
                    @Override
                    public void onStartTrackingTouch(IndicatorSeekBar seekBar) {
                        if (start != null) {
                            start.onStartTrackingTouch(seekBar);
                        }
                    }
    
                    @Override
                    public void onStopTrackingTouch(IndicatorSeekBar seekBar) {
                        if (stop != null) {
                            stop.onStopTrackingTouch(seekBar);
                        }
                    }
                });
            }
        }
    
        public interface OnSeeking {
            void onSeeking(IndicatorSeekBar seekBar, SeekParams seekParams);
        }
    
        public interface OnStartTrackingTouch {
            void onStartTrackingTouch(IndicatorSeekBar seekBar);
        }
    
        public interface OnStopTrackingTouch {
            void onStopTrackingTouch(IndicatorSeekBar seekBar);
        }
    }
    

    Step 2: Add the following code into your view model class.

    public class MyViewModel extends ViewModel {
    
        public void onSeeking(IndicatorSeekBar seekBar, SeekParams seekParams) {
            Log.i("TAG", "onSeeking: " + seekParams.progress);
        }
    
        public void onStartTrackingTouch(IndicatorSeekBar seekBar) {
            Log.i("TAG", "onStartTrackingTouch: " + seekBar.getProgress());
        }
    
        public void onStopTrackingTouch(IndicatorSeekBar seekBar) {
            Log.i("TAG", "onStopTrackingTouch: " + seekBar.getProgress());
        }
    }
    

    Step 3: Use it from layout xml file

    <com.warkiz.widget.IndicatorSeekBar
        android:id="@+id/seekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:onSeeking="@{viewModel::onSeeking}"
        app:onStartTrackingTouch="@{viewModel::onStartTrackingTouch}"
        app:onStopTrackingTouch="@{viewModel::onStopTrackingTouch}" />