@BindingAdapter(value = {"onRefreshListener", "refreshingAttrChanged"}, requireAll = false) public static void setOnRefreshListener(final SwipeRefreshLayout view, final SwipeRefreshLayout.OnRefreshListener listener, final InverseBindingListener refreshingAttrChanged) { SwipeRefreshLayout.OnRefreshListener newValue = new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { if (listener != null) { if (refreshingAttrChanged != null) { refreshingAttrChanged.onChange(); } listener.onRefresh(); } } }; SwipeRefreshLayout.OnRefreshListener oldValue = ListenerUtil.trackListener(view, newValue, R.id.onRefreshListener); if (oldValue != null) { view.setOnRefreshListener(null); } view.setOnRefreshListener(newValue); }
/** * This is how you implement 2-way data binding of a custom attribute if you want to maintain * a custom listener interface - OnHueChangeListener, in this case - while also leveraging * the synthetic attributes hueAttrChanged (the InverseBindingListener). For an example of * how to implement custom 2-way binding with just the synthetic AttrChanged attribute's * InverseBindingListener, see DocumentView or LayerListView's currentLayer 2-way binding * (along with the InverseBindingMethod declarations in DocumentViewModelBindingAdapters). * * @param view The view we're 2-way binding to. * @param onHueChangeListener The OnHueChangeListener bound by the developer on the view * in question. * @param inverseBindingListener Synthetic attribute representing an InverseBindingListener * for changes to the hue attribute. */ @BindingAdapter(value = {"onHueChange", "hueAttrChanged"}, requireAll = false) public static void setListeners(HuePicker view, final HuePicker.OnHueChangeListener onHueChangeListener, final InverseBindingListener inverseBindingListener) { HuePicker.OnHueChangeListener newListener; if (inverseBindingListener == null) { // If the synthetic listener param is null, just keep track of the listener set in // the binding newListener = onHueChangeListener; } else { // Otherwise define a new listener to wraps both listeners and invoke them at the // right time within the new listener if they are non-null newListener = new HuePicker.OnHueChangeListener() { @Override public void onHueChange(HuePicker huePicker, float hue) { if (onHueChangeListener != null) { onHueChangeListener.onHueChange(huePicker, hue); } inverseBindingListener.onChange(); } }; } // Use track listener to record listener we're adding and return any old listeners // registered through this method so that on rebind we don't add duplicate listeners HuePicker.OnHueChangeListener oldListener = ListenerUtil.trackListener(view, newListener, R.id.hueChangeListener); // Remove the old listener we set using this BindingAdapter, if there is one if (oldListener != null) { view.removeHueChangeListener(oldListener); } // Add our new listener if (newListener != null) { view.addHueChangeListener(newListener); } }
/** * Assign a list of items to a ViewGroup. This is used with the {@code entries} and * {@code layout} attributes in the application namespace. Example Usage: * <pre><code><LinearLayout * android:layout_width="match_parent" * android:layout_height="wrap_content" * android:orientation="vertical" * app:entries="@{items}" * app:layout="@{@layout/item}"/> * </code></pre> * <p> * In the above, {@code items} is a List or ObservableList. {@code layout} does not * need to be hard-coded, but most commonly will be. This BindingAdapter will work * with any ViewGroup that only needs addView() and removeView() to manage its Views. * <p> * The layout, @layout/item for example, must have a single variable named * {@code data}. */ @BindingAdapter({"entries", "layout"}) public static <T> void setEntries(ViewGroup viewGroup, List<T> oldEntries, int oldLayoutId, List<T> newEntries, int newLayoutId) { if (oldEntries == newEntries && oldLayoutId == newLayoutId) { return; // nothing has changed } EntryChangeListener listener = ListenerUtil.getListener(viewGroup, R.id.entryListener); if (oldEntries != newEntries && listener != null && oldEntries instanceof ObservableList) { ((ObservableList)oldEntries).removeOnListChangedCallback(listener); } if (newEntries == null) { viewGroup.removeAllViews(); } else { if (newEntries instanceof ObservableList) { if (listener == null) { listener = new EntryChangeListener(viewGroup, newLayoutId); ListenerUtil.trackListener(viewGroup, listener, R.id.entryListener); } else { listener.setLayoutId(newLayoutId); } if (newEntries != oldEntries) { ((ObservableList)newEntries).addOnListChangedCallback(listener); } } resetViews(viewGroup, newLayoutId, newEntries); } }
@BindingAdapter(value = {"onScrollStateChanged", "onScrolled"}, requireAll = false) public static void setOnScrollListener(RecyclerView view, final OnScrollStateChanged scrollStateChanged, final OnScrolled scrolled) { final RecyclerView.OnScrollListener newValue; if (scrollStateChanged == null && scrolled == null) { newValue = null; } else { newValue = new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { if (scrollStateChanged != null) { scrollStateChanged.onScrollStateChanged(recyclerView, newState); } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { if (scrolled != null) { scrolled.onScrolled(recyclerView, dx, dy); } } }; } final RecyclerView.OnScrollListener oldValue = ListenerUtil.trackListener(view, newValue, R.id.recyclerViewOnScrollListener); if (oldValue != null) { view.removeOnScrollListener(oldValue); } if (newValue != null) { view.addOnScrollListener(newValue); } }
@BindingAdapter({"android:onViewDetachedFromWindow", "android:onViewAttachedToWindow"}) public static void setListener(View view, final OnViewDetachedFromWindow detach, final OnViewAttachedToWindow attach) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) { final View.OnAttachStateChangeListener newListener; if (detach == null && attach == null) { newListener = null; } else { newListener = new View.OnAttachStateChangeListener() { @Override public void onViewAttachedToWindow(View v) { if (attach != null) { attach.onViewAttachedToWindow(v); } } @Override public void onViewDetachedFromWindow(View v) { if (detach != null) { detach.onViewDetachedFromWindow(v); } } }; } final View.OnAttachStateChangeListener oldListener = ListenerUtil.trackListener(view, newListener, R.id.onAttachStateChangeListener); if (oldListener != null) { view.removeOnAttachStateChangeListener(oldListener); } if (newListener != null) { view.addOnAttachStateChangeListener(newListener); } } }