package me.tatarka.bindingcollectionadapter2; import android.databinding.DataBindingUtil; import android.databinding.ObservableList; import android.databinding.ViewDataBinding; import android.support.annotation.LayoutRes; import android.support.annotation.Nullable; import android.support.v4.view.PagerAdapter; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import java.lang.ref.WeakReference; import java.util.List; /** * A {@link PagerAdapter} that binds items to layouts using the given {@link ItemView} or {@link * ItemViewSelector}. If you give it an {@link ObservableList} it will also updated itself based on * changes to that list. */ public class BindingViewPagerAdapter<T> extends PagerAdapter implements BindingCollectionAdapter<T> { private ItemBinding<T> itemBinding; private final WeakReferenceOnListChangedCallback<T> callback = new WeakReferenceOnListChangedCallback<>(this); private List<T> items; private LayoutInflater inflater; private PageTitles<T> pageTitles; @Override public void setItemBinding(ItemBinding<T> itemBinding) { this.itemBinding = itemBinding; } @Override public ItemBinding<T> getItemBinding() { return itemBinding; } @Override public void setItems(@Nullable List<T> items) { if (this.items == items) { return; } if (this.items instanceof ObservableList) { ((ObservableList<T>) this.items).removeOnListChangedCallback(callback); } if (items instanceof ObservableList) { ((ObservableList<T>) items).addOnListChangedCallback(callback); } this.items = items; notifyDataSetChanged(); } @Override public T getAdapterItem(int position) { return items.get(position); } @Override public ViewDataBinding onCreateBinding(LayoutInflater inflater, @LayoutRes int layoutRes, ViewGroup viewGroup) { return DataBindingUtil.inflate(inflater, layoutRes, viewGroup, false); } @Override public void onBindBinding(ViewDataBinding binding, int variableId, @LayoutRes int layoutRes, int position, T item) { if (itemBinding.bind(binding, item)) { binding.executePendingBindings(); } } /** * Sets the page titles for the adapter. */ public void setPageTitles(@Nullable PageTitles<T> pageTitles) { this.pageTitles = pageTitles; } @Override public int getCount() { return items == null ? 0 : items.size(); } @Override public CharSequence getPageTitle(int position) { return pageTitles == null ? null : pageTitles.getPageTitle(position, items.get(position)); } @Override public Object instantiateItem(ViewGroup container, int position) { if (inflater == null) { inflater = LayoutInflater.from(container.getContext()); } T item = items.get(position); itemBinding.onItemBind(position, item); ViewDataBinding binding = onCreateBinding(inflater, itemBinding.layoutRes(), container); onBindBinding(binding, itemBinding.variableId(), itemBinding.layoutRes(), position, item); container.addView(binding.getRoot()); binding.getRoot().setTag(item); return binding.getRoot(); } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @SuppressWarnings("unchecked") @Override public int getItemPosition(Object object) { T item = (T) ((View) object).getTag(); if (items != null) { for (int i = 0; i < items.size(); i++) { if (item == items.get(i)) { return i; } } } return POSITION_NONE; } private static class WeakReferenceOnListChangedCallback<T> extends ObservableList.OnListChangedCallback<ObservableList<T>> { final WeakReference<BindingViewPagerAdapter<T>> adapterRef; WeakReferenceOnListChangedCallback(BindingViewPagerAdapter<T> adapter) { this.adapterRef = new WeakReference<>(adapter); } @Override public void onChanged(ObservableList sender) { BindingViewPagerAdapter<T> adapter = adapterRef.get(); if (adapter == null) { return; } Utils.ensureChangeOnMainThread(); adapter.notifyDataSetChanged(); } @Override public void onItemRangeChanged(ObservableList sender, int positionStart, int itemCount) { onChanged(sender); } @Override public void onItemRangeInserted(ObservableList sender, int positionStart, int itemCount) { onChanged(sender); } @Override public void onItemRangeMoved(ObservableList sender, int fromPosition, int toPosition, int itemCount) { onChanged(sender); } @Override public void onItemRangeRemoved(ObservableList sender, int positionStart, int itemCount) { onChanged(sender); } } public interface PageTitles<T> { CharSequence getPageTitle(int position, T item); } }