Loading packages/SystemUI/res/layout/volume_dialog_horizontal.xml 0 → 100644 +103 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2025 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. --> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/volume_dialog" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top|right" android:alpha="0" android:clipChildren="false" android:minHeight="@dimen/volume_dialog_window_width"> <View android:id="@+id/volume_dialog_background" android:layout_width="0dp" android:layout_height="@dimen/volume_dialog_width" android:layout_marginStart="@dimen/volume_dialog_background_top_margin" android:layout_marginEnd="@dimen/volume_dialog_background_margin_negative" android:background="@drawable/volume_dialog_background" app:layout_constraintStart_toStartOf="@+id/volume_dialog_main_slider_container" app:layout_constraintEnd_toEndOf="@+id/volume_dialog_bottom_section_container" app:layout_constraintBottom_toBottomOf="@+id/volume_dialog_main_slider_container" app:layout_constraintTop_toTopOf="@+id/volume_dialog_main_slider_container" /> <FrameLayout android:id="@+id/volume_dialog_top_section_container" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginEnd="@dimen/volume_dialog_components_spacing" android:clipChildren="false" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@+id/volume_dialog_main_slider_container" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="@+id/volume_dialog_background" app:layout_constraintWidth_default="spread" app:layout_constraintHeight_default="spread"> <include layout="@layout/volume_dialog_top_section" /> </FrameLayout> <include android:id="@+id/volume_dialog_main_slider_container" layout="@layout/volume_dialog_slider" android:layout_width="0dp" android:layout_height="@dimen/volume_dialog_slider_width" android:layout_marginStart="@dimen/volume_dialog_slider_vertical_margin" android:layout_marginEnd="@dimen/volume_dialog_slider_vertical_margin" android:layout_marginTop="@dimen/volume_dialog_window_margin" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintWidth_max="@dimen/volume_dialog_slider_height" app:layout_constraintHorizontal_bias="1" /> <FrameLayout android:id="@+id/volume_dialog_bottom_section_container" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginStart="@dimen/volume_dialog_components_spacing" android:clipChildren="false" app:layout_constraintStart_toEndOf="@+id/volume_dialog_main_slider_container" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="@+id/volume_dialog_background" app:layout_constraintBottom_toBottomOf="@+id/volume_dialog_background" app:layout_constraintWidth_default="wrap" app:layout_constraintHeight_default="wrap" app:layout_constraintHorizontal_bias="0"> <include layout="@layout/volume_dialog_bottom_section" /> </FrameLayout> <LinearLayout android:id="@+id/volume_dialog_floating_sliders_container" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/volume_dialog_floating_sliders_vertical_padding_negative" android:layout_marginEnd="@dimen/volume_dialog_floating_sliders_vertical_padding_negative" android:clipChildren="false" android:clipToOutline="false" android:clipToPadding="false" android:divider="@drawable/volume_dialog_floating_sliders_spacer" android:gravity="end" android:orientation="vertical" android:showDividers="middle|beginning|end" app:layout_constraintStart_toStartOf="@+id/volume_dialog_main_slider_container" app:layout_constraintEnd_toEndOf="@+id/volume_dialog_main_slider_container" app:layout_constraintBottom_toTopOf="@+id/volume_dialog_background" /> </androidx.constraintlayout.widget.ConstraintLayout> packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialog.kt +19 −4 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.res.R import com.android.systemui.volume.Events import com.android.systemui.volume.dialog.dagger.factory.VolumeDialogComponentFactory import com.android.systemui.volume.dialog.domain.interactor.DesktopAudioTileDetailsFeatureInteractor import com.android.systemui.volume.dialog.domain.interactor.VolumeDialogVisibilityInteractor import javax.inject.Inject import kotlinx.coroutines.awaitCancellation Loading @@ -40,7 +41,10 @@ constructor( @Application context: Context, private val componentFactory: VolumeDialogComponentFactory, private val visibilityInteractor: VolumeDialogVisibilityInteractor, desktopAudioTileDetailsFeatureInteractor: DesktopAudioTileDetailsFeatureInteractor, ) : ComponentDialog(context, R.style.Theme_SystemUI_Dialog_Volume) { // Use horizontal volume dialog if the audio tile details view is enabled private val isVolumeDialogVertical = !desktopAudioTileDetailsFeatureInteractor.isEnabled() init { with(window!!) { Loading @@ -58,8 +62,13 @@ constructor( attributes.apply { title = "VolumeDialog" // Not the same as Window#setTitle } if (isVolumeDialogVertical) { setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT) setGravity(Gravity.END) } else { setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) setGravity(Gravity.TOP or Gravity.END) } } setCancelable(false) setCanceledOnTouchOutside(true) Loading @@ -67,11 +76,17 @@ constructor( override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (isVolumeDialogVertical) { setContentView(R.layout.volume_dialog) } else { setContentView(R.layout.volume_dialog_horizontal) } requireViewById<View>(R.id.volume_dialog).repeatWhenAttached { coroutineScopeTraced("[Volume]dialog") { val component = componentFactory.create(this) with(component.volumeDialogViewBinder()) { bind(this@VolumeDialog) } with(component.volumeDialogViewBinder()) { bind(this@VolumeDialog, isVolumeDialogVertical) } awaitCancellation() } Loading packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/DesktopAudioTileDetailsFeatureInteractor.kt 0 → 100644 +34 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.volume.dialog.domain.interactor import android.content.Context import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.qs.flags.QsDetailedView import com.android.systemui.res.R import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogPluginScope import javax.inject.Inject @VolumeDialogPluginScope class DesktopAudioTileDetailsFeatureInteractor @Inject constructor(@Application private val context: Context) { fun isEnabled(): Boolean { return QsDetailedView.isEnabled && context.resources.getBoolean(R.bool.config_enableDesktopAudioTileDetailsView) } } packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogOverscrollViewBinder.kt +18 −5 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import androidx.dynamicanimation.animation.FloatValueHolder import androidx.dynamicanimation.animation.SpringAnimation import androidx.dynamicanimation.animation.SpringForce import com.android.app.tracing.coroutines.launchInTraced import com.android.systemui.volume.dialog.domain.interactor.DesktopAudioTileDetailsFeatureInteractor import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogOverscrollViewModel import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogOverscrollViewModel.OverscrollEventModel Loading @@ -31,7 +32,13 @@ import kotlinx.coroutines.flow.onEach @VolumeDialogSliderScope class VolumeDialogOverscrollViewBinder @Inject constructor(private val viewModel: VolumeDialogOverscrollViewModel) { constructor( private val viewModel: VolumeDialogOverscrollViewModel, desktopAudioTileDetailsFeatureInteractor: DesktopAudioTileDetailsFeatureInteractor, ) { // Use horizontal volume dialog if the audio tile details view is enabled private val isVolumeDialogVertical = !desktopAudioTileDetailsFeatureInteractor.isEnabled() /** * [viewsToAnimate] is an array of [View] to be affected by the overscroll animation. [view] is Loading @@ -47,7 +54,9 @@ constructor(private val viewModel: VolumeDialogOverscrollViewModel) { dampingRatio = 0.6f } ) .addUpdateListener { _, value, _ -> viewsToAnimate.setTranslationY(value) } .addUpdateListener { _, value, _ -> viewsToAnimate.setTranslation(value, isVolumeDialogVertical) } viewModel.overscrollEvent .onEach { event -> Loading @@ -57,7 +66,7 @@ constructor(private val viewModel: VolumeDialogOverscrollViewModel) { } is OverscrollEventModel.Move -> { animation.cancel() viewsToAnimate.setTranslationY(event.touchOffsetPx) viewsToAnimate.setTranslation(event.touchOffsetPx, isVolumeDialogVertical) animationValueHolder.value = event.touchOffsetPx } } Loading @@ -66,8 +75,12 @@ constructor(private val viewModel: VolumeDialogOverscrollViewModel) { } } private fun Array<View>.setTranslationY(translation: Float) { private fun Array<View>.setTranslation(translation: Float, isVertical: Boolean) { for (viewToAnimate in this) { if (isVertical) { viewToAnimate.translationY = translation } else { viewToAnimate.translationX = translation } } } packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt +20 −4 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import com.android.systemui.common.ui.compose.Icon import com.android.systemui.haptics.slider.SliderHapticFeedbackFilter import com.android.systemui.haptics.slider.compose.ui.SliderHapticsViewModel import com.android.systemui.res.R import com.android.systemui.volume.dialog.domain.interactor.DesktopAudioTileDetailsFeatureInteractor import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope import com.android.systemui.volume.dialog.sliders.ui.compose.SliderTrack import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogOverscrollViewModel Loading @@ -61,8 +62,11 @@ constructor( private val viewModel: VolumeDialogSliderViewModel, private val overscrollViewModel: VolumeDialogOverscrollViewModel, private val hapticsViewModelFactory: SliderHapticsViewModel.Factory, private val desktopAudioTileDetailsFeatureInteractor: DesktopAudioTileDetailsFeatureInteractor, ) { fun bind(view: View) { // Use horizontal volume dialog if the audio tile details view is enabled val isVolumeDialogVertical = !desktopAudioTileDetailsFeatureInteractor.isEnabled() val sliderComposeView: ComposeView = view.requireViewById(R.id.volume_dialog_slider) sliderComposeView.setContent { PlatformTheme { Loading @@ -70,6 +74,7 @@ constructor( viewModel = viewModel, overscrollViewModel = overscrollViewModel, hapticsViewModelFactory = hapticsViewModelFactory, isVolumeDialogVertical = isVolumeDialogVertical, ) } } Loading @@ -82,6 +87,7 @@ private fun VolumeDialogSlider( viewModel: VolumeDialogSliderViewModel, overscrollViewModel: VolumeDialogOverscrollViewModel, hapticsViewModelFactory: SliderHapticsViewModel.Factory, isVolumeDialogVertical: Boolean, modifier: Modifier = Modifier, ) { val colors = Loading Loading @@ -119,7 +125,7 @@ private fun VolumeDialogSlider( onValueChangeFinished = { viewModel.onSliderChangeFinished(it) }, isEnabled = !sliderStateModel.isDisabled, isReverseDirection = true, isVertical = true, isVertical = isVolumeDialogVertical, colors = colors, interactionSource = interactionSource, haptics = Loading @@ -127,7 +133,12 @@ private fun VolumeDialogSlider( hapticsViewModelFactory = hapticsViewModelFactory, hapticConfigs = VolumeHapticsConfigsProvider.continuousConfigs(SliderHapticFeedbackFilter()), orientation = Orientation.Vertical, orientation = if (isVolumeDialogVertical) { Orientation.Vertical } else { Orientation.Horizontal }, ), stepDistance = 1f, track = { sliderState -> Loading @@ -135,7 +146,7 @@ private fun VolumeDialogSlider( sliderState, colors = colors, isEnabled = !sliderStateModel.isDisabled, isVertical = true, isVertical = isVolumeDialogVertical, activeTrackEndIcon = { iconsState -> SliderIcon( icon = { Loading Loading @@ -168,7 +179,12 @@ private fun VolumeDialogSlider( interactionSource = interactions, enabled = !sliderStateModel.isDisabled, colors = colors, thumbSize = DpSize(52.dp, 4.dp), thumbSize = if (isVolumeDialogVertical) { DpSize(52.dp, 4.dp) } else { DpSize(4.dp, 52.dp) }, ) }, accessibilityParams = AccessibilityParams(contentDescription = sliderStateModel.label), Loading Loading
packages/SystemUI/res/layout/volume_dialog_horizontal.xml 0 → 100644 +103 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2025 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. --> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/volume_dialog" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top|right" android:alpha="0" android:clipChildren="false" android:minHeight="@dimen/volume_dialog_window_width"> <View android:id="@+id/volume_dialog_background" android:layout_width="0dp" android:layout_height="@dimen/volume_dialog_width" android:layout_marginStart="@dimen/volume_dialog_background_top_margin" android:layout_marginEnd="@dimen/volume_dialog_background_margin_negative" android:background="@drawable/volume_dialog_background" app:layout_constraintStart_toStartOf="@+id/volume_dialog_main_slider_container" app:layout_constraintEnd_toEndOf="@+id/volume_dialog_bottom_section_container" app:layout_constraintBottom_toBottomOf="@+id/volume_dialog_main_slider_container" app:layout_constraintTop_toTopOf="@+id/volume_dialog_main_slider_container" /> <FrameLayout android:id="@+id/volume_dialog_top_section_container" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginEnd="@dimen/volume_dialog_components_spacing" android:clipChildren="false" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@+id/volume_dialog_main_slider_container" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="@+id/volume_dialog_background" app:layout_constraintWidth_default="spread" app:layout_constraintHeight_default="spread"> <include layout="@layout/volume_dialog_top_section" /> </FrameLayout> <include android:id="@+id/volume_dialog_main_slider_container" layout="@layout/volume_dialog_slider" android:layout_width="0dp" android:layout_height="@dimen/volume_dialog_slider_width" android:layout_marginStart="@dimen/volume_dialog_slider_vertical_margin" android:layout_marginEnd="@dimen/volume_dialog_slider_vertical_margin" android:layout_marginTop="@dimen/volume_dialog_window_margin" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintWidth_max="@dimen/volume_dialog_slider_height" app:layout_constraintHorizontal_bias="1" /> <FrameLayout android:id="@+id/volume_dialog_bottom_section_container" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginStart="@dimen/volume_dialog_components_spacing" android:clipChildren="false" app:layout_constraintStart_toEndOf="@+id/volume_dialog_main_slider_container" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="@+id/volume_dialog_background" app:layout_constraintBottom_toBottomOf="@+id/volume_dialog_background" app:layout_constraintWidth_default="wrap" app:layout_constraintHeight_default="wrap" app:layout_constraintHorizontal_bias="0"> <include layout="@layout/volume_dialog_bottom_section" /> </FrameLayout> <LinearLayout android:id="@+id/volume_dialog_floating_sliders_container" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="@dimen/volume_dialog_floating_sliders_vertical_padding_negative" android:layout_marginEnd="@dimen/volume_dialog_floating_sliders_vertical_padding_negative" android:clipChildren="false" android:clipToOutline="false" android:clipToPadding="false" android:divider="@drawable/volume_dialog_floating_sliders_spacer" android:gravity="end" android:orientation="vertical" android:showDividers="middle|beginning|end" app:layout_constraintStart_toStartOf="@+id/volume_dialog_main_slider_container" app:layout_constraintEnd_toEndOf="@+id/volume_dialog_main_slider_container" app:layout_constraintBottom_toTopOf="@+id/volume_dialog_background" /> </androidx.constraintlayout.widget.ConstraintLayout>
packages/SystemUI/src/com/android/systemui/volume/dialog/VolumeDialog.kt +19 −4 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.res.R import com.android.systemui.volume.Events import com.android.systemui.volume.dialog.dagger.factory.VolumeDialogComponentFactory import com.android.systemui.volume.dialog.domain.interactor.DesktopAudioTileDetailsFeatureInteractor import com.android.systemui.volume.dialog.domain.interactor.VolumeDialogVisibilityInteractor import javax.inject.Inject import kotlinx.coroutines.awaitCancellation Loading @@ -40,7 +41,10 @@ constructor( @Application context: Context, private val componentFactory: VolumeDialogComponentFactory, private val visibilityInteractor: VolumeDialogVisibilityInteractor, desktopAudioTileDetailsFeatureInteractor: DesktopAudioTileDetailsFeatureInteractor, ) : ComponentDialog(context, R.style.Theme_SystemUI_Dialog_Volume) { // Use horizontal volume dialog if the audio tile details view is enabled private val isVolumeDialogVertical = !desktopAudioTileDetailsFeatureInteractor.isEnabled() init { with(window!!) { Loading @@ -58,8 +62,13 @@ constructor( attributes.apply { title = "VolumeDialog" // Not the same as Window#setTitle } if (isVolumeDialogVertical) { setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT) setGravity(Gravity.END) } else { setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) setGravity(Gravity.TOP or Gravity.END) } } setCancelable(false) setCanceledOnTouchOutside(true) Loading @@ -67,11 +76,17 @@ constructor( override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (isVolumeDialogVertical) { setContentView(R.layout.volume_dialog) } else { setContentView(R.layout.volume_dialog_horizontal) } requireViewById<View>(R.id.volume_dialog).repeatWhenAttached { coroutineScopeTraced("[Volume]dialog") { val component = componentFactory.create(this) with(component.volumeDialogViewBinder()) { bind(this@VolumeDialog) } with(component.volumeDialogViewBinder()) { bind(this@VolumeDialog, isVolumeDialogVertical) } awaitCancellation() } Loading
packages/SystemUI/src/com/android/systemui/volume/dialog/domain/interactor/DesktopAudioTileDetailsFeatureInteractor.kt 0 → 100644 +34 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.volume.dialog.domain.interactor import android.content.Context import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.qs.flags.QsDetailedView import com.android.systemui.res.R import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogPluginScope import javax.inject.Inject @VolumeDialogPluginScope class DesktopAudioTileDetailsFeatureInteractor @Inject constructor(@Application private val context: Context) { fun isEnabled(): Boolean { return QsDetailedView.isEnabled && context.resources.getBoolean(R.bool.config_enableDesktopAudioTileDetailsView) } }
packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogOverscrollViewBinder.kt +18 −5 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import androidx.dynamicanimation.animation.FloatValueHolder import androidx.dynamicanimation.animation.SpringAnimation import androidx.dynamicanimation.animation.SpringForce import com.android.app.tracing.coroutines.launchInTraced import com.android.systemui.volume.dialog.domain.interactor.DesktopAudioTileDetailsFeatureInteractor import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogOverscrollViewModel import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogOverscrollViewModel.OverscrollEventModel Loading @@ -31,7 +32,13 @@ import kotlinx.coroutines.flow.onEach @VolumeDialogSliderScope class VolumeDialogOverscrollViewBinder @Inject constructor(private val viewModel: VolumeDialogOverscrollViewModel) { constructor( private val viewModel: VolumeDialogOverscrollViewModel, desktopAudioTileDetailsFeatureInteractor: DesktopAudioTileDetailsFeatureInteractor, ) { // Use horizontal volume dialog if the audio tile details view is enabled private val isVolumeDialogVertical = !desktopAudioTileDetailsFeatureInteractor.isEnabled() /** * [viewsToAnimate] is an array of [View] to be affected by the overscroll animation. [view] is Loading @@ -47,7 +54,9 @@ constructor(private val viewModel: VolumeDialogOverscrollViewModel) { dampingRatio = 0.6f } ) .addUpdateListener { _, value, _ -> viewsToAnimate.setTranslationY(value) } .addUpdateListener { _, value, _ -> viewsToAnimate.setTranslation(value, isVolumeDialogVertical) } viewModel.overscrollEvent .onEach { event -> Loading @@ -57,7 +66,7 @@ constructor(private val viewModel: VolumeDialogOverscrollViewModel) { } is OverscrollEventModel.Move -> { animation.cancel() viewsToAnimate.setTranslationY(event.touchOffsetPx) viewsToAnimate.setTranslation(event.touchOffsetPx, isVolumeDialogVertical) animationValueHolder.value = event.touchOffsetPx } } Loading @@ -66,8 +75,12 @@ constructor(private val viewModel: VolumeDialogOverscrollViewModel) { } } private fun Array<View>.setTranslationY(translation: Float) { private fun Array<View>.setTranslation(translation: Float, isVertical: Boolean) { for (viewToAnimate in this) { if (isVertical) { viewToAnimate.translationY = translation } else { viewToAnimate.translationX = translation } } }
packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt +20 −4 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import com.android.systemui.common.ui.compose.Icon import com.android.systemui.haptics.slider.SliderHapticFeedbackFilter import com.android.systemui.haptics.slider.compose.ui.SliderHapticsViewModel import com.android.systemui.res.R import com.android.systemui.volume.dialog.domain.interactor.DesktopAudioTileDetailsFeatureInteractor import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope import com.android.systemui.volume.dialog.sliders.ui.compose.SliderTrack import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogOverscrollViewModel Loading @@ -61,8 +62,11 @@ constructor( private val viewModel: VolumeDialogSliderViewModel, private val overscrollViewModel: VolumeDialogOverscrollViewModel, private val hapticsViewModelFactory: SliderHapticsViewModel.Factory, private val desktopAudioTileDetailsFeatureInteractor: DesktopAudioTileDetailsFeatureInteractor, ) { fun bind(view: View) { // Use horizontal volume dialog if the audio tile details view is enabled val isVolumeDialogVertical = !desktopAudioTileDetailsFeatureInteractor.isEnabled() val sliderComposeView: ComposeView = view.requireViewById(R.id.volume_dialog_slider) sliderComposeView.setContent { PlatformTheme { Loading @@ -70,6 +74,7 @@ constructor( viewModel = viewModel, overscrollViewModel = overscrollViewModel, hapticsViewModelFactory = hapticsViewModelFactory, isVolumeDialogVertical = isVolumeDialogVertical, ) } } Loading @@ -82,6 +87,7 @@ private fun VolumeDialogSlider( viewModel: VolumeDialogSliderViewModel, overscrollViewModel: VolumeDialogOverscrollViewModel, hapticsViewModelFactory: SliderHapticsViewModel.Factory, isVolumeDialogVertical: Boolean, modifier: Modifier = Modifier, ) { val colors = Loading Loading @@ -119,7 +125,7 @@ private fun VolumeDialogSlider( onValueChangeFinished = { viewModel.onSliderChangeFinished(it) }, isEnabled = !sliderStateModel.isDisabled, isReverseDirection = true, isVertical = true, isVertical = isVolumeDialogVertical, colors = colors, interactionSource = interactionSource, haptics = Loading @@ -127,7 +133,12 @@ private fun VolumeDialogSlider( hapticsViewModelFactory = hapticsViewModelFactory, hapticConfigs = VolumeHapticsConfigsProvider.continuousConfigs(SliderHapticFeedbackFilter()), orientation = Orientation.Vertical, orientation = if (isVolumeDialogVertical) { Orientation.Vertical } else { Orientation.Horizontal }, ), stepDistance = 1f, track = { sliderState -> Loading @@ -135,7 +146,7 @@ private fun VolumeDialogSlider( sliderState, colors = colors, isEnabled = !sliderStateModel.isDisabled, isVertical = true, isVertical = isVolumeDialogVertical, activeTrackEndIcon = { iconsState -> SliderIcon( icon = { Loading Loading @@ -168,7 +179,12 @@ private fun VolumeDialogSlider( interactionSource = interactions, enabled = !sliderStateModel.isDisabled, colors = colors, thumbSize = DpSize(52.dp, 4.dp), thumbSize = if (isVolumeDialogVertical) { DpSize(52.dp, 4.dp) } else { DpSize(4.dp, 52.dp) }, ) }, accessibilityParams = AccessibilityParams(contentDescription = sliderStateModel.label), Loading