diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java index d1383eb79d850..55dea3d3bcb9d 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java @@ -163,7 +163,7 @@ public interface QSTile { public SlashState slash; public boolean handlesLongClick = true; public boolean showRippleEffect = true; - public Drawable sideViewDrawable; + public Drawable sideViewCustomDrawable; public boolean copyTo(State other) { if (other == null) throw new IllegalArgumentException(); @@ -185,7 +185,7 @@ public interface QSTile { || !Objects.equals(other.slash, slash) || !Objects.equals(other.handlesLongClick, handlesLongClick) || !Objects.equals(other.showRippleEffect, showRippleEffect) - || !Objects.equals(other.sideViewDrawable, sideViewDrawable); + || !Objects.equals(other.sideViewCustomDrawable, sideViewCustomDrawable); other.icon = icon; other.iconSupplier = iconSupplier; other.label = label; @@ -201,7 +201,7 @@ public interface QSTile { other.slash = slash != null ? slash.copy() : null; other.handlesLongClick = handlesLongClick; other.showRippleEffect = showRippleEffect; - other.sideViewDrawable = sideViewDrawable; + other.sideViewCustomDrawable = sideViewCustomDrawable; return changed; } @@ -227,7 +227,7 @@ public interface QSTile { sb.append(",isTransient=").append(isTransient); sb.append(",state=").append(state); sb.append(",slash=\"").append(slash).append("\""); - sb.append(",sideViewDrawable").append(sideViewDrawable); + sb.append(",sideViewCustomDrawable=").append(sideViewCustomDrawable); return sb.append(']'); } @@ -242,12 +242,16 @@ public interface QSTile { public static class BooleanState extends State { public static final int VERSION = 1; public boolean value; + public boolean forceExpandIcon; @Override public boolean copyTo(State other) { final BooleanState o = (BooleanState) other; - final boolean changed = super.copyTo(other) || o.value != value; + final boolean changed = super.copyTo(other) + || o.value != value + || o.forceExpandIcon != forceExpandIcon; o.value = value; + o.forceExpandIcon = forceExpandIcon; return changed; } @@ -255,6 +259,7 @@ public interface QSTile { protected StringBuilder toStringBuilder() { final StringBuilder rt = super.toStringBuilder(); rt.insert(rt.length() - 1, ",value=" + value); + rt.insert(rt.length() - 1, ",forceExpandIcon=" + forceExpandIcon); return rt; } diff --git a/packages/SystemUI/res/layout/qs_tile_side_icon.xml b/packages/SystemUI/res/layout/qs_tile_side_icon.xml new file mode 100644 index 0000000000000..9f9af9d21db11 --- /dev/null +++ b/packages/SystemUI/res/layout/qs_tile_side_icon.xml @@ -0,0 +1,41 @@ + + + + + + + \ No newline at end of file diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 78cd22dae2a07..4c98e375a6967 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -557,6 +557,7 @@ 60dp 12dp 16dp + 4dp 16dp 18dp 16dp diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.kt b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.kt index 287d815c2e4ab..a316e6aa5f1b3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.kt @@ -36,10 +36,17 @@ class CustomizeTileView( secondaryLabel.visibility = getVisibilityState(secondaryLabel.text) } + var showSideView = true + set(value) { + field = value + if (!showSideView) sideView.visibility = GONE + } + override fun handleStateChanged(state: QSTile.State) { super.handleStateChanged(state) showRippleEffect = false secondaryLabel.visibility = getVisibilityState(state.secondaryLabel) + if (!showSideView) sideView.visibility = GONE } private fun getVisibilityState(text: CharSequence?): Int { diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java index 505f5866c105e..fe0e56c4869ef 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java @@ -366,6 +366,8 @@ public class TileAdapter extends RecyclerView.Adapter implements TileSta // The holder has a tileView, therefore this call is not null holder.getTileAsCustomizeView().changeState(info.state); holder.getTileAsCustomizeView().setShowAppLabel(position > mEditIndex && !info.isSystem); + // Don't show the side view for third party tiles, as we don't have the actual state. + holder.getTileAsCustomizeView().setShowSideView(position < mEditIndex || info.isSystem); holder.mTileView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); holder.mTileView.setClickable(true); holder.mTileView.setOnClickListener(null); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt index 954321e50587c..3ad95d27e9401 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt @@ -72,10 +72,12 @@ open class QSTileViewImpl @JvmOverloads constructor( private val colorLabelUnavailable = Utils.getColorAttrDefaultColor(context, android.R.attr.textColorTertiary) - private val sideView = ImageView(context) private lateinit var label: TextView protected lateinit var secondaryLabel: TextView private lateinit var labelContainer: IgnorableChildLinearLayout + protected lateinit var sideView: ViewGroup + private lateinit var customDrawableView: ImageView + private lateinit var chevronView: ImageView protected var showRippleEffect = true @@ -112,22 +114,15 @@ open class QSTileViewImpl @JvmOverloads constructor( addView(_icon, LayoutParams(iconSize, iconSize)) createAndAddLabels() - - sideView.visibility = GONE - val sideViewLayoutParams = LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ).apply { - gravity = Gravity.CENTER_VERTICAL - marginStart = resources.getDimensionPixelSize(R.dimen.qs_label_container_margin) - } - addView(sideView, sideViewLayoutParams) - sideView.adjustViewBounds = true - sideView.scaleType = ImageView.ScaleType.FIT_CENTER + createAndAddSideView() } override fun onConfigurationChanged(newConfig: Configuration?) { super.onConfigurationChanged(newConfig) + updateResources() + } + + fun updateResources() { FontSizeUtils.updateFontSize(label, R.dimen.qs_tile_text_size) FontSizeUtils.updateFontSize(secondaryLabel, R.dimen.qs_tile_text_size) @@ -141,13 +136,24 @@ open class QSTileViewImpl @JvmOverloads constructor( val startPadding = resources.getDimensionPixelSize(R.dimen.qs_tile_start_padding) setPaddingRelative(startPadding, padding, padding, padding) - val labelMargin = context.resources.getDimensionPixelSize(R.dimen.qs_label_container_margin) + val labelMargin = resources.getDimensionPixelSize(R.dimen.qs_label_container_margin) (labelContainer.layoutParams as MarginLayoutParams).apply { marginStart = labelMargin } + (sideView.layoutParams as MarginLayoutParams).apply { marginStart = labelMargin } + (chevronView.layoutParams as MarginLayoutParams).apply { + height = iconSize + width = iconSize + } + + val endMargin = resources.getDimensionPixelSize(R.dimen.qs_drawable_end_margin) + (customDrawableView.layoutParams as MarginLayoutParams).apply { + height = iconSize + marginEnd = endMargin + } } private fun createAndAddLabels() { @@ -164,6 +170,14 @@ open class QSTileViewImpl @JvmOverloads constructor( addView(labelContainer) } + private fun createAndAddSideView() { + sideView = LayoutInflater.from(context) + .inflate(R.layout.qs_tile_side_icon, this, false) as ViewGroup + customDrawableView = sideView.requireViewById(R.id.customDrawable) + chevronView = sideView.requireViewById(R.id.chevron) + addView(sideView) + } + fun createTileBackground(): Drawable { ripple = mContext.getDrawable(R.drawable.qs_tile_background) as RippleDrawable colorBackgroundDrawable = ripple.findDrawableByLayerId(R.id.background) @@ -376,20 +390,28 @@ open class QSTileViewImpl @JvmOverloads constructor( secondaryLabel.setTextColor(getSecondaryLabelColor(state.state)) } - label.isEnabled = !state.disabledByPolicy - + // Right side icon loadSideViewDrawableIfNecessary(state) + chevronView.imageTintList = ColorStateList.valueOf(getSecondaryLabelColor(state.state)) + + label.isEnabled = !state.disabledByPolicy lastState = state.state } private fun loadSideViewDrawableIfNecessary(state: QSTile.State) { - if (state.sideViewDrawable != null) { - sideView.setImageDrawable(state.sideViewDrawable) - sideView.visibility = View.VISIBLE + if (state.sideViewCustomDrawable != null) { + customDrawableView.setImageDrawable(state.sideViewCustomDrawable) + customDrawableView.visibility = VISIBLE + chevronView.visibility = GONE + } else if (state !is BooleanState || state.forceExpandIcon) { + customDrawableView.setImageDrawable(null) + customDrawableView.visibility = GONE + chevronView.visibility = VISIBLE } else { - sideView.setImageDrawable(null) - sideView.visibility = GONE + customDrawableView.setImageDrawable(null) + customDrawableView.visibility = GONE + chevronView.visibility = GONE } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java index 5dcbf49a9b727..577c0d8455ebe 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java @@ -99,7 +99,9 @@ public class InternetTile extends QSTileImpl { @Override public SignalState newTileState() { - return new SignalState(); + SignalState s = new SignalState(); + s.forceExpandIcon = true; + return s; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java index be40423df3fab..2efd5065c57fe 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java @@ -175,7 +175,7 @@ public class QuickAccessWalletTile extends QSTileImpl { } else { state.state = Tile.STATE_UNAVAILABLE; } - state.sideViewDrawable = isDeviceLocked ? null : mCardViewDrawable; + state.sideViewCustomDrawable = isDeviceLocked ? null : mCardViewDrawable; } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt index 42c89f9eb1834..e5e2e53b0a090 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt @@ -17,9 +17,11 @@ package com.android.systemui.qs.tileimpl import android.content.Context +import android.graphics.drawable.Drawable import android.service.quicksettings.Tile import android.testing.AndroidTestingRunner import android.text.TextUtils +import android.view.View import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase @@ -38,14 +40,20 @@ class QSTileViewImplTest : SysuiTestCase() { @Mock private lateinit var iconView: QSIconView + @Mock + private lateinit var customDrawable: Drawable private lateinit var tileView: FakeTileView + private lateinit var customDrawableView: View + private lateinit var chevronView: View @Before fun setUp() { MockitoAnnotations.initMocks(this) tileView = FakeTileView(context, iconView, false) + customDrawableView = tileView.requireViewById(R.id.customDrawable) + chevronView = tileView.requireViewById(R.id.chevron) } @Test @@ -145,6 +153,71 @@ class QSTileViewImplTest : SysuiTestCase() { ) } + @Test + fun testShowCustomDrawableViewBooleanState() { + val state = QSTile.BooleanState() + state.sideViewCustomDrawable = customDrawable + + tileView.changeState(state) + + assertThat(customDrawableView.visibility).isEqualTo(View.VISIBLE) + assertThat(chevronView.visibility).isEqualTo(View.GONE) + } + + @Test + fun testShowCustomDrawableViewNonBooleanState() { + val state = QSTile.State() + state.sideViewCustomDrawable = customDrawable + + tileView.changeState(state) + + assertThat(customDrawableView.visibility).isEqualTo(View.VISIBLE) + assertThat(chevronView.visibility).isEqualTo(View.GONE) + } + + @Test + fun testShowCustomDrawableViewBooleanStateForceChevron() { + val state = QSTile.BooleanState() + state.sideViewCustomDrawable = customDrawable + state.forceExpandIcon = true + + tileView.changeState(state) + + assertThat(customDrawableView.visibility).isEqualTo(View.VISIBLE) + assertThat(chevronView.visibility).isEqualTo(View.GONE) + } + + @Test + fun testShowChevronNonBooleanState() { + val state = QSTile.State() + + tileView.changeState(state) + + assertThat(customDrawableView.visibility).isEqualTo(View.GONE) + assertThat(chevronView.visibility).isEqualTo(View.VISIBLE) + } + + @Test + fun testShowChevronBooleanStateForcheShow() { + val state = QSTile.BooleanState() + state.forceExpandIcon = true + + tileView.changeState(state) + + assertThat(customDrawableView.visibility).isEqualTo(View.GONE) + assertThat(chevronView.visibility).isEqualTo(View.VISIBLE) + } + + @Test + fun testNoImageShown() { + val state = QSTile.BooleanState() + + tileView.changeState(state) + + assertThat(customDrawableView.visibility).isEqualTo(View.GONE) + assertThat(chevronView.visibility).isEqualTo(View.GONE) + } + class FakeTileView( context: Context, icon: QSIconView, diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java index 5cdad05e43f52..09060f5254125 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java @@ -271,7 +271,7 @@ public class QuickAccessWalletTileTest extends SysuiTestCase { mContext.getString(R.string.wallet_secondary_label_device_locked), state.secondaryLabel); assertNotNull(state.stateDescription); - assertNull(state.sideViewDrawable); + assertNull(state.sideViewCustomDrawable); } @Test @@ -287,7 +287,7 @@ public class QuickAccessWalletTileTest extends SysuiTestCase { mContext.getString(R.string.wallet_secondary_label_active), state.secondaryLabel); assertNotNull(state.stateDescription); - assertNotNull(state.sideViewDrawable); + assertNotNull(state.sideViewCustomDrawable); } @@ -303,7 +303,7 @@ public class QuickAccessWalletTileTest extends SysuiTestCase { mContext.getString(R.string.wallet_secondary_label_no_card), state.secondaryLabel); assertNotNull(state.stateDescription); - assertNull(state.sideViewDrawable); + assertNull(state.sideViewCustomDrawable); } @Test @@ -315,7 +315,7 @@ public class QuickAccessWalletTileTest extends SysuiTestCase { assertEquals(Tile.STATE_UNAVAILABLE, state.state); assertNull(state.stateDescription); - assertNull(state.sideViewDrawable); + assertNull(state.sideViewCustomDrawable); } @Test @@ -342,7 +342,7 @@ public class QuickAccessWalletTileTest extends SysuiTestCase { when(mKeyguardStateController.isUnlocked()).thenReturn(true); setUpWalletCard(/* hasCard= */ true); - assertNotNull(mTile.getState().sideViewDrawable); + assertNotNull(mTile.getState().sideViewCustomDrawable); } @Test @@ -362,7 +362,7 @@ public class QuickAccessWalletTileTest extends SysuiTestCase { mCallbackCaptor.getValue().onWalletCardsRetrieved(responseWithCards); mTestableLooper.processAllMessages(); - assertNotNull(mTile.getState().sideViewDrawable); + assertNotNull(mTile.getState().sideViewCustomDrawable); mTile.handleSetListening(true); @@ -373,14 +373,14 @@ public class QuickAccessWalletTileTest extends SysuiTestCase { mCallbackCaptor.getValue().onWalletCardsRetrieved(responseWithoutCards); mTestableLooper.processAllMessages(); - assertNull(mTile.getState().sideViewDrawable); + assertNull(mTile.getState().sideViewCustomDrawable); } @Test public void testQueryCards_noCards_notUpdateSideViewDrawable() { setUpWalletCard(/* hasCard= */ false); - assertNull(mTile.getState().sideViewDrawable); + assertNull(mTile.getState().sideViewCustomDrawable); } @Test @@ -395,7 +395,7 @@ public class QuickAccessWalletTileTest extends SysuiTestCase { mCallbackCaptor.getValue().onWalletCardRetrievalError(error); mTestableLooper.processAllMessages(); - assertNull(mTile.getState().sideViewDrawable); + assertNull(mTile.getState().sideViewCustomDrawable); } @Test