Apply insets (nav bar)
This is applied to QS, as well as passed down to the RecyclerView so it
can show content behind the nav bar.
Test: atest QSScenAdapterImplTest
Fixes: 316571756
Flag: ACONFIG com.android.systemui.scene_container DEVELOPMENT
Change-Id: I3761a32675dec05b002231df73a199b4f8893c36
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
index 1cbc992..46554a4 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
@@ -29,10 +29,13 @@
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.rememberScrollState
@@ -125,6 +128,9 @@
remember(lifecycleOwner, viewModel) {
viewModel.getFooterActionsViewModel(lifecycleOwner)
}
+
+ // ############## SCROLLING ################
+
val scrollState = rememberScrollState()
// When animating into the scene, we don't want it to be able to scroll, as it could mess
// up with the expansion animation.
@@ -142,6 +148,18 @@
}
}
+ // ############# NAV BAR paddings ###############
+
+ val navBarBottomHeight =
+ WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()
+ val density = LocalDensity.current
+
+ LaunchedEffect(navBarBottomHeight, density) {
+ with(density) {
+ viewModel.qsSceneAdapter.applyBottomNavBarPadding(navBarBottomHeight.roundToPx())
+ }
+ }
+
// This is the background for the whole scene, as the elements don't necessarily provide
// a background that extends to the edges.
Spacer(
@@ -154,8 +172,13 @@
horizontalAlignment = Alignment.CenterHorizontally,
modifier =
Modifier.fillMaxSize()
- // bottom should be tied to insets
- .padding(bottom = 16.dp)
+ .then(
+ if (isCustomizing) {
+ Modifier.padding(top = 48.dp)
+ } else {
+ Modifier.padding(bottom = navBarBottomHeight)
+ }
+ )
) {
Box(modifier = Modifier.fillMaxSize().weight(1f)) {
val shadeHeaderAndQuickSettingsModifier =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt
index cae20d0..f8573cc2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt
@@ -414,4 +414,56 @@
verify(qsImpl!!).onConfigurationChanged(configuration)
verify(qsImpl!!.view).dispatchConfigurationChanged(configuration)
}
+
+ @Test
+ fun dispatchNavBarSize_beforeInflation() =
+ testScope.runTest {
+ runCurrent()
+ val navBarHeight = 171
+
+ val qsImpl by collectLastValue(underTest.qsImpl)
+
+ underTest.applyBottomNavBarPadding(navBarHeight)
+ underTest.inflate(context)
+ runCurrent()
+
+ verify(qsImpl!!).applyBottomNavBarToCustomizerPadding(navBarHeight)
+ }
+
+ @Test
+ fun dispatchNavBarSize_afterInflation() =
+ testScope.runTest {
+ runCurrent()
+ val navBarHeight = 171
+
+ val qsImpl by collectLastValue(underTest.qsImpl)
+
+ underTest.inflate(context)
+ runCurrent()
+
+ underTest.applyBottomNavBarPadding(navBarHeight)
+ runCurrent()
+
+ verify(qsImpl!!).applyBottomNavBarToCustomizerPadding(navBarHeight)
+ }
+
+ @Test
+ fun dispatchNavBarSize_reinflation() =
+ testScope.runTest {
+ runCurrent()
+ val navBarHeight = 171
+
+ val qsImpl by collectLastValue(underTest.qsImpl)
+
+ underTest.inflate(context)
+ runCurrent()
+
+ underTest.applyBottomNavBarPadding(navBarHeight)
+ runCurrent()
+
+ underTest.inflate(context)
+ runCurrent()
+
+ verify(qsImpl!!).applyBottomNavBarToCustomizerPadding(navBarHeight)
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java
index 4d55714..8ff0e36 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java
@@ -992,6 +992,15 @@
return mContainer.getQsHeight();
}
+ /**
+ * Pass the size of the navbar when it's at the bottom of the device so it can be used as
+ * padding
+ * @param padding size of the bottom nav bar in px
+ */
+ public void applyBottomNavBarToCustomizerPadding(int padding) {
+ mQSCustomizerController.applyBottomNavBarSizeToRecyclerViewPadding(padding);
+ }
+
@NeverCompile
@Override
public void dump(PrintWriter pw, String[] args) {
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 07705f3..f8d4080 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -65,6 +65,8 @@
private boolean mOpening;
private boolean mIsShowingNavBackdrop;
+ private boolean mSceneContainerEnabled;
+
public QSCustomizer(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -88,6 +90,28 @@
updateTransparentViewHeight();
}
+ void applyBottomNavBarToPadding(int padding) {
+ mRecyclerView.setPadding(
+ /* left= */ mRecyclerView.getPaddingLeft(),
+ /* top= */ mRecyclerView.getPaddingTop(),
+ /* right= */ mRecyclerView.getPaddingRight(),
+ /* bottom= */ padding
+ );
+ }
+
+ void setSceneContainerEnabled(boolean enabled) {
+ if (enabled != mSceneContainerEnabled) {
+ mSceneContainerEnabled = enabled;
+ updateTransparentViewHeight();
+ if (mSceneContainerEnabled) {
+ findViewById(R.id.nav_bar_background).setVisibility(View.GONE);
+ } else {
+ findViewById(R.id.nav_bar_background)
+ .setVisibility(mIsShowingNavBackdrop ? View.VISIBLE : View.GONE);
+ }
+ }
+ }
+
void updateResources() {
updateTransparentViewHeight();
mRecyclerView.getAdapter().notifyItemChanged(0);
@@ -98,7 +122,8 @@
mIsShowingNavBackdrop = newConfig.smallestScreenWidthDp >= 600
|| newConfig.orientation != Configuration.ORIENTATION_LANDSCAPE;
if (navBackdrop != null) {
- navBackdrop.setVisibility(mIsShowingNavBackdrop ? View.VISIBLE : View.GONE);
+ navBackdrop.setVisibility(
+ mIsShowingNavBackdrop && !mSceneContainerEnabled ? View.VISIBLE : View.GONE);
}
updateNavColors(lightBarController);
}
@@ -275,7 +300,7 @@
private void updateTransparentViewHeight() {
LayoutParams lp = (LayoutParams) mTransparentView.getLayoutParams();
- lp.height = QSUtils.getQsHeaderSystemIconsAreaHeight(mContext);
+ lp.height = mSceneContainerEnabled ? 0 : QSUtils.getQsHeaderSystemIconsAreaHeight(mContext);
mTransparentView.setLayoutParams(lp);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
index c28371c..34b1b2d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
@@ -42,6 +42,7 @@
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.res.R;
+import com.android.systemui.scene.shared.flag.SceneContainerFlags;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -106,7 +107,8 @@
protected QSCustomizerController(QSCustomizer view, TileQueryHelper tileQueryHelper,
QSHost qsHost, TileAdapter tileAdapter, ScreenLifecycle screenLifecycle,
KeyguardStateController keyguardStateController, LightBarController lightBarController,
- ConfigurationController configurationController, UiEventLogger uiEventLogger) {
+ ConfigurationController configurationController, UiEventLogger uiEventLogger,
+ SceneContainerFlags sceneContainerFlags) {
super(view);
mTileQueryHelper = tileQueryHelper;
mQsHost = qsHost;
@@ -116,10 +118,14 @@
mLightBarController = lightBarController;
mConfigurationController = configurationController;
mUiEventLogger = uiEventLogger;
+ view.setSceneContainerEnabled(sceneContainerFlags.isEnabled());
mToolbar = mView.findViewById(com.android.internal.R.id.action_bar);
}
+ public void applyBottomNavBarSizeToRecyclerViewPadding(int padding) {
+ mView.applyBottomNavBarToPadding(padding);
+ }
@Override
protected void onViewAttached() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt
index 3d12eed..6e4f72d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt
@@ -39,10 +39,13 @@
import kotlin.coroutines.suspendCoroutine
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
@@ -69,6 +72,9 @@
/** Set the current state for QS. [state]. */
fun setState(state: State)
+ /** Propagates the bottom nav bar size to [QSImpl] to be used as necessary. */
+ suspend fun applyBottomNavBarPadding(padding: Int)
+
/** The current height of QQS in the current [qsView], or 0 if there's no view. */
val qqsHeight: Int
@@ -123,6 +129,11 @@
::AsyncLayoutInflater,
)
+ private val bottomNavBarSize =
+ MutableSharedFlow<Int>(
+ extraBufferCapacity = 1,
+ onBufferOverflow = BufferOverflow.DROP_OLDEST,
+ )
private val state = MutableStateFlow<QSSceneAdapter.State>(QSSceneAdapter.State.CLOSED)
private val _isCustomizing: MutableStateFlow<Boolean> = MutableStateFlow(false)
override val isCustomizing = _isCustomizing.asStateFlow()
@@ -168,6 +179,11 @@
}
}
}
+ launch {
+ combine(bottomNavBarSize, qsImpl.filterNotNull(), ::Pair).collect {
+ it.second.applyBottomNavBarToCustomizerPadding(it.first)
+ }
+ }
}
}
@@ -208,6 +224,10 @@
this.state.value = state
}
+ override suspend fun applyBottomNavBarPadding(padding: Int) {
+ bottomNavBarSize.emit(padding)
+ }
+
private fun QSImpl.applyState(state: QSSceneAdapter.State) {
setQsVisible(state.isVisible)
setExpanded(state.isVisible)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt
index 8e430db..b1581d1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/adapter/FakeQSSceneAdapter.kt
@@ -38,6 +38,9 @@
private val _state = MutableStateFlow<QSSceneAdapter.State?>(null)
val state = _state.filterNotNull()
+ private val _navBarPadding = MutableStateFlow<Int>(0)
+ val navBarPadding = _navBarPadding.asStateFlow()
+
override suspend fun inflate(context: Context) {
_view.value = inflateDelegate(context)
}
@@ -51,4 +54,8 @@
fun setCustomizing(value: Boolean) {
_customizing.value = value
}
+
+ override suspend fun applyBottomNavBarPadding(padding: Int) {
+ _navBarPadding.value = padding
+ }
}