blob: 6bc8b50911141136331a20c4245091fc3cd06cf5 [file] [log] [blame]
Jason Monkcaf37622015-08-18 12:33:50 -04001package 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;
Jason Monkcaf37622015-08-18 12:33:50 -04009import 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
Jason Monkcaf37622015-08-18 12:33:50 -040026 private PageIndicator mPageIndicator;
27
28 private int mNumPages;
29
30 public PagedTileLayout(Context context, AttributeSet attrs) {
31 super(context, attrs);
32 setAdapter(mAdapter);
33 setOnPageChangeListener(new OnPageChangeListener() {
34 @Override
35 public void onPageSelected(int position) {
36 if (mPageIndicator == null) return;
37 mPageIndicator.setLocation(position);
38 }
39
40 @Override
41 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
42 if (mPageIndicator == null) return;
43 mPageIndicator.setLocation(position + positionOffset);
44 }
45
46 @Override
47 public void onPageScrollStateChanged(int state) {
48 }
49 });
50 setCurrentItem(0);
51 }
52
53 @Override
54 protected void onFinishInflate() {
55 super.onFinishInflate();
56 mPageIndicator = (PageIndicator) findViewById(R.id.page_indicator);
57 ((LayoutParams) mPageIndicator.getLayoutParams()).isDecor = true;
58
Jason Monke4e69302016-01-20 11:27:15 -050059 mPages.add((TilePage) LayoutInflater.from(mContext)
60 .inflate(R.layout.qs_paged_page, this, false));
Jason Monkcaf37622015-08-18 12:33:50 -040061 }
62
63 @Override
64 public int getOffsetTop(TileRecord tile) {
Jason Monk9d02a432016-01-20 16:33:46 -050065 return ((ViewGroup) tile.tileView.getParent()).getTop() + getTop();
Jason Monkcaf37622015-08-18 12:33:50 -040066 }
67
68 @Override
Jason Monkcaf37622015-08-18 12:33:50 -040069 public void addTile(TileRecord tile) {
70 mTiles.add(tile);
Jason Monk9d02a432016-01-20 16:33:46 -050071 postDistributeTiles();
Jason Monkcaf37622015-08-18 12:33:50 -040072 }
73
74 @Override
75 public void removeTile(TileRecord tile) {
76 if (mTiles.remove(tile)) {
Jason Monk9d02a432016-01-20 16:33:46 -050077 postDistributeTiles();
Jason Monkcaf37622015-08-18 12:33:50 -040078 }
79 }
80
Jason Monk9d02a432016-01-20 16:33:46 -050081 private void postDistributeTiles() {
82 removeCallbacks(mDistribute);
83 post(mDistribute);
84 }
85
Jason Monkcaf37622015-08-18 12:33:50 -040086 private void distributeTiles() {
87 if (DEBUG) Log.d(TAG, "Distributing tiles");
Jason Monkcaf37622015-08-18 12:33:50 -040088 final int NP = mPages.size();
89 for (int i = 0; i < NP; i++) {
Jason Monk9d02a432016-01-20 16:33:46 -050090 mPages.get(i).removeAllViews();
Jason Monkcaf37622015-08-18 12:33:50 -040091 }
92 int index = 0;
93 final int NT = mTiles.size();
94 for (int i = 0; i < NT; i++) {
95 TileRecord tile = mTiles.get(i);
Jason Monkcaf37622015-08-18 12:33:50 -040096 if (mPages.get(index).isFull()) {
97 if (++index == mPages.size()) {
98 if (DEBUG) Log.d(TAG, "Adding page for " + tile.tile.getClass().getSimpleName());
99 mPages.add((TilePage) LayoutInflater.from(mContext)
100 .inflate(R.layout.qs_paged_page, this, false));
101 }
102 }
103 if (DEBUG) Log.d(TAG, "Adding " + tile.tile.getClass().getSimpleName() + " to "
104 + index);
105 mPages.get(index).addTile(tile);
106 }
107 if (mNumPages != index + 1) {
108 mNumPages = index + 1;
109 mPageIndicator.setNumPages(mNumPages);
110 mAdapter.notifyDataSetChanged();
111 }
112 }
113
114 @Override
Jason Monk9d02a432016-01-20 16:33:46 -0500115 public boolean updateResources() {
116 boolean changed = false;
Jason Monkcaf37622015-08-18 12:33:50 -0400117 for (int i = 0; i < mPages.size(); i++) {
Jason Monk9d02a432016-01-20 16:33:46 -0500118 changed |= mPages.get(i).updateResources();
Jason Monkcaf37622015-08-18 12:33:50 -0400119 }
Jason Monk9d02a432016-01-20 16:33:46 -0500120 if (changed) {
121 distributeTiles();
122 }
123 return changed;
Jason Monkcaf37622015-08-18 12:33:50 -0400124 }
125
126 @Override
127 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
128 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
129 // The ViewPager likes to eat all of the space, instead force it to wrap to the max height
130 // of the pages.
131 int maxHeight = 0;
132 final int N = getChildCount();
133 for (int i = 0; i < N; i++) {
134 int height = getChildAt(i).getMeasuredHeight();
135 if (height > maxHeight) {
136 maxHeight = height;
137 }
138 }
139 setMeasuredDimension(getMeasuredWidth(), maxHeight + mPageIndicator.getMeasuredHeight());
140 }
141
Jason Monk9d02a432016-01-20 16:33:46 -0500142 private final Runnable mDistribute = new Runnable() {
143 @Override
144 public void run() {
145 distributeTiles();
146 }
147 };
148
Jason Monkcaf37622015-08-18 12:33:50 -0400149 public static class TilePage extends TileLayout {
Jason Monk94a1bf62015-10-20 08:43:36 -0700150 private int mMaxRows = 3;
Jason Monkcaf37622015-08-18 12:33:50 -0400151
152 public TilePage(Context context, AttributeSet attrs) {
153 super(context, attrs);
Jason Monkb9c00192015-10-07 11:45:33 -0400154 updateResources();
Jason Monkcaf37622015-08-18 12:33:50 -0400155 }
156
Jason Monk9d02a432016-01-20 16:33:46 -0500157 @Override
158 public boolean updateResources() {
159 if (super.updateResources()) {
160 mMaxRows = mColumns != 3 ? 2 : 3;
161 return true;
162 }
163 return false;
164 }
165
Jason Monkbd6dbb02015-09-03 15:46:25 -0400166 public void setMaxRows(int maxRows) {
167 mMaxRows = maxRows;
168 }
169
Jason Monkbd6dbb02015-09-03 15:46:25 -0400170 public boolean isFull() {
Jason Monkcaf37622015-08-18 12:33:50 -0400171 return mRecords.size() >= mColumns * mMaxRows;
172 }
173 }
174
175 private final PagerAdapter mAdapter = new PagerAdapter() {
176 public void destroyItem(ViewGroup container, int position, Object object) {
177 if (DEBUG) Log.d(TAG, "Destantiating " + position);
178 // TODO: Find way to clean up the extra pages.
179 container.removeView((View) object);
180 }
181
182 public Object instantiateItem(ViewGroup container, int position) {
183 if (DEBUG) Log.d(TAG, "Instantiating " + position);
Jason Monke4e69302016-01-20 11:27:15 -0500184 ViewGroup view = mPages.get(position);
Jason Monkcaf37622015-08-18 12:33:50 -0400185 container.addView(view);
186 return view;
187 }
188
189 @Override
190 public int getCount() {
191 return mNumPages;
192 }
193
194 @Override
195 public boolean isViewFromObject(View view, Object object) {
196 return view == object;
197 }
198 };
199}