ListRowDataAdapter.java revision b3756c53c5be55e8c8a2f6e2cda264407be84881
1package android.support.v17.leanback.app; 2 3import android.support.v17.leanback.widget.DividerRow; 4import android.support.v17.leanback.widget.ListRow; 5import android.support.v17.leanback.widget.ObjectAdapter; 6import android.support.v17.leanback.widget.Row; 7 8/** 9 * Wrapper class for {@link ObjectAdapter} used by {@link BrowseFragment} to initialize 10 * {@link RowsFragment}. We use invisible rows to represent 11 * {@link android.support.v17.leanback.widget.DividerRow}, 12 * {@link android.support.v17.leanback.widget.SectionRow} and 13 * {@link android.support.v17.leanback.widget.PageRow} in RowsFragment. In case we have an 14 * invisible row at the end of a RowsFragment, it creates a jumping effect as the layout manager 15 * thinks there are items even though they're invisible. This class takes care of filtering out 16 * the invisible rows at the end. In case the data inside the adapter changes, it adjusts the 17 * bounds to reflect the latest data. 18 */ 19class ListRowDataAdapter extends ObjectAdapter { 20 private final ObjectAdapter mAdapter; 21 private int mLastVisibleRowIndex; 22 23 public ListRowDataAdapter(ObjectAdapter adapter) { 24 super(adapter.getPresenterSelector()); 25 this.mAdapter = adapter; 26 initialize(); 27 mAdapter.registerObserver(new DataObserver() { 28 29 @Override 30 public void onItemRangeChanged(int positionStart, int itemCount) { 31 initialize(); 32 notifyItemRangeChanged(positionStart, itemCount); 33 } 34 35 @Override 36 public void onItemRangeInserted(int positionStart, int itemCount) { 37 Row item = (Row) mAdapter.get(mLastVisibleRowIndex); 38 boolean isLastRowNonVisible = (item instanceof DividerRow); 39 initialize(); 40 41 boolean hasVisibleRow = hasVisibleRow(positionStart); 42 if (positionStart >= mLastVisibleRowIndex 43 && isLastRowNonVisible 44 && hasVisibleRow) { 45 positionStart--; 46 itemCount++; 47 } 48 notifyItemRangeInserted(positionStart, itemCount); 49 } 50 51 @Override 52 public void onItemRangeRemoved(int positionStart, int itemCount) { 53 Row item = (Row) mAdapter.get(mLastVisibleRowIndex); 54 boolean isLastRowNonVisible = (item instanceof DividerRow); 55 initialize(); 56 57 if (positionStart + itemCount >= mLastVisibleRowIndex && isLastRowNonVisible) { 58 itemCount--; 59 } 60 notifyItemRangeRemoved(positionStart, itemCount); 61 } 62 63 @Override 64 public void onChanged() { 65 initialize(); 66 notifyChanged(); 67 } 68 }); 69 } 70 71 private boolean hasVisibleRow(int startIndex) { 72 for (int i = startIndex; i < Math.min(mLastVisibleRowIndex, mAdapter.size()); i++) { 73 Row item = (Row) mAdapter.get(i); 74 if (item instanceof ListRow) { 75 return true; 76 } 77 } 78 return false; 79 } 80 81 private void initialize() { 82 int i = 0; 83 while (i < mAdapter.size()) { 84 Row item = (Row) mAdapter.get(i); 85 if (item.isRenderedAsRowView()) { 86 break; 87 } 88 i++; 89 } 90 91 i = mAdapter.size() - 1; 92 while (i >= 0) { 93 Row item = (Row) mAdapter.get(i); 94 if (item.isRenderedAsRowView()) { 95 mLastVisibleRowIndex = i; 96 break; 97 } 98 i--; 99 } 100 } 101 102 @Override 103 public int size() { 104 return mLastVisibleRowIndex + 1; 105 } 106 107 @Override 108 public Object get(int index) { 109 return mAdapter.get(index); 110 } 111}