ItemBridgeAdapter.java revision 8b068ddbbf22a246eab49ec25a2f7c3abfbdca51
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14package android.support.v17.leanback.widget; 15 16import android.support.v7.widget.RecyclerView; 17import android.support.v17.leanback.R; 18import android.util.Log; 19import android.view.View; 20import android.view.ViewGroup; 21 22import java.util.ArrayList; 23 24/** 25 * Bridge from Presenter to RecyclerView.Adapter. Public to allow use by third 26 * party presenters. 27 */ 28public class ItemBridgeAdapter extends RecyclerView.Adapter { 29 private static final String TAG = "ItemBridgeAdapter"; 30 private static final boolean DEBUG = false; 31 32 /** 33 * Interface for listening to view holder operations. 34 */ 35 public static class AdapterListener { 36 public void onAddPresenter(Presenter presenter) { 37 } 38 public void onCreate(ViewHolder viewHolder) { 39 } 40 public void onBind(ViewHolder viewHolder) { 41 } 42 public void onUnbind(ViewHolder viewHolder) { 43 } 44 public void onAttachedToWindow(ViewHolder viewHolder) { 45 } 46 public void onDetachedFromWindow(ViewHolder viewHolder) { 47 } 48 } 49 50 private ObjectAdapter mAdapter; 51 private PresenterSelector mPresenterSelector; 52 private FocusHighlight mFocusHighlight; 53 private AdapterListener mAdapterListener; 54 private ArrayList<Presenter> mPresenters = new ArrayList<Presenter>(); 55 56 class OnFocusChangeListener implements View.OnFocusChangeListener { 57 View.OnFocusChangeListener mChainedListener; 58 59 @Override 60 public void onFocusChange(View view, boolean hasFocus) { 61 if (DEBUG) Log.v(TAG, "onFocusChange " + hasFocus + " " + view + " mFocusHighlight" + mFocusHighlight); 62 ViewHolder viewHolder = getChildViewHolder(view); 63 if (mFocusHighlight != null) { 64 mFocusHighlight.onItemFocused(view, viewHolder.mItem, hasFocus); 65 } 66 if (mChainedListener != null) { 67 mChainedListener.onFocusChange(view, hasFocus); 68 } 69 } 70 } 71 72 public class ViewHolder extends RecyclerView.ViewHolder { 73 Presenter mPresenter; 74 Presenter.ViewHolder mHolder; 75 Object mItem; 76 OnFocusChangeListener mFocusChangeListener = new OnFocusChangeListener(); 77 78 public final Presenter getPresenter() { 79 return mPresenter; 80 } 81 public final Presenter.ViewHolder getViewHolder() { 82 return mHolder; 83 } 84 85 ViewHolder(Presenter presenter, Presenter.ViewHolder holder) { 86 super(holder.view); 87 mPresenter = presenter; 88 mHolder = holder; 89 } 90 } 91 92 private ObjectAdapter.DataObserver mDataObserver = new ObjectAdapter.DataObserver() { 93 @Override 94 public void onChanged() { 95 ItemBridgeAdapter.this.notifyDataSetChanged(); 96 } 97 @Override 98 public void onItemRangeChanged(int positionStart, int itemCount) { 99 ItemBridgeAdapter.this.notifyItemRangeChanged(positionStart, itemCount); 100 } 101 @Override 102 public void onItemRangeInserted(int positionStart, int itemCount) { 103 ItemBridgeAdapter.this.notifyItemRangeInserted(positionStart, itemCount); 104 } 105 @Override 106 public void onItemRangeRemoved(int positionStart, int itemCount) { 107 ItemBridgeAdapter.this.notifyItemRangeRemoved(positionStart, itemCount); 108 } 109 }; 110 111 public ItemBridgeAdapter(ObjectAdapter adapter, PresenterSelector presenterSelector) { 112 setAdapter(adapter); 113 mPresenterSelector = presenterSelector; 114 } 115 116 public ItemBridgeAdapter() { 117 } 118 119 private ViewHolder getChildViewHolder(View view) { 120 RecyclerView recyclerView = (RecyclerView) view.getParent(); 121 return (ViewHolder) recyclerView.getChildViewHolder(view); 122 } 123 124 public void setAdapter(ObjectAdapter adapter) { 125 if (mAdapter != null) { 126 mAdapter.unregisterObserver(mDataObserver); 127 } 128 mAdapter = adapter; 129 if (mAdapter == null) { 130 return; 131 } 132 133 mAdapter.registerObserver(mDataObserver); 134 setHasStableIds(mAdapter.hasStableIds()); 135 } 136 137 void setFocusHighlight(FocusHighlight listener) { 138 mFocusHighlight = listener; 139 if (DEBUG) Log.v(TAG, "setFocusHighlight " + mFocusHighlight); 140 } 141 142 public void clear() { 143 setAdapter(null); 144 } 145 146 @Override 147 public int getItemCount() { 148 return mAdapter.size(); 149 } 150 151 @Override 152 public int getItemViewType(int position) { 153 PresenterSelector presenterSelector = mPresenterSelector != null ? 154 mPresenterSelector : mAdapter.getPresenterSelector(); 155 Object item = mAdapter.get(position); 156 Presenter presenter = presenterSelector.getPresenter(item); 157 int type = mPresenters.indexOf(presenter); 158 if (type < 0) { 159 mPresenters.add(presenter); 160 type = mPresenters.indexOf(presenter); 161 if (mAdapterListener != null) { 162 mAdapterListener.onAddPresenter(presenter); 163 } 164 } 165 return type; 166 } 167 168 /** 169 * {@link View.OnFocusChangeListener} that assigned in 170 * {@link Presenter#onCreateViewHolder(ViewGroup)} may be chained, user should never change 171 * {@link View.OnFocusChangeListener} after that. 172 */ 173 @Override 174 public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 175 if (DEBUG) Log.v(TAG, "onCreateViewHolder viewType " + viewType); 176 Presenter presenter = mPresenters.get(viewType); 177 ViewHolder viewHolder = new ViewHolder(presenter, presenter.onCreateViewHolder(parent)); 178 if (mAdapterListener != null) { 179 mAdapterListener.onCreate(viewHolder); 180 } 181 View view = viewHolder.mHolder.view; 182 if (view != null) { 183 viewHolder.mFocusChangeListener.mChainedListener = view.getOnFocusChangeListener(); 184 view.setOnFocusChangeListener(viewHolder.mFocusChangeListener); 185 } 186 return viewHolder; 187 } 188 189 public void setAdapterListener(AdapterListener listener) { 190 mAdapterListener = listener; 191 } 192 193 @Override 194 public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 195 if (DEBUG) Log.v(TAG, "onBindViewHolder position " + position); 196 ViewHolder viewHolder = (ViewHolder) holder; 197 viewHolder.mItem = mAdapter.get(position); 198 199 viewHolder.mPresenter.onBindViewHolder(viewHolder.mHolder, viewHolder.mItem); 200 201 if (mAdapterListener != null) { 202 mAdapterListener.onBind(viewHolder); 203 } 204 } 205 206 @Override 207 public void onViewRecycled(RecyclerView.ViewHolder holder) { 208 ViewHolder viewHolder = (ViewHolder) holder; 209 viewHolder.mPresenter.onUnbindViewHolder(viewHolder.mHolder); 210 211 viewHolder.mItem = null; 212 213 if (mAdapterListener != null) { 214 mAdapterListener.onUnbind(viewHolder); 215 } 216 } 217 218 @Override 219 public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { 220 ViewHolder viewHolder = (ViewHolder) holder; 221 if (mAdapterListener != null) { 222 mAdapterListener.onAttachedToWindow(viewHolder); 223 } 224 viewHolder.mPresenter.onViewAttachedToWindow(viewHolder.mHolder); 225 } 226 227 @Override 228 public void onViewDetachedFromWindow(RecyclerView.ViewHolder holder) { 229 ViewHolder viewHolder = (ViewHolder) holder; 230 viewHolder.mPresenter.onViewDetachedFromWindow(viewHolder.mHolder); 231 if (mAdapterListener != null) { 232 mAdapterListener.onDetachedFromWindow(viewHolder); 233 } 234 } 235 236 @Override 237 public long getItemId(int position) { 238 return mAdapter.getId(position); 239 } 240 241} 242