From 703f295c2925ec38b1744eb5f9a0a3b3e972eec2 Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Wed, 30 Dec 2020 13:31:12 -0500 Subject: [PATCH] Prototype tiles with side labels This switches the tiles in QS to have the labels on the side, and display in two columns. Implemented: * animation in expansion interleaves the tiles from QQS into QS, so the first half of QQS moves to the left column * Tapping on the label has the same effect as long pressing Not implemented: * animated shape between QQS and QS * Edit screen Landscape with media has a bug where scrolling pages resets to first page. Also, animations in landscape with media don't look great. To enable: adb shell settings put secure sysui_side_labels 1 (0 to disable) and restart SystemUI Test: manual Test: SystemUITests Change-Id: I7468bc2c0b81e99a2de235a3b4312e678e968fd2 --- .../res/layout/qs_paged_page_side_labels.xml | 23 ++++ .../qs_paged_tile_layout_side_labels.xml | 27 ++++ .../SystemUI/res/layout/qs_tile_label.xml | 3 +- .../res/layout/qs_tile_label_divider.xml | 27 ++++ packages/SystemUI/res/values/attrs.xml | 4 + packages/SystemUI/res/values/dimens.xml | 1 + .../android/systemui/qs/PageIndicator.java | 1 + .../android/systemui/qs/PagedTileLayout.java | 42 ++++--- .../src/com/android/systemui/qs/QSPanel.java | 21 +++- .../systemui/qs/QuickQSPanelController.java | 16 ++- .../systemui/qs/SideLabelTileLayout.kt | 40 ++++++ .../com/android/systemui/qs/TileLayout.java | 18 ++- .../systemui/qs/tileimpl/QSFactoryImpl.java | 8 ++ .../systemui/qs/tileimpl/QSTileBaseView.java | 10 +- .../systemui/qs/tileimpl/QSTileView.java | 29 +++-- .../qs/tileimpl/QSTileViewHorizontal.kt | 116 ++++++++++++++++++ 16 files changed, 345 insertions(+), 41 deletions(-) create mode 100644 packages/SystemUI/res/layout/qs_paged_page_side_labels.xml create mode 100644 packages/SystemUI/res/layout/qs_paged_tile_layout_side_labels.xml create mode 100644 packages/SystemUI/res/layout/qs_tile_label_divider.xml create mode 100644 packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt create mode 100644 packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewHorizontal.kt diff --git a/packages/SystemUI/res/layout/qs_paged_page_side_labels.xml b/packages/SystemUI/res/layout/qs_paged_page_side_labels.xml new file mode 100644 index 0000000000000..c83077371bb06 --- /dev/null +++ b/packages/SystemUI/res/layout/qs_paged_page_side_labels.xml @@ -0,0 +1,23 @@ + + + diff --git a/packages/SystemUI/res/layout/qs_paged_tile_layout_side_labels.xml b/packages/SystemUI/res/layout/qs_paged_tile_layout_side_labels.xml new file mode 100644 index 0000000000000..efa240362f679 --- /dev/null +++ b/packages/SystemUI/res/layout/qs_paged_tile_layout_side_labels.xml @@ -0,0 +1,27 @@ + + + + diff --git a/packages/SystemUI/res/layout/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml index 81d44cfa49dda..571cbbcc77dbe 100644 --- a/packages/SystemUI/res/layout/qs_tile_label.xml +++ b/packages/SystemUI/res/layout/qs_tile_label.xml @@ -34,7 +34,8 @@ + android:layout_height="0dp" + android:visibility="gone" /> + + + \ No newline at end of file diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml index 897e3902b55c6..4059b49ec4868 100644 --- a/packages/SystemUI/res/values/attrs.xml +++ b/packages/SystemUI/res/values/attrs.xml @@ -167,5 +167,9 @@ + + + + diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 6f69483106e5d..e7d0214a08689 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -519,6 +519,7 @@ Scaled @dimen/qs_page_indicator-width by .4f. --> 6.4dp + 6dp 24dp 12sp 1dp diff --git a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java index 0053fea35262f..e822dd58fb988 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java +++ b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java @@ -98,6 +98,7 @@ public class PageIndicator extends ViewGroup { } // Refresh state. setIndex(mPosition >> 1); + requestLayout(); } /** diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java index 321f73295e2e2..eaf2123623204 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java +++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java @@ -8,6 +8,7 @@ import android.animation.PropertyValuesHolder; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; +import android.content.res.TypedArray; import android.graphics.Rect; import android.os.Bundle; import android.util.AttributeSet; @@ -47,7 +48,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { }; private final ArrayList mTiles = new ArrayList<>(); - private final ArrayList mPages = new ArrayList<>(); + private final ArrayList mPages = new ArrayList<>(); private PageIndicator mPageIndicator; private float mPageIndicatorPosition; @@ -71,6 +72,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { private int mMaxColumns = TileLayout.NO_MAX_COLUMNS; private boolean mShowLabels = true; + private final boolean mSideLabels; public PagedTileLayout(Context context, AttributeSet attrs) { super(context, attrs); @@ -81,13 +83,18 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { mLayoutOrientation = getResources().getConfiguration().orientation; mLayoutDirection = getLayoutDirection(); mClippingRect = new Rect(); + + TypedArray t = context.getTheme().obtainStyledAttributes( + attrs, R.styleable.PagedTileLayout, 0, 0); + mSideLabels = t.getBoolean(R.styleable.PagedTileLayout_sideLabels, false); + t.recycle(); } private int mLastMaxHeight = -1; @Override public void setShowLabels(boolean show) { mShowLabels = show; - for (TilePage p : mPages) { + for (TileLayout p : mPages) { p.setShowLabels(show); } mDistributeTiles = true; @@ -145,7 +152,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { } // This will dump to the ui log all the tiles that are visible in this page - private void logVisibleTiles(TilePage page) { + private void logVisibleTiles(TileLayout page) { for (int i = 0; i < page.mRecords.size(); i++) { QSTile t = page.mRecords.get(i).tile; mUiEventLogger.logWithInstanceId(QSEvent.QS_TILE_VISIBLE, 0, t.getMetricsSpec(), @@ -161,7 +168,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { } private void updateListening() { - for (TilePage tilePage : mPages) { + for (TileLayout tilePage : mPages) { tilePage.setListening(tilePage.getParent() != null && mListening); } } @@ -222,13 +229,14 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { @Override protected void onFinishInflate() { super.onFinishInflate(); - mPages.add(createTilePage()); + mPages.add(createTileLayout()); mAdapter.notifyDataSetChanged(); } - private TilePage createTilePage() { - TilePage page = (TilePage) LayoutInflater.from(getContext()) - .inflate(R.layout.qs_paged_page, this, false); + private TileLayout createTileLayout() { + TileLayout page = (TileLayout) LayoutInflater.from(getContext()) + .inflate(mSideLabels ? R.layout.qs_paged_page_side_labels + : R.layout.qs_paged_page, this, false); page.setMinRows(mMinRows); page.setMaxColumns(mMaxColumns); page.setShowLabels(mShowLabels); @@ -283,7 +291,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); int currentItem = getCurrentPageNumber(); for (int i = 0; i < mPages.size(); i++) { - TilePage page = mPages.get(i); + TileLayout page = mPages.get(i); page.setSelected(i == currentItem ? selected : false); if (page.isSelected()) { logVisibleTiles(page); @@ -325,7 +333,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { } while (mPages.size() < numPages) { if (DEBUG) Log.d(TAG, "Adding page"); - mPages.add(createTilePage()); + mPages.add(createTileLayout()); } while (mPages.size() > numPages) { if (DEBUG) Log.d(TAG, "Removing page"); @@ -422,7 +430,7 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { final int nRows = mPages.get(0).mRows; for (int i = 0; i < mPages.size(); i++) { - TilePage t = mPages.get(i); + TileLayout t = mPages.get(i); t.mRows = nRows; } } @@ -465,19 +473,19 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { public int getNumVisibleTiles() { if (mPages.size() == 0) return 0; - TilePage currentPage = mPages.get(getCurrentPageNumber()); + TileLayout currentPage = mPages.get(getCurrentPageNumber()); return currentPage.mRecords.size(); } public void startTileReveal(Set tileSpecs, final Runnable postAnimation) { if (tileSpecs.isEmpty() || mPages.size() < 2 || getScrollX() != 0 || !beginFakeDrag()) { // Do not start the reveal animation unless there are tiles to animate, multiple - // TilePages available and the user has not already started dragging. + // TileLayouts available and the user has not already started dragging. return; } final int lastPageNumber = mPages.size() - 1; - final TilePage lastPage = mPages.get(lastPageNumber); + final TileLayout lastPage = mPages.get(lastPageNumber); final ArrayList bounceAnims = new ArrayList<>(); for (TileRecord tr : lastPage.mRecords) { if (tileSpecs.contains(tr.tile.getTileSpec())) { @@ -557,12 +565,6 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout { return mRecords.size() >= maxTiles(); } - public int maxTiles() { - // Each page should be able to hold at least one tile. If there's not enough room to - // show even 1 or there are no tiles, it probably means we are in the middle of setting - // up. - return Math.max(mColumns * mRows, 1); - } } private final PagerAdapter mAdapter = new PagerAdapter() { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 65f174c508e89..5eba147ab2790 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -26,6 +26,7 @@ import android.content.res.Resources; import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.provider.Settings; import android.util.AttributeSet; import android.util.Pair; import android.view.Gravity; @@ -112,6 +113,7 @@ public class QSPanel extends LinearLayout implements Tunable { private int mMediaTotalBottomMargin; private int mFooterMarginStartHorizontal; private Consumer mMediaVisibilityChangedListener; + private final boolean mSideLabels; public QSPanel(Context context, AttributeSet attrs) { super(context, attrs); @@ -119,6 +121,8 @@ public class QSPanel extends LinearLayout implements Tunable { mMediaTotalBottomMargin = getResources().getDimensionPixelSize( R.dimen.quick_settings_bottom_margin_media); mContext = context; + mSideLabels = Settings.Secure.getInt( + mContext.getContentResolver(), "sysui_side_labels", 0) != 0; setOrientation(VERTICAL); @@ -174,8 +178,9 @@ public class QSPanel extends LinearLayout implements Tunable { /** */ public QSTileLayout createRegularTileLayout() { if (mRegularTileLayout == null) { - mRegularTileLayout = (QSTileLayout) LayoutInflater.from(mContext).inflate( - R.layout.qs_paged_tile_layout, this, false); + mRegularTileLayout = (QSTileLayout) LayoutInflater.from(mContext) + .inflate(mSideLabels ? R.layout.qs_paged_tile_layout_side_labels + : R.layout.qs_paged_tile_layout, this, false); } return mRegularTileLayout; } @@ -748,7 +753,13 @@ public class QSPanel extends LinearLayout implements Tunable { if (needsDynamicRowsAndColumns()) { newLayout.setMinRows(horizontal ? 2 : 1); // Let's use 3 columns to match the current layout - newLayout.setMaxColumns(horizontal ? 3 : TileLayout.NO_MAX_COLUMNS); + int columns; + if (mSideLabels) { + columns = horizontal ? 1 : 2; + } else { + columns = horizontal ? 3 : TileLayout.NO_MAX_COLUMNS; + } + newLayout.setMaxColumns(columns); } updateMargins(mediaHostView); } @@ -763,6 +774,10 @@ public class QSPanel extends LinearLayout implements Tunable { updatePadding(); } + boolean useSideLabels() { + return mSideLabels; + } + private class H extends Handler { private static final int SHOW_DETAIL = 1; private static final int SET_TILE_VISIBILITY = 2; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java index cca0e1b0c0f0d..e2d7d201a5de5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java @@ -90,14 +90,26 @@ public class QuickQSPanelController extends QSPanelControllerBase @Override public void setTiles() { - List tiles = new ArrayList(); + List tiles = new ArrayList<>(); for (QSTile tile : mHost.getTiles()) { tiles.add(tile); if (tiles.size() == mView.getNumQuickTiles()) { break; } } - super.setTiles(tiles, true); + if (mView.useSideLabels()) { + List newTiles = new ArrayList<>(); + for (int i = 0; i < tiles.size(); i += 2) { + newTiles.add(tiles.get(i)); + } + for (int i = 1; i < tiles.size(); i += 2) { + newTiles.add(tiles.get(i)); + } + super.setTiles(newTiles, true); + + } else { + super.setTiles(tiles, true); + } } /** */ diff --git a/packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt new file mode 100644 index 0000000000000..74a7ac1cb6ddd --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 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 + +import android.content.Context +import android.util.AttributeSet +import com.android.systemui.R + +open class SideLabelTileLayout(context: Context, attrs: AttributeSet) : TileLayout(context, attrs) { + + override fun updateResources(): Boolean { + return super.updateResources().also { + mResourceColumns = 2 + mMaxAllowedRows = 4 + mCellMarginHorizontal = (mCellMarginHorizontal * 1.2).toInt() + mCellMarginVertical = mCellMarginHorizontal + mMaxCellHeight = context.resources.getDimensionPixelSize(R.dimen.qs_quick_tile_size) + } + } + + override fun setShowLabels(show: Boolean) { } + + override fun isFull(): Boolean { + return mRecords.size >= maxTiles() + } +} \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java index e38c931287b12..911261a011438 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java +++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java @@ -42,7 +42,7 @@ public class TileLayout extends ViewGroup implements QSTileLayout { private final boolean mLessRows; private int mMinRows = 1; private int mMaxColumns = NO_MAX_COLUMNS; - private int mResourceColumns; + protected int mResourceColumns; public TileLayout(Context context) { this(context, null); @@ -216,7 +216,7 @@ public class TileLayout extends ViewGroup implements QSTileLayout { return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY); } - private int getCellHeight() { + protected int getCellHeight() { return mShowLabels ? mMaxCellHeight : mMaxCellHeight / 2; } @@ -260,4 +260,18 @@ public class TileLayout extends ViewGroup implements QSTileLayout { public int getNumVisibleTiles() { return mRecords.size(); } + + public boolean isFull() { + return false; + } + + /** + * @return The maximum number of tiles this layout can hold + */ + public int maxTiles() { + // Each layout should be able to hold at least one tile. If there's not enough room to + // show even 1 or there are no tiles, it probably means we are in the middle of setting + // up. + return Math.max(mColumns * mRows, 1); + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java index 24c0fd76d8276..5b1dbe0c5ae2b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java @@ -48,6 +48,7 @@ import com.android.systemui.qs.tiles.UserTile; import com.android.systemui.qs.tiles.WifiTile; import com.android.systemui.qs.tiles.WorkModeTile; import com.android.systemui.util.leak.GarbageMonitor; +import com.android.systemui.util.settings.SecureSettings; import javax.inject.Inject; import javax.inject.Provider; @@ -84,9 +85,12 @@ public class QSFactoryImpl implements QSFactory { private final Lazy mQsHostLazy; private final Provider mCustomTileBuilderProvider; + private final boolean mSideLabels; + @Inject public QSFactoryImpl( Lazy qsHostLazy, + SecureSettings settings, Provider customTileBuilderProvider, Provider wifiTileProvider, Provider bluetoothTileProvider, @@ -112,6 +116,8 @@ public class QSFactoryImpl implements QSFactory { mQsHostLazy = qsHostLazy; mCustomTileBuilderProvider = customTileBuilderProvider; + mSideLabels = settings.getInt("sysui_side_labels", 0) != 0; + mWifiTileProvider = wifiTileProvider; mBluetoothTileProvider = bluetoothTileProvider; mCellularTileProvider = cellularTileProvider; @@ -212,6 +218,8 @@ public class QSFactoryImpl implements QSFactory { QSIconView icon = tile.createTileView(context); if (collapsedView) { return new QSTileBaseView(context, icon, collapsedView); + } else if (mSideLabels) { + return new QSTileViewHorizontal(context, icon); } else { return new com.android.systemui.qs.tileimpl.QSTileView(context, icon); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java index 655e4e2684e43..38e2ba4df79a7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java @@ -61,15 +61,15 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView { private final FrameLayout mIconFrame; protected QSIconView mIcon; protected RippleDrawable mRipple; - private Drawable mTileBackground; + protected Drawable mTileBackground; private String mAccessibilityClass; private boolean mTileState; private boolean mCollapsedView; - private boolean mShowRippleEffect = true; + protected boolean mShowRippleEffect = true; private float mStrokeWidthActive; private float mStrokeWidthInactive; - private final ImageView mBg; + protected final ImageView mBg; private final int mColorActive; private final int mColorInactive; private final int mColorDisabled; @@ -162,7 +162,7 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView { } } - private void updateRippleSize() { + protected void updateRippleSize() { // center the touch feedback on the center of the icon, and dial it down a bit final int cx = mIconFrame.getMeasuredWidth() / 2 + mIconFrame.getLeft(); final int cy = mIconFrame.getMeasuredHeight() / 2 + mIconFrame.getTop(); @@ -311,7 +311,7 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView { return mLocInScreen[1] >= -getHeight(); } - private int getCircleColor(int state) { + protected int getCircleColor(int state) { switch (state) { case Tile.STATE_ACTIVE: return mColorActive; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java index 650206672c1e3..2dbd2cfe9c109 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java @@ -37,7 +37,6 @@ import java.util.Objects; /** View that represents a standard quick settings tile. **/ public class QSTileView extends QSTileBaseView { private static final int MAX_LABEL_LINES = 2; - private static final boolean DUAL_TARGET_ALLOWED = false; private View mDivider; protected TextView mLabel; protected TextView mSecondLine; @@ -46,8 +45,10 @@ public class QSTileView extends QSTileBaseView { protected ViewGroup mLabelContainer; private View mExpandIndicator; private View mExpandSpace; - private ColorStateList mColorLabelDefault; + protected ColorStateList mColorLabelActive; + protected ColorStateList mColorLabelInactive; private ColorStateList mColorLabelUnavailable; + protected boolean mDualTargetAllowed = false; public QSTileView(Context context, QSIconView icon) { this(context, icon, false); @@ -64,7 +65,8 @@ public class QSTileView extends QSTileBaseView { createLabel(); setOrientation(VERTICAL); setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP); - mColorLabelDefault = Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary); + mColorLabelActive = Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary); + mColorLabelInactive = mColorLabelActive; // The text color for unavailable tiles is textColorSecondary, same as secondaryLabel for // contrast purposes mColorLabelUnavailable = Utils.getColorAttr(getContext(), @@ -118,8 +120,15 @@ public class QSTileView extends QSTileBaseView { protected void handleStateChanged(QSTile.State state) { super.handleStateChanged(state); if (!Objects.equals(mLabel.getText(), state.label) || mState != state.state) { - mLabel.setTextColor(state.state == Tile.STATE_UNAVAILABLE ? mColorLabelUnavailable - : mColorLabelDefault); + ColorStateList labelColor; + if (state.state == Tile.STATE_ACTIVE) { + labelColor = mColorLabelActive; + } else if (state.state == Tile.STATE_INACTIVE) { + labelColor = mColorLabelInactive; + } else { + labelColor = mColorLabelUnavailable; + } + mLabel.setTextColor(labelColor); mState = state.state; mLabel.setText(state.label); } @@ -128,9 +137,8 @@ public class QSTileView extends QSTileBaseView { mSecondLine.setVisibility(TextUtils.isEmpty(state.secondaryLabel) ? View.GONE : View.VISIBLE); } - boolean dualTarget = DUAL_TARGET_ALLOWED && state.dualTarget; - mExpandIndicator.setVisibility(dualTarget ? View.VISIBLE : View.GONE); - mExpandSpace.setVisibility(dualTarget ? View.VISIBLE : View.GONE); + boolean dualTarget = mDualTargetAllowed && state.dualTarget; + handleExpand(dualTarget); mLabelContainer.setContentDescription(dualTarget ? state.dualLabelContentDescription : null); if (dualTarget != mLabelContainer.isClickable()) { @@ -142,6 +150,11 @@ public class QSTileView extends QSTileBaseView { mPadLock.setVisibility(state.disabledByPolicy ? View.VISIBLE : View.GONE); } + protected void handleExpand(boolean dualTarget) { + mExpandIndicator.setVisibility(dualTarget ? View.VISIBLE : View.GONE); + mExpandSpace.setVisibility(dualTarget ? View.VISIBLE : View.GONE); + } + @Override public void init(OnClickListener click, OnClickListener secondaryClick, OnLongClickListener longClick) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewHorizontal.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewHorizontal.kt new file mode 100644 index 0000000000000..2ef78c2492462 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewHorizontal.kt @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2020 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.tileimpl + +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.Color +import android.graphics.drawable.Drawable +import android.graphics.drawable.PaintDrawable +import android.graphics.drawable.RippleDrawable +import android.service.quicksettings.Tile.STATE_ACTIVE +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.widget.LinearLayout +import com.android.systemui.R +import com.android.systemui.plugins.qs.QSIconView +import com.android.systemui.plugins.qs.QSTile +import com.android.systemui.qs.tileimpl.QSTileImpl.getColorForState + +class QSTileViewHorizontal( + context: Context, + icon: QSIconView +) : QSTileView(context, icon, false) { + + private var paintDrawable: PaintDrawable? = null + private var divider: View? = null + + init { + orientation = HORIZONTAL + mDualTargetAllowed = true + mBg.setImageDrawable(null) + createDivider() + mColorLabelActive = ColorStateList.valueOf(getColorForState(getContext(), STATE_ACTIVE)) + } + + override fun createLabel() { + super.createLabel() + findViewById(R.id.label_group)?.gravity = Gravity.START + mLabel.gravity = Gravity.START + mSecondLine.gravity = Gravity.START + val padding = context.resources.getDimensionPixelSize(R.dimen.qs_tile_side_label_padding) + mLabelContainer.setPadding(padding, padding, padding, padding) + (mLabelContainer.layoutParams as LayoutParams).gravity = Gravity.CENTER_VERTICAL + } + + fun createDivider() { + divider = LayoutInflater.from(context).inflate(R.layout.qs_tile_label_divider, this, false) + val position = indexOfChild(mLabelContainer) + addView(divider, position) + } + + override fun init( + click: OnClickListener?, + secondaryClick: OnClickListener?, + longClick: OnLongClickListener? + ) { + super.init(click, secondaryClick, longClick) + mLabelContainer.setOnClickListener { + longClick?.onLongClick(it) + } + mLabelContainer.isClickable = false + } + + override fun updateRippleSize() { + } + + override fun newTileBackground(): Drawable? { + val d = super.newTileBackground() + if (paintDrawable == null) { + paintDrawable = PaintDrawable(Color.WHITE).apply { + setCornerRadius(30f) + } + } + if (d is RippleDrawable) { + d.addLayer(paintDrawable) + return d + } else { + return paintDrawable + } + } + + override fun setClickable(clickable: Boolean) { + super.setClickable(clickable) + background = mTileBackground + if (clickable && mShowRippleEffect) { + mRipple?.setHotspotBounds(left, top, right, bottom) + } else { + mRipple?.setHotspotBounds(0, 0, 0, 0) + } + } + + override fun handleStateChanged(state: QSTile.State) { + super.handleStateChanged(state) + paintDrawable?.setTint(getCircleColor(state.state)) + mSecondLine.setTextColor(mLabel.textColors) + mLabelContainer.background = null + divider?.backgroundTintList = mLabel.textColors + } + + override fun handleExpand(dualTarget: Boolean) {} +} \ No newline at end of file