PagedTileLayout.java revision c5bdafb776ae8111da9da8f2b619181e136f1419
1package com.android.systemui.qs; 2 3import android.content.Context; 4import android.util.AttributeSet; 5import android.util.Log; 6import android.view.LayoutInflater; 7import android.view.View; 8import android.view.ViewGroup; 9import com.android.internal.widget.PagerAdapter; 10import com.android.internal.widget.ViewPager; 11import com.android.systemui.R; 12import com.android.systemui.qs.QSPanel.QSTileLayout; 13import com.android.systemui.qs.QSPanel.TileRecord; 14 15import java.util.ArrayList; 16 17public class PagedTileLayout extends ViewPager implements QSTileLayout { 18 19 private static final boolean DEBUG = false; 20 21 private static final String TAG = "PagedTileLayout"; 22 23 private final ArrayList<TileRecord> mTiles = new ArrayList<TileRecord>(); 24 private final ArrayList<TilePage> mPages = new ArrayList<TilePage>(); 25 26 private PageIndicator mPageIndicator; 27 28 private int mNumPages; 29 private View mDecorGroup; 30 private PageListener mPageListener; 31 32 public PagedTileLayout(Context context, AttributeSet attrs) { 33 super(context, attrs); 34 setAdapter(mAdapter); 35 setOnPageChangeListener(new OnPageChangeListener() { 36 @Override 37 public void onPageSelected(int position) { 38 if (mPageIndicator == null) return; 39 mPageIndicator.setLocation(position); 40 if (mPageListener != null) { 41 mPageListener.onPageChanged(position == 0); 42 } 43 } 44 45 @Override 46 public void onPageScrolled(int position, float positionOffset, 47 int positionOffsetPixels) { 48 if (mPageIndicator == null) return; 49 mPageIndicator.setLocation(position + positionOffset); 50 if (mPageListener != null) { 51 mPageListener.onPageChanged(position == 0 && positionOffsetPixels == 0); 52 } 53 } 54 55 @Override 56 public void onPageScrollStateChanged(int state) { 57 } 58 }); 59 setCurrentItem(0); 60 } 61 62 @Override 63 public boolean hasOverlappingRendering() { 64 return false; 65 } 66 67 @Override 68 protected void onFinishInflate() { 69 super.onFinishInflate(); 70 mPageIndicator = (PageIndicator) findViewById(R.id.page_indicator); 71 mDecorGroup = findViewById(R.id.page_decor); 72 ((LayoutParams) mDecorGroup.getLayoutParams()).isDecor = true; 73 74 mPages.add((TilePage) LayoutInflater.from(mContext) 75 .inflate(R.layout.qs_paged_page, this, false)); 76 } 77 78 @Override 79 public int getOffsetTop(TileRecord tile) { 80 return ((ViewGroup) tile.tileView.getParent()).getTop() + getTop(); 81 } 82 83 @Override 84 public void addTile(TileRecord tile) { 85 mTiles.add(tile); 86 postDistributeTiles(); 87 } 88 89 @Override 90 public void removeTile(TileRecord tile) { 91 if (mTiles.remove(tile)) { 92 postDistributeTiles(); 93 } 94 } 95 96 public void setPageListener(PageListener listener) { 97 mPageListener = listener; 98 } 99 100 private void postDistributeTiles() { 101 removeCallbacks(mDistribute); 102 post(mDistribute); 103 } 104 105 private void distributeTiles() { 106 if (DEBUG) Log.d(TAG, "Distributing tiles"); 107 final int NP = mPages.size(); 108 for (int i = 0; i < NP; i++) { 109 mPages.get(i).removeAllViews(); 110 } 111 int index = 0; 112 final int NT = mTiles.size(); 113 for (int i = 0; i < NT; i++) { 114 TileRecord tile = mTiles.get(i); 115 if (mPages.get(index).isFull()) { 116 if (++index == mPages.size()) { 117 if (DEBUG) Log.d(TAG, "Adding page for " + tile.tile.getClass().getSimpleName()); 118 mPages.add((TilePage) LayoutInflater.from(mContext) 119 .inflate(R.layout.qs_paged_page, this, false)); 120 } 121 } 122 if (DEBUG) Log.d(TAG, "Adding " + tile.tile.getClass().getSimpleName() + " to " 123 + index); 124 mPages.get(index).addTile(tile); 125 } 126 if (mNumPages != index + 1) { 127 mNumPages = index + 1; 128 mPageIndicator.setNumPages(mNumPages); 129 mAdapter.notifyDataSetChanged(); 130 } 131 } 132 133 @Override 134 public boolean updateResources() { 135 boolean changed = false; 136 for (int i = 0; i < mPages.size(); i++) { 137 changed |= mPages.get(i).updateResources(); 138 } 139 if (changed) { 140 distributeTiles(); 141 } 142 return changed; 143 } 144 145 @Override 146 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 147 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 148 // The ViewPager likes to eat all of the space, instead force it to wrap to the max height 149 // of the pages. 150 int maxHeight = 0; 151 final int N = getChildCount(); 152 for (int i = 0; i < N; i++) { 153 int height = getChildAt(i).getMeasuredHeight(); 154 if (height > maxHeight) { 155 maxHeight = height; 156 } 157 } 158 setMeasuredDimension(getMeasuredWidth(), maxHeight + mDecorGroup.getMeasuredHeight()); 159 } 160 161 private final Runnable mDistribute = new Runnable() { 162 @Override 163 public void run() { 164 distributeTiles(); 165 } 166 }; 167 168 public static class TilePage extends TileLayout { 169 private int mMaxRows = 3; 170 171 public TilePage(Context context, AttributeSet attrs) { 172 super(context, attrs); 173 updateResources(); 174 } 175 176 @Override 177 public boolean updateResources() { 178 if (super.updateResources()) { 179 mMaxRows = mColumns != 3 ? 2 : 3; 180 return true; 181 } 182 return false; 183 } 184 185 public void setMaxRows(int maxRows) { 186 mMaxRows = maxRows; 187 } 188 189 public boolean isFull() { 190 return mRecords.size() >= mColumns * mMaxRows; 191 } 192 } 193 194 private final PagerAdapter mAdapter = new PagerAdapter() { 195 public void destroyItem(ViewGroup container, int position, Object object) { 196 if (DEBUG) Log.d(TAG, "Destantiating " + position); 197 // TODO: Find way to clean up the extra pages. 198 container.removeView((View) object); 199 } 200 201 public Object instantiateItem(ViewGroup container, int position) { 202 if (DEBUG) Log.d(TAG, "Instantiating " + position); 203 ViewGroup view = mPages.get(position); 204 container.addView(view); 205 return view; 206 } 207 208 @Override 209 public int getCount() { 210 return mNumPages; 211 } 212 213 @Override 214 public boolean isViewFromObject(View view, Object object) { 215 return view == object; 216 } 217 }; 218 219 public interface PageListener { 220 void onPageChanged(boolean isFirst); 221 } 222} 223