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
This commit is contained in:
23
packages/SystemUI/res/layout/qs_paged_page_side_labels.xml
Normal file
23
packages/SystemUI/res/layout/qs_paged_page_side_labels.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<com.android.systemui.qs.SideLabelTileLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/tile_page"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false" />
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<com.android.systemui.qs.PagedTileLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:systemui="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/qs_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:clipChildren="true"
|
||||
android:paddingBottom="@dimen/qs_paged_tile_layout_padding_bottom"
|
||||
systemui:sideLabels="true" />
|
||||
@@ -34,7 +34,8 @@
|
||||
<Space
|
||||
android:id="@+id/expand_space"
|
||||
android:layout_width="22dp"
|
||||
android:layout_height="0dp" />
|
||||
android:layout_height="0dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tile_label"
|
||||
|
||||
27
packages/SystemUI/res/layout/qs_tile_label_divider.xml
Normal file
27
packages/SystemUI/res/layout/qs_tile_label_divider.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<View xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="1px"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginStart="0dp"
|
||||
android:layout_marginEnd="0dp"
|
||||
android:background="?android:attr/textColorSecondary"
|
||||
/>
|
||||
@@ -167,5 +167,9 @@
|
||||
<attr name="android:drawable" />
|
||||
<attr name="android:alpha" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="PagedTileLayout">
|
||||
<attr name="sideLabels" format="boolean"/>
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
|
||||
|
||||
@@ -519,6 +519,7 @@
|
||||
Scaled @dimen/qs_page_indicator-width by .4f.
|
||||
-->
|
||||
<dimen name="qs_page_indicator_dot_width">6.4dp</dimen>
|
||||
<dimen name="qs_tile_side_label_padding">6dp</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>
|
||||
|
||||
@@ -98,6 +98,7 @@ public class PageIndicator extends ViewGroup {
|
||||
}
|
||||
// Refresh state.
|
||||
setIndex(mPosition >> 1);
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<TileRecord> mTiles = new ArrayList<>();
|
||||
private final ArrayList<TilePage> mPages = new ArrayList<>();
|
||||
private final ArrayList<TileLayout> 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<String> 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<Animator> 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() {
|
||||
|
||||
@@ -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<Boolean> 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;
|
||||
|
||||
@@ -90,14 +90,26 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
|
||||
|
||||
@Override
|
||||
public void setTiles() {
|
||||
List<QSTile> tiles = new ArrayList();
|
||||
List<QSTile> 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<QSTile> 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);
|
||||
}
|
||||
}
|
||||
|
||||
/** */
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<QSHost> mQsHostLazy;
|
||||
private final Provider<CustomTile.Builder> mCustomTileBuilderProvider;
|
||||
|
||||
private final boolean mSideLabels;
|
||||
|
||||
@Inject
|
||||
public QSFactoryImpl(
|
||||
Lazy<QSHost> qsHostLazy,
|
||||
SecureSettings settings,
|
||||
Provider<CustomTile.Builder> customTileBuilderProvider,
|
||||
Provider<WifiTile> wifiTileProvider,
|
||||
Provider<BluetoothTile> 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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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<LinearLayout>(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) {}
|
||||
}
|
||||
Reference in New Issue
Block a user