diff options
| author | 2015-09-09 18:00:31 +0000 | |
|---|---|---|
| committer | 2015-09-09 18:00:31 +0000 | |
| commit | 435acfc88917e3535462ea520b01d0868266acd2 (patch) | |
| tree | 0138afdc11f5ccd5032e9fa4065cbd9884904446 | |
| parent | f83e94d5205e614cddb354676413773b265cef17 (diff) | |
| parent | f7fe83f36b93681d0df7ddbd4cd727501fadd471 (diff) | |
Merge "QS: Add long-press to customize prototype - part 2"
8 files changed, 273 insertions, 65 deletions
diff --git a/packages/SystemUI/res/drawable/ic_close_white.xml b/packages/SystemUI/res/drawable/ic_close_white.xml new file mode 100644 index 000000000000..ce64047e5de4 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_close_white.xml @@ -0,0 +1,24 @@ +<!-- + 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="24.0dp" + android:height="24.0dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:pathData="M19.000000,6.400000l-1.400000,-1.400000 -5.600000,5.600000 -5.600000,-5.600000 -1.400000,1.400000 5.600000,5.600000 -5.600000,5.600000 1.400000,1.400000 5.600000,-5.600000 5.600000,5.600000 1.400000,-1.400000 -5.600000,-5.600000z" + android:fillColor="#FFFFFFFF"/> +</vector> diff --git a/packages/SystemUI/res/layout/qs_customize_panel.xml b/packages/SystemUI/res/layout/qs_customize_panel.xml index 6beac3175636..fbd29b0858da 100644 --- a/packages/SystemUI/res/layout/qs_customize_panel.xml +++ b/packages/SystemUI/res/layout/qs_customize_panel.xml @@ -21,13 +21,58 @@ android:orientation="vertical" android:background="?android:attr/windowBackground"> - <Toolbar - android:id="@*android:id/action_bar" + <FrameLayout 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" /> + android:background="?android:attr/colorPrimary"> + + <LinearLayout + android:id="@+id/drag_buttons" + android:layout_width="match_parent" + android:layout_height="fill_parent" + android:orientation="horizontal"> + <FrameLayout + android:layout_width="0dp" + android:layout_height="fill_parent" + android:layout_weight="1"> + <com.android.systemui.qs.customize.DropButton + android:id="@+id/info_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:gravity="center" + android:drawableStart="@drawable/ic_info" + android:drawablePadding="10dp" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="@android:color/white" + android:text="@string/qs_customize_info" /> + </FrameLayout> + <FrameLayout + android:layout_width="0dp" + android:layout_height="fill_parent" + android:layout_weight="1"> + <com.android.systemui.qs.customize.DropButton + android:id="@+id/remove_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:gravity="center" + android:drawableStart="@drawable/ic_close_white" + android:drawablePadding="10dp" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="@android:color/white" + android:text="@string/qs_customize_remove" /> + </FrameLayout> + </LinearLayout> + + <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" + style="?android:attr/toolbarStyle" + android:background="?android:attr/colorPrimary" /> + </FrameLayout> <com.android.systemui.tuner.AutoScrollView android:layout_width="match_parent" diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index da7eadcedc3f..db1e688c1244 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1158,5 +1158,7 @@ <string name="save" translatable="false">Save</string> <string name="qs_customize" translatable="false">Allow long-press customize in Quick Settings</string> + <string name="qs_customize_info" translatable="false">Info</string> + <string name="qs_customize_remove" translatable="false">Remove</string> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomQSPanel.java index fe752207ff61..8866e558d6fb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomQSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomQSPanel.java @@ -19,26 +19,21 @@ 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, + * clicked on. Dragging starting and receiving is handled in the NonPagedTileLayout, * and the saving/ordering is handled by the CustomQSTileHost. */ -public class CustomQSPanel extends QSPanel implements OnTouchListener { +public class CustomQSPanel extends QSPanel { private CustomQSTileHost mCustomHost; - private ClipData mCurrentClip; - private View mCurrentView; public CustomQSPanel(Context context, AttributeSet attrs) { super(context, attrs); @@ -62,52 +57,26 @@ public class CustomQSPanel extends QSPanel implements OnTouchListener { } } - @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 CustomQSTileHost getCustomHost() { + return mCustomHost; } - public void tileSelected(View v) { - String sourceSpec = mCurrentClip.getItemAt(0).getText().toString(); - String destSpec = ((QSTile<?>) v.getTag()).getTileSpec(); + public void tileSelected(QSTile<?> tile, ClipData currentClip) { + String sourceSpec = getSpec(currentClip); + String destSpec = tile.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 ClipData getClip(QSTile<?> tile) { + String tileSpec = tile.getTileSpec(); + // TODO: Something better than plain text. + // TODO: Once using something better than plain text, stop listening to non-QS drag events. + return ClipData.newPlainText(tileSpec, tileSpec); } - public void onDragEnded() { - mCurrentView.setAlpha(1f); - mCurrentView = null; - mCurrentClip = null; + public String getSpec(ClipData data) { + return data.getItemAt(0).getText().toString(); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomQSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomQSTileHost.java index 095112912ce5..84b05d0055ea 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomQSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomQSTileHost.java @@ -37,6 +37,7 @@ public class CustomQSTileHost extends QSTileHost { private static final String TAG = "CustomHost"; private List<String> mTiles; private List<String> mSavedTiles; + private ArrayList<String> mStash; public CustomQSTileHost(Context context, QSTileHost host) { super(context, null, host.getBluetoothController(), host.getLocationController(), @@ -70,6 +71,14 @@ public class CustomQSTileHost extends QSTileHost { TextUtils.join(",", mTiles), ActivityManager.getCurrentUser()); } + public void stashCurrentTiles() { + mStash = new ArrayList<>(mTiles); + } + + public void unstashTiles() { + setTiles(mStash); + } + public void moveTo(String from, String to) { int fromIndex = mTiles.indexOf(from); if (fromIndex < 0) { @@ -86,6 +95,13 @@ public class CustomQSTileHost extends QSTileHost { super.onTuningChanged(TILES_SETTING, null); } + public void remove(String spec) { + if (!mTiles.remove(spec)) { + Log.e(TAG, "Unknown remove spec " + spec); + } + super.onTuningChanged(TILES_SETTING, null); + } + public void setTiles(List<String> tiles) { mTiles = new ArrayList<>(tiles); super.onTuningChanged(TILES_SETTING, null); diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/DropButton.java b/packages/SystemUI/src/com/android/systemui/qs/customize/DropButton.java new file mode 100644 index 000000000000..0e15f2b12116 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/DropButton.java @@ -0,0 +1,70 @@ +/* + * 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.DragEvent; +import android.view.View; +import android.view.View.OnDragListener; +import android.widget.TextView; + +public class DropButton extends TextView implements OnDragListener { + + private OnDropListener mListener; + + public DropButton(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + // TODO: Don't do this, instead make this view the right size... + ((View) getParent()).setOnDragListener(this); + } + + public void setOnDropListener(OnDropListener listener) { + mListener = listener; + } + + private void setHovering(boolean hovering) { + setAlpha(hovering ? .5f : 1); + } + + @Override + public boolean onDrag(View v, DragEvent event) { + switch (event.getAction()) { + case DragEvent.ACTION_DRAG_ENTERED: + setHovering(true); + break; + case DragEvent.ACTION_DROP: + if (mListener != null) { + mListener.onDrop(this, event.getClipData()); + } + case DragEvent.ACTION_DRAG_EXITED: + case DragEvent.ACTION_DRAG_ENDED: + setHovering(false); + break; + } + return true; + } + + public interface OnDropListener { + void onDrop(View v, ClipData data); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/NonPagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/customize/NonPagedTileLayout.java index 47c938429f96..fdcff1d10653 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/NonPagedTileLayout.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/NonPagedTileLayout.java @@ -15,12 +15,15 @@ */ package com.android.systemui.qs.customize; +import android.content.ClipData; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.view.DragEvent; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; +import android.view.View.OnTouchListener; import android.widget.LinearLayout; import com.android.systemui.R; @@ -28,6 +31,7 @@ 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.QSTile; import com.android.systemui.qs.QSTileView; import com.android.systemui.qs.QuickTileLayout; @@ -38,7 +42,7 @@ import java.util.ArrayList; * vertically and expects to be inside a ScrollView. * @see CustomQSPanel */ -public class NonPagedTileLayout extends LinearLayout implements QSTileLayout { +public class NonPagedTileLayout extends LinearLayout implements QSTileLayout, OnTouchListener { private QuickTileLayout mQuickTiles; private final ArrayList<TilePage> mPages = new ArrayList<>(); @@ -46,6 +50,9 @@ public class NonPagedTileLayout extends LinearLayout implements QSTileLayout { private CustomQSPanel mPanel; private final Rect mHitRect = new Rect(); + private ClipData mCurrentClip; + private View mCurrentView; + public NonPagedTileLayout(Context context, AttributeSet attrs) { super(context, attrs); } @@ -63,17 +70,23 @@ public class NonPagedTileLayout extends LinearLayout implements QSTileLayout { 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); + public void addTile(TileRecord record) { + mTiles.add(record); distributeTiles(); + if (record.tile.getTileType() == QSTileView.QS_TYPE_QUICK + || 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(record.tile.getTileSpec())) { + record.tileView.setAlpha(.3f); + mCurrentView = record.tileView; + } } @Override @@ -118,8 +131,8 @@ public class NonPagedTileLayout extends LinearLayout implements QSTileLayout { @Override public int getOffsetTop(TileRecord tile) { - // TODO: Fix this. - return getTop(); + // No touch feedback, so this isn't required. + return 0; } @Override @@ -145,7 +158,7 @@ public class NonPagedTileLayout extends LinearLayout implements QSTileLayout { for (int j = 0; j < NC; j++) { View child = page.getChildAt(j); if (contains(child, x, y)) { - mPanel.tileSelected(child); + mPanel.tileSelected((QSTile<?>) child.getTag(), mCurrentClip); } } break; @@ -154,12 +167,35 @@ public class NonPagedTileLayout extends LinearLayout implements QSTileLayout { } break; case DragEvent.ACTION_DRAG_ENDED: - mPanel.onDragEnded(); + onDragEnded(); break; } return true; } + @Override + public boolean onTouch(View v, MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + // Stash the current tiles, in case the drop is on info, that we we can restore + // the previous state. + mPanel.getCustomHost().stashCurrentTiles(); + mCurrentView = v; + mCurrentClip = mPanel.getClip((QSTile<?>) v.getTag()); + 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; + } + private boolean contains(View v, float x, float y) { v.getHitRect(mHitRect); return mHitRect.contains((int) x, (int) y); diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java index 7724a8759cbc..13a8dba2166d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java @@ -15,13 +15,17 @@ */ package com.android.systemui.qs.customize; +import android.app.AlertDialog; +import android.content.ClipData; import android.content.Context; import android.util.AttributeSet; import android.util.TypedValue; import android.view.ContextThemeWrapper; +import android.view.DragEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.Toolbar; import android.widget.Toolbar.OnMenuItemClickListener; @@ -29,8 +33,10 @@ 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.qs.customize.DropButton.OnDropListener; import com.android.systemui.statusbar.phone.PhoneStatusBar; import com.android.systemui.statusbar.phone.QSTileHost; +import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.tuner.QSPagingSwitch; import java.util.ArrayList; @@ -41,7 +47,8 @@ import java.util.ArrayList; * 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 { +public class QSCustomizer extends LinearLayout implements OnMenuItemClickListener, Callback, + OnDropListener { private static final int MENU_SAVE = Menu.FIRST; private static final int MENU_RESET = Menu.FIRST + 1; @@ -49,10 +56,13 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene private PhoneStatusBar mPhoneStatusBar; private Toolbar mToolbar; + private ViewGroup mDragButtons; private CustomQSPanel mQsPanel; private boolean isShown; private CustomQSTileHost mHost; + private DropButton mInfoButton; + private DropButton mRemoveButton; public QSCustomizer(Context context, AttributeSet attrs) { super(new ContextThemeWrapper(context, android.R.style.Theme_Material), attrs); @@ -90,6 +100,14 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene mContext.getString(com.android.internal.R.string.reset)); mQsPanel = (CustomQSPanel) findViewById(R.id.quick_settings_panel); + + mDragButtons = (ViewGroup) findViewById(R.id.drag_buttons); + setDragging(false); + + mInfoButton = (DropButton) findViewById(R.id.info_button); + mInfoButton.setOnDropListener(this); + mRemoveButton = (DropButton) findViewById(R.id.remove_button); + mRemoveButton.setOnDropListener(this); } public void show() { @@ -117,6 +135,10 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene mHost.setTiles(tiles); } + private void setDragging(boolean dragging) { + mToolbar.setVisibility(!dragging ? View.VISIBLE : View.INVISIBLE); + } + private void save() { mHost.saveCurrentTiles(); hide(); @@ -139,4 +161,28 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene public void onTilesChanged() { mQsPanel.setTiles(mHost.getTiles()); } + + public boolean onDragEvent(DragEvent event) { + switch (event.getAction()) { + case DragEvent.ACTION_DRAG_STARTED: + setDragging(true); + break; + case DragEvent.ACTION_DRAG_ENDED: + setDragging(false); + break; + } + return true; + } + + public void onDrop(View v, ClipData data) { + if (v == mRemoveButton) { + mHost.remove(mQsPanel.getSpec(data)); + } else if (v == mInfoButton) { + mHost.unstashTiles(); + SystemUIDialog dialog = new SystemUIDialog(mContext); + dialog.setTitle(mQsPanel.getSpec(data)); + dialog.setPositiveButton(R.string.ok, null); + dialog.show(); + } + } }
\ No newline at end of file |