1 package com.android.systemui.qs;
2 
3 import android.content.Context;
4 import android.content.res.Resources;
5 import android.util.AttributeSet;
6 import android.view.View;
7 import android.view.ViewGroup;
8 
9 import com.android.systemui.R;
10 import com.android.systemui.qs.QSPanel.QSTileLayout;
11 import com.android.systemui.qs.QSPanel.TileRecord;
12 
13 import java.util.ArrayList;
14 
15 public class TileLayout extends ViewGroup implements QSTileLayout {
16 
17     private static final float TILE_ASPECT = 1.2f;
18 
19     private static final String TAG = "TileLayout";
20 
21     protected int mColumns;
22     protected int mCellWidth;
23     protected int mCellHeight;
24     protected int mCellMargin;
25 
26     protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
27     private int mCellMarginTop;
28     private boolean mListening;
29 
TileLayout(Context context)30     public TileLayout(Context context) {
31         this(context, null);
32     }
33 
TileLayout(Context context, AttributeSet attrs)34     public TileLayout(Context context, AttributeSet attrs) {
35         super(context, attrs);
36         setFocusableInTouchMode(true);
37         updateResources();
38     }
39 
40     @Override
getOffsetTop(TileRecord tile)41     public int getOffsetTop(TileRecord tile) {
42         return getTop();
43     }
44 
45     @Override
setListening(boolean listening)46     public void setListening(boolean listening) {
47         if (mListening == listening) return;
48         mListening = listening;
49         for (TileRecord record : mRecords) {
50             record.tile.setListening(this, mListening);
51         }
52     }
53 
addTile(TileRecord tile)54     public void addTile(TileRecord tile) {
55         mRecords.add(tile);
56         tile.tile.setListening(this, mListening);
57         addView(tile.tileView);
58     }
59 
60     @Override
removeTile(TileRecord tile)61     public void removeTile(TileRecord tile) {
62         mRecords.remove(tile);
63         tile.tile.setListening(this, false);
64         removeView(tile.tileView);
65     }
66 
removeAllViews()67     public void removeAllViews() {
68         for (TileRecord record : mRecords) {
69             record.tile.setListening(this, false);
70         }
71         mRecords.clear();
72         super.removeAllViews();
73     }
74 
updateResources()75     public boolean updateResources() {
76         final Resources res = mContext.getResources();
77         final int columns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns));
78         mCellHeight = mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_height);
79         mCellMargin = res.getDimensionPixelSize(R.dimen.qs_tile_margin);
80         mCellMarginTop = res.getDimensionPixelSize(R.dimen.qs_tile_margin_top);
81         if (mColumns != columns) {
82             mColumns = columns;
83             requestLayout();
84             return true;
85         }
86         return false;
87     }
88 
89     @Override
onMeasure(int widthMeasureSpec, int heightMeasureSpec)90     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
91         final int numTiles = mRecords.size();
92         final int width = MeasureSpec.getSize(widthMeasureSpec);
93         final int rows = (numTiles + mColumns - 1) / mColumns;
94         mCellWidth = (width - (mCellMargin * (mColumns + 1))) / mColumns;
95 
96         View previousView = this;
97         for (TileRecord record : mRecords) {
98             if (record.tileView.getVisibility() == GONE) continue;
99             record.tileView.measure(exactly(mCellWidth), exactly(mCellHeight));
100             previousView = record.tileView.updateAccessibilityOrder(previousView);
101         }
102         setMeasuredDimension(width,
103                 (mCellHeight + mCellMargin) * rows + (mCellMarginTop - mCellMargin));
104     }
105 
exactly(int size)106     private static int exactly(int size) {
107         return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
108     }
109 
110     @Override
onLayout(boolean changed, int l, int t, int r, int b)111     protected void onLayout(boolean changed, int l, int t, int r, int b) {
112         final int w = getWidth();
113         boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
114         int row = 0;
115         int column = 0;
116         for (int i = 0; i < mRecords.size(); i++, column++) {
117             if (column == mColumns) {
118                 row++;
119                 column -= mColumns;
120             }
121             TileRecord record = mRecords.get(i);
122             int left = getColumnStart(column);
123             final int top = getRowTop(row);
124             int right;
125             if (isRtl) {
126                 right = w - left;
127                 left = right - mCellWidth;
128             } else {
129                 right = left + mCellWidth;
130             }
131             record.tileView.layout(left, top, right, top + record.tileView.getMeasuredHeight());
132         }
133     }
134 
getRowTop(int row)135     private int getRowTop(int row) {
136         return row * (mCellHeight + mCellMargin) + mCellMarginTop;
137     }
138 
getColumnStart(int column)139     private int getColumnStart(int column) {
140         return column * (mCellWidth + mCellMargin) + mCellMargin;
141     }
142 }
143