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