QS prototype work
- All work is defaulted to off, with no changes to UI
- Add 'quick' QS tiles, which have circles around them and no text,
they just toggle things like wifi
- Add tuner switch to hide brightness from QS panel
- Add paginated QS layout, it shows a row of the circle tiles across
the top, followed by 3 rows of normal tiles, following pages
have 4 rows, dual tiles are not allowed in this mode
- Add tuner switch to turn on paging for QS, and set to a set of tiles
that look ok with it
Change-Id: Ia2d2eb36f8953033ce4810cd3628fcb86315fe46
diff --git a/packages/SystemUI/res/drawable/ic_qs_circle.xml b/packages/SystemUI/res/drawable/ic_qs_circle.xml
new file mode 100644
index 0000000..57223cf
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_circle.xml
@@ -0,0 +1,30 @@
+<!--
+ Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="2.2"
+ android:viewportHeight="2.2">
+
+ <path
+ android:strokeColor="#4DFFFFFF"
+ android:strokeWidth=".05"
+ android:pathData="M.1,1.1
+ c0,.55 .45,1 1,1
+ c.55,0 1,-.45 1,-1
+ c0,-.55 -.45,-1 -1,-1
+ c-.55,0 -1,.45 -1,1"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/qs_paged_page.xml b/packages/SystemUI/res/layout/qs_paged_page.xml
new file mode 100644
index 0000000..eef08ba
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_paged_page.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<view
+ class="com.android.systemui.qs.PagedTileLayout$TilePage"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/tile_page"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
diff --git a/packages/SystemUI/res/layout/qs_paged_tile_layout.xml b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml
new file mode 100644
index 0000000..6c236ea
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<com.android.systemui.qs.PagedTileLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <view
+ class="com.android.systemui.qs.PagedTileLayout$FirstPage"
+ android:id="@+id/first_page"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <com.android.systemui.qs.QuickTileLayout
+ android:id="@+id/quick_tile_layout"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/qs_quick_actions_height"
+ android:orientation="horizontal"
+ android:paddingLeft="@dimen/qs_quick_actions_padding"
+ android:paddingRight="@dimen/qs_quick_actions_padding" />
+
+ <view
+ class="com.android.systemui.qs.PagedTileLayout$TilePage"
+ android:id="@+id/tile_page"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ </view>
+
+ <com.android.systemui.qs.PageIndicator
+ android:id="@+id/page_indicator"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal|bottom"
+ android:gravity="center" />
+
+</com.android.systemui.qs.PagedTileLayout>
diff --git a/packages/SystemUI/res/layout/qs_tile_layout.xml b/packages/SystemUI/res/layout/qs_tile_layout.xml
new file mode 100644
index 0000000..b5d1a1e
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_tile_layout.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<com.android.systemui.qs.TileLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent" />
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 527248c..c070a0e 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -90,5 +90,9 @@
<declare-styleable name="AlphaOptimizedImageView">
<attr name="hasOverlappingRendering" format="boolean" />
</declare-styleable>
+
+ <declare-styleable name="TunerSwitch">
+ <attr name="defValue" format="boolean" />
+ </declare-styleable>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 03ea73c..3817741 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -164,6 +164,9 @@
<dimen name="pull_span_min">25dp</dimen>
<dimen name="qs_tile_height">88dp</dimen>
+ <dimen name="qs_quick_actions_height">88dp</dimen>
+ <dimen name="qs_quick_actions_padding">25dp</dimen>
+ <dimen name="qs_page_indicator_size">12dp</dimen>
<dimen name="qs_tile_icon_size">24dp</dimen>
<dimen name="qs_tile_text_size">12sp</dimen>
<dimen name="qs_tile_divider_height">1dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8b3f2d8..b732e99 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1145,4 +1145,15 @@
<!-- Description of setting to show clock seconds [CHAR LIMIT=NONE] -->
<string name="clock_seconds_desc">Show clock seconds in the status bar. May impact battery life.</string>
+ <!-- Button that leads to page to rearrange quick settings tiles [CHAR LIMIT=60] -->
+ <string name="qs_rearrange">Rearrange Quick Settings</string>
+ <!-- Option to show brightness bar in quick settings [CHAR LIMIT=60] -->
+ <string name="show_brightness">Show brightness in Quick Settings</string>
+ <!-- Option to use new paging layout in quick settings [CHAR LIMIT=60] -->
+ <string name="qs_paging">Use paging in Quick Settings</string>
+
+ <!-- Category in the System UI Tuner settings, where new/experimental
+ settings are -->
+ <string name="experimental">Experimental</string>
+
</resources>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index beb863c..5980108 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -15,11 +15,32 @@
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:sysui="http://schemas.android.com/apk/res-auto"
android:title="@string/system_ui_tuner">
- <Preference
- android:key="qs_tuner"
- android:title="@string/quick_settings" />
+ <PreferenceScreen
+ android:title="@string/quick_settings">
+
+ <Preference
+ android:key="qs_tuner"
+ android:title="@string/qs_rearrange" />
+
+ <PreferenceCategory
+ android:title="@string/experimental">
+
+ <com.android.systemui.tuner.TunerSwitch
+ android:key="qs_show_brightness"
+ android:title="@string/show_brightness"
+ sysui:defValue="true" />
+
+ <com.android.systemui.tuner.QSPagingSwitch
+ android:key="qs_paged_panel"
+ android:title="@string/qs_paging" />
+
+ </PreferenceCategory>
+
+ </PreferenceScreen>
+
<PreferenceScreen
android:title="@string/status_bar" >
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
new file mode 100644
index 0000000..1200266
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
@@ -0,0 +1,86 @@
+package com.android.systemui.qs;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import com.android.systemui.R;
+
+public class PageIndicator extends LinearLayout {
+
+ private final int mPageIndicatorSize;
+
+ public PageIndicator(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setGravity(Gravity.CENTER);
+ mPageIndicatorSize =
+ (int) mContext.getResources().getDimension(R.dimen.qs_page_indicator_size);
+ }
+
+ public void setNumPages(int numPages) {
+ while (numPages < getChildCount()) {
+ removeViewAt(getChildCount() - 1);
+ }
+ while (numPages > getChildCount()) {
+ SinglePageIndicator v = new SinglePageIndicator(mContext);
+ v.setAmount(0);
+ addView(v, new LayoutParams(mPageIndicatorSize, mPageIndicatorSize));
+ }
+ }
+
+ public void setLocation(float location) {
+ int index = (int) location;
+ location -= index;
+
+ final int N = getChildCount();
+ for (int i = 0; i < N; i++) {
+ float amount = 0;
+ if (i == index) {
+ amount = 1 - location;
+ } else if (i == index + 1) {
+ amount = location;
+ }
+ ((SinglePageIndicator) getChildAt(i)).setAmount(amount);
+ }
+ }
+
+ // This could be done with a circle drawable and an ImageView, but this seems
+ // easier for now.
+ public static class SinglePageIndicator extends View {
+ private static final int MIN_ALPHA = 0x4d;
+ private static final int MAX_ALPHA = 0xff;
+
+ private static final float MIN_SIZE = .55f;
+ private static final float MAX_SIZE = .7f;
+
+ private final Paint mPaint;
+ private float mSize;
+
+ public SinglePageIndicator(Context context) {
+ super(context);
+ mPaint = new Paint();
+ mPaint.setColor(0xffffffff);
+ mPaint.setAlpha(MAX_ALPHA);
+ }
+
+ public void setAmount(float amount) {
+ mSize = amount * (MAX_SIZE - MIN_SIZE) + MIN_SIZE;
+ int alpha = (int) (amount * (MAX_ALPHA - MIN_ALPHA)) + MIN_ALPHA;
+ mPaint.setAlpha(alpha);
+ postInvalidate();
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ int minDimen = Math.min(getWidth(), getHeight()) / 2;
+ float radius = mSize * minDimen;
+ float x = getWidth() / 2f;
+ float y = getHeight() / 2f;
+ canvas.drawCircle(x, y, radius, mPaint);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
new file mode 100644
index 0000000..ece7022
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -0,0 +1,221 @@
+package com.android.systemui.qs;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+import com.android.internal.widget.PagerAdapter;
+import com.android.internal.widget.ViewPager;
+import com.android.systemui.R;
+import com.android.systemui.qs.QSPanel.QSTileLayout;
+import com.android.systemui.qs.QSPanel.TileRecord;
+
+import java.util.ArrayList;
+
+public class PagedTileLayout extends ViewPager implements QSTileLayout {
+
+ private static final boolean DEBUG = false;
+
+ private static final String TAG = "PagedTileLayout";
+
+ private final ArrayList<TileRecord> mTiles = new ArrayList<TileRecord>();
+ private final ArrayList<TilePage> mPages = new ArrayList<TilePage>();
+
+ private FirstPage mFirstPage;
+ private PageIndicator mPageIndicator;
+
+ private int mNumPages;
+
+ public PagedTileLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setAdapter(mAdapter);
+ setOnPageChangeListener(new OnPageChangeListener() {
+ @Override
+ public void onPageSelected(int position) {
+ if (mPageIndicator == null) return;
+ mPageIndicator.setLocation(position);
+ }
+
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ if (mPageIndicator == null) return;
+ mPageIndicator.setLocation(position + positionOffset);
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+ }
+ });
+ setCurrentItem(0);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mPageIndicator = (PageIndicator) findViewById(R.id.page_indicator);
+ ((LayoutParams) mPageIndicator.getLayoutParams()).isDecor = true;
+
+ mFirstPage = (FirstPage) findViewById(R.id.first_page);
+ removeView(mFirstPage); // We don't actually want this on the view yet, just inflated.
+ mPages.add(mFirstPage.mTilePage);
+ }
+
+ @Override
+ public int getOffsetTop(TileRecord tile) {
+ if (tile.tileView.getParent() == mFirstPage.mTilePage) {
+ return mFirstPage.getTop() + mFirstPage.mTilePage.getTop();
+ }
+ return ((ViewGroup) tile.tileView.getParent()).getTop();
+ }
+
+ @Override
+ public void setTileVisibility(TileRecord tile, int visibility) {
+ tile.tileView.setVisibility(visibility);
+ // TODO: Do something smarter here.
+ distributeTiles();
+ }
+
+ @Override
+ public void addTile(TileRecord tile) {
+ mTiles.add(tile);
+ distributeTiles();
+ }
+
+ @Override
+ public void removeTile(TileRecord tile) {
+ if (mTiles.remove(tile)) {
+ distributeTiles();
+ }
+ }
+
+ private void distributeTiles() {
+ if (DEBUG) Log.d(TAG, "Distributing tiles");
+ mFirstPage.mQuickQuickTiles.removeAllViews();
+ final int NP = mPages.size();
+ for (int i = 0; i < NP; i++) {
+ mPages.get(i).clear();
+ }
+ int index = 0;
+ final int NT = mTiles.size();
+ for (int i = 0; i < NT; i++) {
+ TileRecord tile = mTiles.get(i);
+ if (tile.tile.getTileType() == QSTileView.QS_TYPE_QUICK) {
+ tile.tileView.setType(QSTileView.QS_TYPE_QUICK);
+ mFirstPage.mQuickQuickTiles.addView(tile.tileView);
+ continue;
+ }
+ if (mPages.get(index).isFull()) {
+ if (++index == mPages.size()) {
+ if (DEBUG) Log.d(TAG, "Adding page for " + tile.tile.getClass().getSimpleName());
+ mPages.add((TilePage) LayoutInflater.from(mContext)
+ .inflate(R.layout.qs_paged_page, this, false));
+ }
+ }
+ if (DEBUG) Log.d(TAG, "Adding " + tile.tile.getClass().getSimpleName() + " to "
+ + index);
+ mPages.get(index).addTile(tile);
+ }
+ if (mNumPages != index + 1) {
+ mNumPages = index + 1;
+ mPageIndicator.setNumPages(mNumPages);
+ mAdapter.notifyDataSetChanged();
+ }
+ }
+
+ @Override
+ public void updateResources() {
+ for (int i = 0; i < mPages.size(); i++) {
+ mPages.get(i).updateResources();
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ // The ViewPager likes to eat all of the space, instead force it to wrap to the max height
+ // of the pages.
+ int maxHeight = 0;
+ final int N = getChildCount();
+ for (int i = 0; i < N; i++) {
+ int height = getChildAt(i).getMeasuredHeight();
+ if (height > maxHeight) {
+ maxHeight = height;
+ }
+ }
+ setMeasuredDimension(getMeasuredWidth(), maxHeight + mPageIndicator.getMeasuredHeight());
+ }
+
+ public static class FirstPage extends LinearLayout {
+ private LinearLayout mQuickQuickTiles;
+ private TilePage mTilePage;
+
+ public FirstPage(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mQuickQuickTiles = (LinearLayout) findViewById(R.id.quick_tile_layout);
+ mTilePage = (TilePage) findViewById(R.id.tile_page);
+ // Less rows on first page, because it needs room for the quick tiles.
+ mTilePage.mMaxRows = 3;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // The ViewPager will try to make us taller, don't do it unless we need to.
+ heightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec),
+ MeasureSpec.AT_MOST);
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+ }
+
+ public static class TilePage extends TileLayout {
+ private int mMaxRows = 4;
+
+ public TilePage(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mAllowDual = false;
+ }
+
+ private void clear() {
+ if (DEBUG) Log.d(TAG, "Clearing page");
+ removeAllViews();
+ mRecords.clear();
+ }
+
+ private boolean isFull() {
+ return mRecords.size() >= mColumns * mMaxRows;
+ }
+ }
+
+ private final PagerAdapter mAdapter = new PagerAdapter() {
+ public void destroyItem(ViewGroup container, int position, Object object) {
+ if (DEBUG) Log.d(TAG, "Destantiating " + position);
+ // TODO: Find way to clean up the extra pages.
+ container.removeView((View) object);
+ }
+
+ public Object instantiateItem(ViewGroup container, int position) {
+ if (DEBUG) Log.d(TAG, "Instantiating " + position);
+ ViewGroup view = position == 0 ? mFirstPage : mPages.get(position);
+ container.addView(view);
+ return view;
+ }
+
+ @Override
+ public int getCount() {
+ return mNumPages;
+ }
+
+ @Override
+ public boolean isViewFromObject(View view, Object object) {
+ return view == object;
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index b640cf1..683af97 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -43,12 +43,17 @@
import com.android.systemui.settings.ToggleSlider;
import com.android.systemui.statusbar.phone.QSTileHost;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
import java.util.ArrayList;
import java.util.Collection;
/** View that represents the quick settings tile panel. **/
-public class QSPanel extends FrameLayout {
+public class QSPanel extends FrameLayout implements Tunable {
+
+ public static final String QS_SHOW_BRIGHTNESS = "qs_show_brightness";
+ public static final String QS_PAGED_PANEL = "qs_paged_panel";
private final Context mContext;
protected final ArrayList<TileRecord> mRecords = new ArrayList<TileRecord>();
@@ -75,7 +80,7 @@
private boolean mGridContentVisible = true;
private LinearLayout mQsContainer;
- private TileLayout mTileLayout;
+ private QSTileLayout mTileLayout;
public QSPanel(Context context) {
this(context, null);
@@ -104,10 +109,7 @@
addView(mQsContainer);
- mTileLayout = new TileLayout(mContext, mRecords);
-
mQsContainer.addView(mBrightnessView);
- mQsContainer.addView(mTileLayout);
mQsContainer.addView(mFooter.getView());
mClipper = new QSDetailClipper(mDetail);
updateResources();
@@ -126,6 +128,41 @@
});
}
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ TunerService.get(mContext).addTunable(this, QS_SHOW_BRIGHTNESS, QS_PAGED_PANEL);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ TunerService.get(mContext).removeTunable(this);
+ super.onDetachedFromWindow();
+ }
+
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ if (QS_SHOW_BRIGHTNESS.equals(key)) {
+ mBrightnessView.setVisibility(newValue == null || Integer.parseInt(newValue) != 0
+ ? VISIBLE : GONE);
+ } else if (QS_PAGED_PANEL.equals(key)) {
+ if (mTileLayout != null) {
+ for (int i = 0; i < mRecords.size(); i++) {
+ mTileLayout.removeTile(mRecords.get(i));
+ }
+ mQsContainer.removeView((View) mTileLayout);
+ }
+ int layout = newValue != null && Integer.parseInt(newValue) != 0
+ ? R.layout.qs_paged_tile_layout : R.layout.qs_tile_layout;
+ mTileLayout =
+ (QSTileLayout) LayoutInflater.from(mContext).inflate(layout, mQsContainer, false);
+ mQsContainer.addView((View) mTileLayout, 1 /* Between brightness and footer */);
+ for (int i = 0; i < mRecords.size(); i++) {
+ mTileLayout.addTile(mRecords.get(i));
+ }
+ }
+ }
+
private void updateDetailText() {
mDetailDoneButton.setText(R.string.quick_settings_done);
mDetailSettingsButton.setText(R.string.quick_settings_more_settings);
@@ -164,7 +201,9 @@
refreshAllTiles();
}
updateDetailText();
- mTileLayout.updateResources();
+ if (mTileLayout != null) {
+ mTileLayout.updateResources();
+ }
}
@Override
@@ -240,18 +279,18 @@
mHandler.obtainMessage(H.SHOW_DETAIL, show ? 1 : 0, 0, r).sendToTarget();
}
- private void setTileVisibility(View v, int visibility) {
- mHandler.obtainMessage(H.SET_TILE_VISIBILITY, visibility, 0, v).sendToTarget();
+ private void setTileVisibility(TileRecord record, int visibility) {
+ mHandler.obtainMessage(H.SET_TILE_VISIBILITY, visibility, 0, record).sendToTarget();
}
- private void handleSetTileVisibility(View v, int visibility) {
- if (visibility == v.getVisibility()) return;
- v.setVisibility(visibility);
+ private void handleSetTileVisibility(TileRecord tile, int visibility) {
+ if (visibility == tile.tileView.getVisibility()) return;
+ mTileLayout.setTileVisibility(tile, visibility);
}
public void setTiles(Collection<QSTile<?>> tiles) {
for (TileRecord record : mRecords) {
- removeView(record.tileView);
+ mTileLayout.removeTile(record);
}
mRecords.clear();
for (QSTile<?> tile : tiles) {
@@ -264,7 +303,7 @@
private void drawTile(TileRecord r, QSTile.State state) {
final int visibility = state.visible ? VISIBLE : GONE;
- setTileVisibility(r.tileView, visibility);
+ setTileVisibility(r, visibility);
r.tileView.onStateChanged(state);
}
@@ -329,7 +368,9 @@
r.tile.refreshState();
mRecords.add(r);
- mTileLayout.addView(r.tileView);
+ if (mTileLayout != null) {
+ mTileLayout.addTile(r);
+ }
}
public boolean isShowingDetail() {
@@ -371,7 +412,7 @@
}
r.tile.setDetailListening(show);
int x = r.tileView.getLeft() + r.tileView.getWidth() / 2;
- int y = r.tileView.getTop() + mTileLayout.getTop() + r.tileView.getHeight() / 2;
+ int y = r.tileView.getTop() + mTileLayout.getOffsetTop(r) + r.tileView.getHeight() / 2;
handleShowDetailImpl(r, show, x, y);
}
@@ -474,7 +515,7 @@
if (msg.what == SHOW_DETAIL) {
handleShowDetail((Record)msg.obj, msg.arg1 != 0);
} else if (msg.what == SET_TILE_VISIBILITY) {
- handleSetTileVisibility((View)msg.obj, msg.arg1);
+ handleSetTileVisibility((TileRecord) msg.obj, msg.arg1);
}
}
}
@@ -534,4 +575,12 @@
void onToggleStateChanged(boolean state);
void onScanStateChanged(boolean state);
}
+
+ public interface QSTileLayout {
+ void addTile(TileRecord tile);
+ void removeTile(TileRecord tile);
+ void setTileVisibility(TileRecord tile, int visibility);
+ int getOffsetTop(TileRecord tile);
+ void updateResources();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index b330582..9b3372c3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -83,9 +83,13 @@
mContext = host.getContext();
mHandler = new H(host.getLooper());
}
+
+ public int getTileType() {
+ return QSTileView.QS_TYPE_NORMAL;
+ }
- public boolean supportsDualTargets() {
- return false;
+ public final boolean supportsDualTargets() {
+ return getTileType() == QSTileView.QS_TYPE_DUAL;
}
public Host getHost() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index 6d26a3b..08cdc1e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -48,6 +48,10 @@
private static final Typeface CONDENSED = Typeface.create("sans-serif-condensed",
Typeface.NORMAL);
+ public static final int QS_TYPE_NORMAL = 0;
+ public static final int QS_TYPE_DUAL = 1;
+ public static final int QS_TYPE_QUICK = 2;
+
protected final Context mContext;
private final View mIcon;
private final View mDivider;
@@ -61,13 +65,15 @@
private TextView mLabel;
private QSDualTileLabel mDualLabel;
- private boolean mDual;
+ private int mType;
private OnClickListener mClickPrimary;
private OnClickListener mClickSecondary;
private OnLongClickListener mLongClick;
private Drawable mTileBackground;
private RippleDrawable mRipple;
+ private View mCircle;
+
public QSTileView(Context context) {
super(context);
@@ -89,6 +95,9 @@
mIcon = createIcon();
addView(mIcon);
+ mCircle = createCircleIcon();
+ addView(mCircle);
+
mDivider = new View(mContext);
mDivider.setBackgroundColor(context.getColor(R.color.qs_tile_divider));
final int dh = res.getDimensionPixelSize(R.dimen.qs_tile_divider_height);
@@ -131,12 +140,12 @@
}
if (mDualLabel != null) {
labelText = mDualLabel.getText();
- labelDescription = mLabel.getContentDescription();
+ labelDescription = mLabel != null ? mLabel.getContentDescription() : null;
removeView(mDualLabel);
mDualLabel = null;
}
final Resources res = mContext.getResources();
- if (mDual) {
+ if (mType == QS_TYPE_DUAL) {
mDualLabel = new QSDualTileLabel(mContext);
mDualLabel.setId(View.generateViewId());
mDualLabel.setBackgroundResource(R.drawable.btn_borderless_rect);
@@ -157,7 +166,7 @@
}
addView(mDualLabel);
mDualLabel.setAccessibilityTraversalAfter(mTopBackgroundView.getId());
- } else {
+ } else if (mType == QS_TYPE_NORMAL) {
mLabel = new TextView(mContext);
mLabel.setTextColor(mContext.getColor(R.color.qs_tile_text));
mLabel.setGravity(Gravity.CENTER_HORIZONTAL);
@@ -174,16 +183,16 @@
}
}
- public boolean setDual(boolean dual) {
- final boolean changed = dual != mDual;
- mDual = dual;
+ public boolean setType(int type) {
+ final boolean changed = mType != type;
+ mType = type;
if (changed) {
recreateLabel();
}
if (mTileBackground instanceof RippleDrawable) {
setRipple((RippleDrawable) mTileBackground);
}
- if (dual) {
+ if (mType == QS_TYPE_DUAL) {
mTopBackgroundView.setOnClickListener(mClickPrimary);
setOnClickListener(null);
setClickable(false);
@@ -197,9 +206,10 @@
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
setBackground(mTileBackground);
}
- mTopBackgroundView.setFocusable(dual);
- setFocusable(!dual);
- mDivider.setVisibility(dual ? VISIBLE : GONE);
+ mTopBackgroundView.setFocusable(mType == QS_TYPE_DUAL);
+ setFocusable(mType != QS_TYPE_DUAL);
+ mDivider.setVisibility(mType == QS_TYPE_DUAL ? VISIBLE : GONE);
+ mCircle.setVisibility(mType == QS_TYPE_QUICK ? VISIBLE : GONE);
postInvalidate();
return changed;
}
@@ -225,6 +235,21 @@
return icon;
}
+ protected View createCircleIcon() {
+ final ImageView icon = new ImageView(mContext);
+ icon.setImageResource(R.drawable.ic_qs_circle);
+ // TODO: Not this.
+ icon.setPadding(20, 20, 20, 20);
+ return icon;
+ }
+
+ protected View createCircle() {
+ final ImageView icon = new ImageView(mContext);
+ icon.setId(android.R.id.icon);
+ icon.setScaleType(ScaleType.CENTER_INSIDE);
+ return icon;
+ }
+
private Drawable newTileBackground() {
final int[] attrs = new int[] { android.R.attr.selectableItemBackgroundBorderless };
final TypedArray ta = mContext.obtainStyledAttributes(attrs);
@@ -234,7 +259,7 @@
}
private View labelView() {
- return mDual ? mDualLabel : mLabel;
+ return mType == QS_TYPE_DUAL ? mDualLabel : mLabel;
}
@Override
@@ -243,9 +268,18 @@
final int h = MeasureSpec.getSize(heightMeasureSpec);
final int iconSpec = exactly(mIconSizePx);
mIcon.measure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.AT_MOST), iconSpec);
- labelView().measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h, MeasureSpec.AT_MOST));
- if (mDual) {
- mDivider.measure(widthMeasureSpec, exactly(mDivider.getLayoutParams().height));
+ switch (mType) {
+ case QS_TYPE_QUICK:
+ mCircle.measure(
+ MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY));
+ break;
+ case QS_TYPE_DUAL:
+ mDivider.measure(widthMeasureSpec, exactly(mDivider.getLayoutParams().height));
+ default:
+ labelView().measure(widthMeasureSpec,
+ MeasureSpec.makeMeasureSpec(h, MeasureSpec.AT_MOST));
+ break;
}
int heightSpec = exactly(
mIconSizePx + mTilePaddingBelowIconPx + mTilePaddingTopPx);
@@ -268,6 +302,10 @@
top += mTileSpacingPx;
top += mTilePaddingTopPx;
final int iconLeft = (w - mIcon.getMeasuredWidth()) / 2;
+ if (mType == QS_TYPE_QUICK) {
+ top = (h - mIcon.getMeasuredHeight()) / 2;
+ layout(mCircle, 0, 0);
+ }
layout(mIcon, iconLeft, top);
if (mRipple != null) {
updateRippleSize(w, h);
@@ -275,17 +313,19 @@
}
top = mIcon.getBottom();
top += mTilePaddingBelowIconPx;
- if (mDual) {
+ if (mType == QS_TYPE_DUAL) {
layout(mDivider, 0, top);
top = mDivider.getBottom();
}
- layout(labelView(), 0, top);
+ if (mType != QS_TYPE_QUICK) {
+ layout(labelView(), 0, top);
+ }
}
private void updateRippleSize(int width, int height) {
// center the touch feedback on the center of the icon, and dial it down a bit
final int cx = width / 2;
- final int cy = mDual ? mIcon.getTop() + mIcon.getHeight() / 2 : height / 2;
+ final int cy = mType == QS_TYPE_DUAL ? mIcon.getTop() + mIcon.getHeight() / 2 : height / 2;
final int rad = (int)(mIcon.getHeight() * 1.25f);
mRipple.setHotspotBounds(cx - rad, cy - rad, cx + rad, cy + rad);
}
@@ -298,11 +338,11 @@
if (mIcon instanceof ImageView) {
setIcon((ImageView) mIcon, state);
}
- if (mDual) {
+ if (mType == QS_TYPE_DUAL) {
mDualLabel.setText(state.label);
mDualLabel.setContentDescription(state.dualLabelContentDescription);
mTopBackgroundView.setContentDescription(state.contentDescription);
- } else {
+ } else if (mType == QS_TYPE_NORMAL) {
mLabel.setText(state.label);
setContentDescription(state.contentDescription);
}
@@ -338,7 +378,7 @@
public View updateAccessibilityOrder(View previousView) {
View firstView;
View lastView;
- if (mDual) {
+ if (mType == QS_TYPE_DUAL) {
lastView = mDualLabel;
firstView = mTopBackgroundView;
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/QuickTileLayout.java
new file mode 100644
index 0000000..bb2340c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickTileLayout.java
@@ -0,0 +1,28 @@
+package com.android.systemui.qs;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+public class QuickTileLayout extends LinearLayout {
+
+ public QuickTileLayout(Context context) {
+ this(context, null);
+ }
+
+ public QuickTileLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setGravity(Gravity.CENTER);
+ }
+
+ @Override
+ public void addView(View child, int index, ViewGroup.LayoutParams params) {
+ // Make everything square at the height of this view.
+ params = new LayoutParams(params.height, params.height);
+ ((LinearLayout.LayoutParams) params).weight = 1;
+ super.addView(child, index, params);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 02b8fe3..e0c39c5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -2,35 +2,63 @@
import android.content.Context;
import android.content.res.Resources;
+import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import com.android.systemui.R;
+import com.android.systemui.qs.QSPanel.QSTileLayout;
import com.android.systemui.qs.QSPanel.TileRecord;
import java.util.ArrayList;
-public class TileLayout extends ViewGroup {
+public class TileLayout extends ViewGroup implements QSTileLayout {
private static final float TILE_ASPECT = 1.2f;
private static final String TAG = "TileLayout";
private int mDualTileUnderlap;
- private int mColumns;
+ protected int mColumns;
private int mCellWidth;
private int mCellHeight;
private int mLargeCellWidth;
private int mLargeCellHeight;
- private final ArrayList<TileRecord> mRecords;
+ protected boolean mAllowDual = true;
- public TileLayout(Context context, ArrayList<TileRecord> records) {
- super(context);
- mRecords = records;
+ protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
+
+ public TileLayout(Context context) {
+ this(context, null);
+ }
+
+ public TileLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
updateResources();
}
+ @Override
+ public int getOffsetTop(TileRecord tile) {
+ return getTop();
+ }
+
+ public void addTile(TileRecord tile) {
+ mRecords.add(tile);
+ addView(tile.tileView);
+ }
+
+ @Override
+ public void removeTile(TileRecord tile) {
+ mRecords.remove(tile);
+ removeView(tile.tileView);
+ }
+
+ @Override
+ public void setTileVisibility(TileRecord tile, int visibility) {
+ tile.tileView.setVisibility(visibility);
+ }
+
public void updateResources() {
final Resources res = mContext.getResources();
final int columns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns));
@@ -56,10 +84,11 @@
if (record.tileView.getVisibility() == GONE) continue;
// wrap to next column if we've reached the max # of columns
// also don't allow dual + single tiles on the same row
- if (r == -1 || c == (mColumns - 1) || rowIsDual != record.tile.supportsDualTargets()) {
+ if (r == -1 || c == (mColumns - 1)
+ || rowIsDual != (mAllowDual && record.tile.supportsDualTargets())) {
r++;
c = 0;
- rowIsDual = record.tile.supportsDualTargets();
+ rowIsDual = mAllowDual && record.tile.supportsDualTargets();
} else {
c++;
}
@@ -70,7 +99,8 @@
View previousView = this;
for (TileRecord record : mRecords) {
- if (record.tileView.setDual(record.tile.supportsDualTargets())) {
+ if (record.tileView.setType(mAllowDual ? record.tile.getTileType()
+ : QSTileView.QS_TYPE_NORMAL)) {
record.tileView.handleStateChanged(record.tile.getState());
}
if (record.tileView.getVisibility() == GONE) continue;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index abce31f..fd70d02 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -31,6 +31,7 @@
import com.android.systemui.qs.QSDetailItems;
import com.android.systemui.qs.QSDetailItems.Item;
import com.android.systemui.qs.QSTile;
+import com.android.systemui.qs.QSTileView;
import com.android.systemui.statusbar.policy.BluetoothController;
import java.util.Collection;
@@ -43,15 +44,18 @@
private final BluetoothController mController;
private final BluetoothDetailAdapter mDetailAdapter;
- public BluetoothTile(Host host) {
+ private final boolean mAlwaysDetail;
+
+ public BluetoothTile(Host host, boolean alwaysDetail) {
super(host);
+ mAlwaysDetail = alwaysDetail;
mController = host.getBluetoothController();
mDetailAdapter = new BluetoothDetailAdapter();
}
@Override
- public boolean supportsDualTargets() {
- return true;
+ public int getTileType() {
+ return QSTileView.QS_TYPE_DUAL;
}
@Override
@@ -75,6 +79,10 @@
@Override
protected void handleClick() {
+ if (mAlwaysDetail) {
+ handleSecondaryClick();
+ return;
+ }
final boolean isEnabled = (Boolean)mState.value;
MetricsLogger.action(mContext, getMetricsCategory(), !isEnabled);
mController.setBluetoothEnabled(!isEnabled);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QAirplaneTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QAirplaneTile.java
new file mode 100644
index 0000000..13ccaaa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QAirplaneTile.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import com.android.systemui.qs.QSTileView;
+
+/** Quick settings tile: Wifi **/
+public class QAirplaneTile extends AirplaneModeTile {
+
+ public QAirplaneTile(Host host) {
+ super(host);
+ }
+
+ @Override
+ public int getTileType() {
+ return QSTileView.QS_TYPE_QUICK;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QBluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QBluetoothTile.java
new file mode 100644
index 0000000..02975cb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QBluetoothTile.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import com.android.systemui.qs.QSTileView;
+
+/** Quick settings tile: Bluetooth **/
+public class QBluetoothTile extends BluetoothTile {
+
+ public QBluetoothTile(Host host) {
+ super(host, false);
+ }
+
+ @Override
+ public int getTileType() {
+ return QSTileView.QS_TYPE_QUICK;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QFlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QFlashlightTile.java
new file mode 100644
index 0000000..31035cd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QFlashlightTile.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import com.android.systemui.qs.QSTileView;
+
+/** Quick settings tile: Wifi **/
+public class QFlashlightTile extends FlashlightTile {
+
+ public QFlashlightTile(Host host) {
+ super(host);
+ }
+
+ @Override
+ public int getTileType() {
+ return QSTileView.QS_TYPE_QUICK;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QRotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QRotationLockTile.java
new file mode 100644
index 0000000..e066bab
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QRotationLockTile.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import com.android.systemui.qs.QSTileView;
+
+/** Quick settings tile: Rotation **/
+public class QRotationLockTile extends RotationLockTile {
+
+ public QRotationLockTile(Host host) {
+ super(host);
+ }
+
+ @Override
+ public int getTileType() {
+ return QSTileView.QS_TYPE_QUICK;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QWifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QWifiTile.java
new file mode 100644
index 0000000..87194fb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QWifiTile.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import com.android.systemui.qs.QSTileView;
+
+/** Quick settings tile: Wifi **/
+public class QWifiTile extends WifiTile {
+
+ public QWifiTile(Host host) {
+ super(host, false);
+ }
+
+ @Override
+ public int getTileType() {
+ return QSTileView.QS_TYPE_QUICK;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index e654efd..3295e14 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -50,16 +50,19 @@
private final WifiSignalCallback mSignalCallback = new WifiSignalCallback();
- public WifiTile(Host host) {
+ private final boolean mAlwaysDetail;
+
+ public WifiTile(Host host, boolean alwaysDetail) {
super(host);
+ mAlwaysDetail = alwaysDetail;
mController = host.getNetworkController();
mWifiController = mController.getAccessPointController();
mDetailAdapter = new WifiDetailAdapter();
}
@Override
- public boolean supportsDualTargets() {
- return true;
+ public int getTileType() {
+ return QSTileView.QS_TYPE_DUAL;
}
@Override
@@ -97,6 +100,10 @@
@Override
protected void handleClick() {
+ if (mAlwaysDetail) {
+ handleSecondaryClick();
+ return;
+ }
mState.copyTo(mStateBeforeClick);
MetricsLogger.action(mContext, getMetricsCategory(), !mState.enabled);
mController.setWifiEnabled(!mState.enabled);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 12434ac..385c5d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -36,6 +36,11 @@
import com.android.systemui.qs.tiles.HotspotTile;
import com.android.systemui.qs.tiles.IntentTile;
import com.android.systemui.qs.tiles.LocationTile;
+import com.android.systemui.qs.tiles.QAirplaneTile;
+import com.android.systemui.qs.tiles.QBluetoothTile;
+import com.android.systemui.qs.tiles.QFlashlightTile;
+import com.android.systemui.qs.tiles.QRotationLockTile;
+import com.android.systemui.qs.tiles.QWifiTile;
import com.android.systemui.qs.tiles.RotationLockTile;
import com.android.systemui.qs.tiles.WifiTile;
import com.android.systemui.statusbar.policy.BluetoothController;
@@ -64,7 +69,7 @@
private static final String TAG = "QSTileHost";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- protected static final String TILES_SETTING = "sysui_qs_tiles";
+ public static final String TILES_SETTING = "sysui_qs_tiles";
private final Context mContext;
private final PhoneStatusBar mStatusBar;
@@ -243,8 +248,8 @@
}
protected QSTile<?> createTile(String tileSpec) {
- if (tileSpec.equals("wifi")) return new WifiTile(this);
- else if (tileSpec.equals("bt")) return new BluetoothTile(this);
+ if (tileSpec.equals("wifi")) return new WifiTile(this, false);
+ else if (tileSpec.equals("bt")) return new BluetoothTile(this, false);
else if (tileSpec.equals("inversion")) return new ColorInversionTile(this);
else if (tileSpec.equals("cell")) return new CellularTile(this);
else if (tileSpec.equals("airplane")) return new AirplaneModeTile(this);
@@ -254,6 +259,16 @@
else if (tileSpec.equals("location")) return new LocationTile(this);
else if (tileSpec.equals("cast")) return new CastTile(this);
else if (tileSpec.equals("hotspot")) return new HotspotTile(this);
+ // Detail only versions of wifi and bluetooth.
+ else if (tileSpec.equals("dwifi")) return new WifiTile(this, true);
+ else if (tileSpec.equals("dbt")) return new BluetoothTile(this, true);
+ // Quick tiles, no text.
+ else if (tileSpec.equals("qwifi")) return new QWifiTile(this);
+ else if (tileSpec.equals("qbt")) return new QBluetoothTile(this);
+ else if (tileSpec.equals("qairplane")) return new QAirplaneTile(this);
+ else if (tileSpec.equals("qrotation")) return new QRotationLockTile(this);
+ else if (tileSpec.equals("qflashlight")) return new QFlashlightTile(this);
+ // Intent tiles.
else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(this,tileSpec);
else throw new IllegalArgumentException("Bad tile spec: " + tileSpec);
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/QSPagingSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/QSPagingSwitch.java
new file mode 100644
index 0000000..343a231
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/QSPagingSwitch.java
@@ -0,0 +1,26 @@
+package com.android.systemui.tuner;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.util.AttributeSet;
+
+import com.android.systemui.statusbar.phone.QSTileHost;
+
+public class QSPagingSwitch extends TunerSwitch {
+
+ private static final String QS_PAGE_TILES =
+ "dwifi,dbt,inversion,dnd,cell,airplane,rotation,flashlight,location,"
+ + "hotspot,qwifi,qbt,qrotation,qflashlight,qairplane,cast";
+
+ public QSPagingSwitch(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected boolean persistBoolean(boolean value) {
+ Settings.Secure.putString(getContext().getContentResolver(), QSTileHost.TILES_SETTING,
+ value ? QS_PAGE_TILES : "default");
+ return super.persistBoolean(value);
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
index 37ac098..772f866 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
@@ -389,10 +389,11 @@
mView = super.createTileView(context);
return mView;
}
-
+
@Override
- public boolean supportsDualTargets() {
- return "wifi".equals(mSpec) || "bt".equals(mSpec);
+ public int getTileType() {
+ return "wifi".equals(mSpec) || "bt".equals(mSpec) ? QSTileView.QS_TYPE_DUAL
+ : QSTileView.QS_TYPE_NORMAL;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index 96ad756..920f875 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -36,6 +36,8 @@
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
+import com.android.systemui.qs.QSPanel;
+import com.android.systemui.tuner.TunerService.Tunable;
import static com.android.systemui.BatteryMeterView.SHOW_PERCENT_SETTING;
@@ -55,6 +57,8 @@
private SwitchPreference mBatteryPct;
+ private Preference mQsTuner;
+
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -62,7 +66,8 @@
getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
setHasOptionsMenu(true);
- findPreference(KEY_QS_TUNER).setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ mQsTuner = findPreference(KEY_QS_TUNER);
+ mQsTuner.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
@@ -96,6 +101,13 @@
}
}).show();
}
+ TunerService.get(getContext()).addTunable(mQsPaging, QSPanel.QS_PAGED_PANEL);
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ TunerService.get(getContext()).removeTunable(mQsPaging);
}
@Override
@@ -167,4 +179,12 @@
return true;
}
};
+
+ private final Tunable mQsPaging = new Tunable() {
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ // Only enable QS rearranging when paging is off, because its very broken.
+ mQsTuner.setEnabled(newValue == null || Integer.parseInt(newValue) == 0);
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
index 0740e08..54078b0 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
@@ -1,16 +1,23 @@
package com.android.systemui.tuner;
import android.content.Context;
+import android.content.res.TypedArray;
import android.preference.SwitchPreference;
import android.provider.Settings;
import android.util.AttributeSet;
+import com.android.systemui.R;
import com.android.systemui.tuner.TunerService.Tunable;
public class TunerSwitch extends SwitchPreference implements Tunable {
+ private final boolean mDefault;
+
public TunerSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TunerSwitch);
+ mDefault = a.getBoolean(R.styleable.TunerSwitch_defValue, false);
}
@Override
@@ -27,7 +34,7 @@
@Override
public void onTuningChanged(String key, String newValue) {
- setChecked(newValue != null && Integer.parseInt(newValue) != 0);
+ setChecked(newValue != null ? Integer.parseInt(newValue) != 0 : mDefault);
}
@Override