QS: Add long-press to customize prototype - part 1

Start adding prototype to long-press to go to customization view
for QS.  Currently it allows re-arranging and resetting.  Later
it will have more.

Change-Id: Ib2ba0f93ac2f4cced4f146d39771a8a17ac05bc2
This commit is contained in:
Jason Monk
2015-09-03 15:46:25 -04:00
parent c6c28731e5
commit bd6dbb0698
14 changed files with 773 additions and 13 deletions

View File

@@ -0,0 +1,25 @@
<?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
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginStart="40dp"
android:layout_marginEnd="40dp"
android:background="#4dffffff" />

View File

@@ -0,0 +1,39 @@
<?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.customize.NonPagedTileLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tiles_container"
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:paddingStart="@dimen/qs_quick_actions_padding"
android:paddingEnd="@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" />
</com.android.systemui.qs.customize.NonPagedTileLayout>

View File

@@ -0,0 +1,47 @@
<?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.customize.QSCustomizer
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="?android:attr/windowBackground">
<Toolbar
android:id="@*android:id/action_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:navigationContentDescription="@*android:string/action_bar_up_description"
android:background="?android:attr/colorPrimary"
style="?android:attr/toolbarStyle" />
<com.android.systemui.tuner.AutoScrollView
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:elevation="2dp">
<com.android.systemui.qs.customize.CustomQSPanel
android:id="@+id/quick_settings_panel"
android:background="#0000"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.android.systemui.tuner.AutoScrollView>
</com.android.systemui.qs.customize.QSCustomizer>

View File

@@ -1156,4 +1156,7 @@
settings are -->
<string name="experimental">Experimental</string>
<string name="save" translatable="false">Save</string>
<string name="qs_customize" translatable="false">Allow long-press customize in Quick Settings</string>
</resources>

View File

@@ -37,6 +37,10 @@
android:key="qs_paged_panel"
android:title="@string/qs_paging" />
<com.android.systemui.tuner.TunerSwitch
android:key="qs_allow_customize"
android:title="@string/qs_customize" />
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -75,8 +75,8 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
@Override
public void setTileVisibility(TileRecord tile, int visibility) {
tile.tileView.setVisibility(visibility);
// TODO: Do something smarter here.
distributeTiles();
// // TODO: Do something smarter here.
// distributeTiles();
}
@Override
@@ -183,13 +183,17 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
mAllowDual = false;
}
public void setMaxRows(int maxRows) {
mMaxRows = maxRows;
}
private void clear() {
if (DEBUG) Log.d(TAG, "Clearing page");
removeAllViews();
mRecords.clear();
}
private boolean isFull() {
public boolean isFull() {
return mRecords.size() >= mColumns * mMaxRows;
}
}

View File

@@ -39,6 +39,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile.DetailAdapter;
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.settings.BrightnessController;
import com.android.systemui.settings.ToggleSlider;
import com.android.systemui.statusbar.phone.QSTileHost;
@@ -54,8 +55,9 @@ 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";
public static final String QS_ALLOW_CUSTOMIZE = "qs_allow_customize";
private final Context mContext;
protected final Context mContext;
protected final ArrayList<TileRecord> mRecords = new ArrayList<TileRecord>();
private final View mDetail;
private final ViewGroup mDetailContent;
@@ -79,8 +81,10 @@ public class QSPanel extends FrameLayout implements Tunable {
private QSFooter mFooter;
private boolean mGridContentVisible = true;
private LinearLayout mQsContainer;
private QSTileLayout mTileLayout;
protected LinearLayout mQsContainer;
protected QSTileLayout mTileLayout;
private QSCustomizer mCustomizePanel;
public QSPanel(Context context) {
this(context, null);
@@ -131,7 +135,8 @@ public class QSPanel extends FrameLayout implements Tunable {
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
TunerService.get(mContext).addTunable(this, QS_SHOW_BRIGHTNESS, QS_PAGED_PANEL);
TunerService.get(mContext).addTunable(this,
QS_SHOW_BRIGHTNESS, QS_PAGED_PANEL, QS_ALLOW_CUSTOMIZE);
}
@Override
@@ -160,6 +165,17 @@ public class QSPanel extends FrameLayout implements Tunable {
for (int i = 0; i < mRecords.size(); i++) {
mTileLayout.addTile(mRecords.get(i));
}
} else if (QS_ALLOW_CUSTOMIZE.equals(key)) {
if (newValue != null && Integer.parseInt(newValue) != 0) {
mCustomizePanel = (QSCustomizer) LayoutInflater.from(mContext)
.inflate(R.layout.qs_customize_panel, null);
mCustomizePanel.setHost(mHost);
} else {
if (mCustomizePanel != null && mCustomizePanel.isCustomizing()) {
mCustomizePanel.hide();
}
mCustomizePanel = null;
}
}
}
@@ -224,6 +240,12 @@ public class QSPanel extends FrameLayout implements Tunable {
mFooter.onConfigurationChanged();
}
public void onCollapse() {
if (mCustomizePanel != null && mCustomizePanel.isCustomizing()) {
mCustomizePanel.hide();
}
}
public void setExpanded(boolean expanded) {
if (mExpanded == expanded) return;
mExpanded = expanded;
@@ -307,7 +329,7 @@ public class QSPanel extends FrameLayout implements Tunable {
r.tileView.onStateChanged(state);
}
private void addTile(final QSTile<?> tile) {
protected void addTile(final QSTile<?> tile) {
final TileRecord r = new TileRecord();
r.tile = tile;
r.tileView = tile.createTileView(mContext);
@@ -358,7 +380,13 @@ public class QSPanel extends FrameLayout implements Tunable {
final View.OnLongClickListener longClick = new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
r.tile.longClick();
if (mCustomizePanel != null) {
if (!mCustomizePanel.isCustomizing()) {
mCustomizePanel.show();
}
} else {
r.tile.longClick();
}
return true;
}
};
@@ -374,10 +402,16 @@ public class QSPanel extends FrameLayout implements Tunable {
}
public boolean isShowingDetail() {
return mDetailRecord != null;
return mDetailRecord != null
|| (mCustomizePanel != null && mCustomizePanel.isCustomizing());
}
public void closeDetail() {
if (mCustomizePanel != null && mCustomizePanel.isCustomizing()) {
// Treat this as a detail panel for now, to make things easy.
mCustomizePanel.hide();
return;
}
showDetail(false, mDetailRecord);
}
@@ -527,7 +561,7 @@ public class QSPanel extends FrameLayout implements Tunable {
int y;
}
protected static final class TileRecord extends Record {
public static final class TileRecord extends Record {
public QSTile<?> tile;
public QSTileView tileView;
public int row;

View File

@@ -65,6 +65,8 @@ public abstract class QSTile<TState extends State> implements Listenable {
private TState mTmpState = newTileState();
private boolean mAnnounceNextStateChange;
private String mTileSpec;
abstract protected TState newTileState();
abstract protected void handleClick();
abstract protected void handleUpdateState(TState state, Object arg);
@@ -83,7 +85,15 @@ public abstract class QSTile<TState extends State> implements Listenable {
mContext = host.getContext();
mHandler = new H(host.getLooper());
}
public String getTileSpec() {
return mTileSpec;
}
public void setTileSpec(String tileSpec) {
mTileSpec = tileSpec;
}
public int getTileType() {
return QSTileView.QS_TYPE_NORMAL;
}

View File

@@ -54,6 +54,11 @@ public class TileLayout extends ViewGroup implements QSTileLayout {
removeView(tile.tileView);
}
public void removeAllViews() {
mRecords.clear();
super.removeAllViews();
}
@Override
public void setTileVisibility(TileRecord tile, int visibility) {
tile.tileView.setVisibility(visibility);

View File

@@ -0,0 +1,113 @@
/*
* 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.customize;
import android.content.ClipData;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import com.android.systemui.R;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.QSTileView;
import com.android.systemui.statusbar.phone.QSTileHost;
/**
* A version of QSPanel that allows tiles to be dragged around rather than
* clicked on. Dragging is started here, receiving is handled in the NonPagedTileLayout,
* and the saving/ordering is handled by the CustomQSTileHost.
*/
public class CustomQSPanel extends QSPanel implements OnTouchListener {
private CustomQSTileHost mCustomHost;
private ClipData mCurrentClip;
private View mCurrentView;
public CustomQSPanel(Context context, AttributeSet attrs) {
super(context, attrs);
mTileLayout = (QSTileLayout) LayoutInflater.from(mContext)
.inflate(R.layout.qs_customize_layout, mQsContainer, false);
mQsContainer.addView((View) mTileLayout, 1 /* Between brightness and footer */);
((NonPagedTileLayout) mTileLayout).setCustomQsPanel(this);
}
@Override
public void setHost(QSTileHost host) {
super.setHost(host);
mCustomHost = (CustomQSTileHost) host;
}
@Override
public void onTuningChanged(String key, String newValue) {
if (key.equals(QS_SHOW_BRIGHTNESS)) {
// No Brightness for you.
super.onTuningChanged(key, "0");
}
}
@Override
protected void addTile(QSTile<?> tile) {
super.addTile(tile);
if (tile.getTileType() != QSTileView.QS_TYPE_QUICK) {
TileRecord record = mRecords.get(mRecords.size() - 1);
if (record.tileView.getTag() == record.tile) {
return;
}
record.tileView.setTag(record.tile);
record.tileView.setVisibility(View.VISIBLE);
record.tileView.init(null, null, null);
record.tileView.setOnTouchListener(this);
if (mCurrentClip != null
&& mCurrentClip.getItemAt(0).getText().toString().equals(tile.getTileSpec())) {
record.tileView.setAlpha(.3f);
mCurrentView = record.tileView;
}
}
}
public void tileSelected(View v) {
String sourceSpec = mCurrentClip.getItemAt(0).getText().toString();
String destSpec = ((QSTile<?>) v.getTag()).getTileSpec();
if (!sourceSpec.equals(destSpec)) {
mCustomHost.moveTo(sourceSpec, destSpec);
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
String tileSpec = (String) ((QSTile<?>) v.getTag()).getTileSpec();
mCurrentView = v;
mCurrentClip = ClipData.newPlainText(tileSpec, tileSpec);
View.DragShadowBuilder shadow = new View.DragShadowBuilder(v);
((View) getParent().getParent()).startDrag(mCurrentClip, shadow, null, 0);
v.setAlpha(.3f);
return true;
}
return false;
}
public void onDragEnded() {
mCurrentView.setAlpha(1f);
mCurrentView = null;
mCurrentClip = null;
}
}

View File

@@ -0,0 +1,167 @@
/*
* 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.customize;
import android.app.ActivityManager;
import android.content.Context;
import android.provider.Settings.Secure;
import android.text.TextUtils;
import android.util.Log;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.phone.QSTileHost;
import com.android.systemui.statusbar.policy.SecurityController;
import java.util.ArrayList;
import java.util.List;
/**
* @see CustomQSPanel
*/
public class CustomQSTileHost extends QSTileHost {
private static final String TAG = "CustomHost";
private List<String> mTiles;
private List<String> mSavedTiles;
public CustomQSTileHost(Context context, QSTileHost host) {
super(context, null, host.getBluetoothController(), host.getLocationController(),
host.getRotationLockController(), host.getNetworkController(),
host.getZenModeController(), host.getHotspotController(), host.getCastController(),
host.getFlashlightController(), host.getUserSwitcherController(),
host.getKeyguardMonitor(), new BlankSecurityController());
}
@Override
protected QSTile<?> createTile(String tileSpec) {
QSTile<?> tile = super.createTile(tileSpec);
tile.setTileSpec(tileSpec);
return tile;
}
@Override
public void onTuningChanged(String key, String newValue) {
// No Tunings For You.
if (TILES_SETTING.equals(key)) {
mSavedTiles = super.loadTileSpecs(newValue);
}
}
public void setSavedTiles() {
setTiles(mSavedTiles);
}
public void saveCurrentTiles() {
Secure.putStringForUser(getContext().getContentResolver(), TILES_SETTING,
TextUtils.join(",", mTiles), ActivityManager.getCurrentUser());
}
public void moveTo(String from, String to) {
int fromIndex = mTiles.indexOf(from);
if (fromIndex < 0) {
Log.e(TAG, "Unknown from tile " + from);
return;
}
int index = mTiles.indexOf(to);
if (index < 0) {
Log.e(TAG, "Unknown to tile " + to);
return;
}
mTiles.remove(fromIndex);
mTiles.add(index, from);
super.onTuningChanged(TILES_SETTING, null);
}
public void setTiles(List<String> tiles) {
mTiles = new ArrayList<>(tiles);
super.onTuningChanged(TILES_SETTING, null);
}
@Override
protected List<String> loadTileSpecs(String tileList) {
return mTiles;
}
public void replace(String oldTile, String newTile) {
if (oldTile.equals(newTile)) {
return;
}
MetricsLogger.action(getContext(), MetricsLogger.TUNER_QS_REORDER, oldTile + ","
+ newTile);
List<String> order = new ArrayList<>(mTileSpecs);
int index = order.indexOf(oldTile);
if (index < 0) {
Log.e(TAG, "Can't find " + oldTile);
return;
}
order.remove(newTile);
order.add(index, newTile);
setTiles(order);
}
/**
* Blank so that the customizing QS view doesn't show any security messages in the footer.
*/
private static class BlankSecurityController implements SecurityController {
@Override
public boolean hasDeviceOwner() {
return false;
}
@Override
public boolean hasProfileOwner() {
return false;
}
@Override
public String getDeviceOwnerName() {
return null;
}
@Override
public String getProfileOwnerName() {
return null;
}
@Override
public boolean isVpnEnabled() {
return false;
}
@Override
public String getPrimaryVpnName() {
return null;
}
@Override
public String getProfileVpnName() {
return null;
}
@Override
public void onUserSwitched(int newUserId) {
}
@Override
public void addCallback(SecurityControllerCallback callback) {
}
@Override
public void removeCallback(SecurityControllerCallback callback) {
}
}
}

View File

@@ -0,0 +1,167 @@
/*
* 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.customize;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.DragEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import com.android.systemui.R;
import com.android.systemui.qs.PagedTileLayout;
import com.android.systemui.qs.PagedTileLayout.TilePage;
import com.android.systemui.qs.QSPanel.QSTileLayout;
import com.android.systemui.qs.QSPanel.TileRecord;
import com.android.systemui.qs.QSTileView;
import com.android.systemui.qs.QuickTileLayout;
import java.util.ArrayList;
/**
* Similar to PagedTileLayout, except that instead of pages it lays them out
* vertically and expects to be inside a ScrollView.
* @see CustomQSPanel
*/
public class NonPagedTileLayout extends LinearLayout implements QSTileLayout {
private QuickTileLayout mQuickTiles;
private final ArrayList<TilePage> mPages = new ArrayList<>();
private final ArrayList<TileRecord> mTiles = new ArrayList<TileRecord>();
private CustomQSPanel mPanel;
private final Rect mHitRect = new Rect();
public NonPagedTileLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mQuickTiles = (QuickTileLayout) findViewById(R.id.quick_tile_layout);
TilePage page = (PagedTileLayout.TilePage) findViewById(R.id.tile_page);
page.setMaxRows(3 /* First page only gets 3 */);
mPages.add(page);
}
public void setCustomQsPanel(CustomQSPanel qsPanel) {
mPanel = qsPanel;
}
private void clear() {
mQuickTiles.removeAllViews();
for (int i = 0; i < mPages.size(); i++) {
mPages.get(i).removeAllViews();
}
}
@Override
public void addTile(TileRecord tile) {
mTiles.add(tile);
distributeTiles();
}
@Override
public void removeTile(TileRecord tile) {
if (mTiles.remove(tile)) {
distributeTiles();
}
}
private void distributeTiles() {
mQuickTiles.removeAllViews();
final int NP = mPages.size();
for (int i = 0; i < NP; i++) {
mPages.get(i).removeAllViews();
}
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);
mQuickTiles.addView(tile.tileView);
continue;
}
mPages.get(index).addTile(tile);
if (mPages.get(index).isFull()) {
if (++index == mPages.size()) {
LayoutInflater inflater = LayoutInflater.from(mContext);
inflater.inflate(R.layout.horizontal_divider, this);
mPages.add((TilePage) inflater.inflate(R.layout.qs_paged_page, this, false));
addView(mPages.get(mPages.size() - 1));
}
}
}
}
@Override
public void setTileVisibility(TileRecord tile, int visibility) {
// All tiles visible here, so that they can be re-arranged.
tile.tileView.setVisibility(View.VISIBLE);
}
@Override
public int getOffsetTop(TileRecord tile) {
// TODO: Fix this.
return getTop();
}
@Override
public void updateResources() {
}
@Override
public boolean onDragEvent(DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_LOCATION:
float x = event.getX();
float y = event.getY();
if (contains(mQuickTiles, x, y)) {
// TODO: Reset to pre-drag state.
} else {
final int NP = mPages.size();
for (int i = 0; i < NP; i++) {
TilePage page = mPages.get(i);
if (contains(page, x, y)) {
x -= page.getLeft();
y -= page.getTop();
final int NC = page.getChildCount();
for (int j = 0; j < NC; j++) {
View child = page.getChildAt(j);
if (contains(child, x, y)) {
mPanel.tileSelected(child);
}
}
break;
}
}
}
break;
case DragEvent.ACTION_DRAG_ENDED:
mPanel.onDragEnded();
break;
}
return true;
}
private boolean contains(View v, float x, float y) {
v.getHitRect(mHitRect);
return mHitRect.contains((int) x, (int) y);
}
}

View File

@@ -0,0 +1,142 @@
/*
* 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.customize;
import android.content.Context;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.Toolbar;
import android.widget.Toolbar.OnMenuItemClickListener;
import com.android.systemui.R;
import com.android.systemui.SystemUIApplication;
import com.android.systemui.qs.QSTile.Host.Callback;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.phone.QSTileHost;
import com.android.systemui.tuner.QSPagingSwitch;
import java.util.ArrayList;
/**
* Allows full-screen customization of QS, through show() and hide().
*
* This adds itself to the status bar window, so it can appear on top of quick settings and
* *someday* do fancy animations to get into/out of it.
*/
public class QSCustomizer extends LinearLayout implements OnMenuItemClickListener, Callback {
private static final int MENU_SAVE = Menu.FIRST;
private static final int MENU_RESET = Menu.FIRST + 1;
private PhoneStatusBar mPhoneStatusBar;
private Toolbar mToolbar;
private CustomQSPanel mQsPanel;
private boolean isShown;
private CustomQSTileHost mHost;
public QSCustomizer(Context context, AttributeSet attrs) {
super(new ContextThemeWrapper(context, android.R.style.Theme_Material), attrs);
mPhoneStatusBar = ((SystemUIApplication) mContext.getApplicationContext())
.getComponent(PhoneStatusBar.class);
}
public void setHost(QSTileHost host) {
mHost = new CustomQSTileHost(mContext, host);
mHost.setCallback(this);
mQsPanel.setTiles(mHost.getTiles());
mQsPanel.setHost(mHost);
mHost.setSavedTiles();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mToolbar = (Toolbar) findViewById(com.android.internal.R.id.action_bar);
TypedValue value = new TypedValue();
mContext.getTheme().resolveAttribute(android.R.attr.homeAsUpIndicator, value, true);
mToolbar.setNavigationIcon(
getResources().getDrawable(value.resourceId, mContext.getTheme()));
mToolbar.setNavigationOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO: Is this all we want...?
hide();
}
});
mToolbar.setOnMenuItemClickListener(this);
mToolbar.getMenu().add(Menu.NONE, MENU_SAVE, 0, mContext.getString(R.string.save))
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
mToolbar.getMenu().add(Menu.NONE, MENU_RESET, 0,
mContext.getString(com.android.internal.R.string.reset));
mQsPanel = (CustomQSPanel) findViewById(R.id.quick_settings_panel);
}
public void show() {
isShown = true;
mHost.setSavedTiles();
// TODO: Fancy shmancy reveal.
mPhoneStatusBar.getStatusBarWindow().addView(this);
}
public void hide() {
isShown = false;
// TODO: Similarly awesome or better hide.
mPhoneStatusBar.getStatusBarWindow().removeView(this);
}
public boolean isCustomizing() {
return isShown;
}
private void reset() {
ArrayList<String> tiles = new ArrayList<>();
for (String tile : QSPagingSwitch.QS_PAGE_TILES.split(",")) {
tiles.add(tile);
}
mHost.setTiles(tiles);
}
private void save() {
mHost.saveCurrentTiles();
hide();
}
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case MENU_SAVE:
save();
break;
case MENU_RESET:
reset();
break;
}
return true;
}
@Override
public void onTilesChanged() {
mQsPanel.setTiles(mHost.getTiles());
}
}

View File

@@ -8,7 +8,7 @@ import com.android.systemui.statusbar.phone.QSTileHost;
public class QSPagingSwitch extends TunerSwitch {
private static final String QS_PAGE_TILES =
public static final String QS_PAGE_TILES =
"dwifi,dbt,inversion,dnd,cell,airplane,rotation,flashlight,location,"
+ "hotspot,qwifi,qbt,qrotation,qflashlight,qairplane,cast";