Loading packages/SystemUI/res/drawable/ic_stop.xml 0 → 100644 +29 −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. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="20dp" android:height="20dp" android:viewportWidth="20" android:viewportHeight="20"> <group> <clip-path android:pathData="M0,0h20v20h-20z"/> <path android:pathData="M4,14V6C4,5.45 4.192,4.983 4.575,4.6C4.975,4.2 5.45,4 6,4H14C14.55,4 15.017,4.2 15.4,4.6C15.8,4.983 16,5.45 16,6V14C16,14.55 15.8,15.025 15.4,15.425C15.017,15.808 14.55,16 14,16H6C5.45,16 4.975,15.808 4.575,15.425C4.192,15.025 4,14.55 4,14Z" android:fillColor="#ffffff"/> </group> </vector> packages/SystemUI/src/com/android/systemui/screencapture/common/ui/compose/PrimaryButton.kt +9 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,9 @@ package com.android.systemui.screencapture.common.ui.compose import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.size import androidx.compose.material3.ButtonColors import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment Loading @@ -41,11 +44,17 @@ fun PrimaryButton( icon: IconModel? = null, contentPadding: PaddingValues = ButtonPaddings, iconPadding: Dp = 5.dp, colors: ButtonColors = ButtonDefaults.buttonColors( containerColor = MaterialTheme.colorScheme.primary, contentColor = MaterialTheme.colorScheme.onPrimary, ), ) { PlatformButton( onClick = onClick, modifier = modifier, enabled = enabled, colors = colors, contentPadding = contentPadding, ) { if (icon != null) { Loading packages/SystemUI/src/com/android/systemui/screencapture/record/smallscreen/ui/compose/SmallScreenCaptureRecordContent.kt +58 −12 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.FloatingToolbarDefaults import androidx.compose.material3.IconButtonDefaults Loading @@ -66,6 +67,7 @@ import com.android.systemui.screencapture.common.ui.compose.LoadingIcon import com.android.systemui.screencapture.common.ui.compose.PrimaryButton import com.android.systemui.screencapture.common.ui.compose.ScreenCaptureContent import com.android.systemui.screencapture.common.ui.compose.loadIcon import com.android.systemui.screencapture.common.ui.viewmodel.DrawableLoaderViewModel import com.android.systemui.screencapture.record.smallscreen.ui.viewmodel.RecordDetailsPopupType import com.android.systemui.screencapture.record.smallscreen.ui.viewmodel.SmallScreenCaptureRecordViewModel import javax.inject.Inject Loading Loading @@ -135,18 +137,10 @@ constructor(private val viewModelFactory: SmallScreenCaptureRecordViewModel.Fact ) } Spacer(Modifier.width(12.dp)) val recordIcon by loadIcon( ToolbarPrimaryButton( recording = viewModel.isRecording, onClick = { viewModel.onPrimaryButtonTapped() }, viewModel = viewModel, resId = R.drawable.ic_screenrecord, contentDescription = null, ) PrimaryButton( onClick = { viewModel.startRecording() }, text = stringResource(R.string.screen_capture_toolbar_record_button), icon = recordIcon, contentPadding = PaddingValues(horizontal = 14.dp), iconPadding = 4.dp, modifier = Modifier.height(40.dp), ) } Loading Loading @@ -228,3 +222,55 @@ private fun ToggleToolbarButton( } } } @Composable private fun ToolbarPrimaryButton( recording: Boolean, viewModel: DrawableLoaderViewModel, onClick: () -> Unit, modifier: Modifier = Modifier, ) { AnimatedContent(targetState = recording) { isRecording -> if (isRecording) { PrimaryButton( onClick = onClick, text = stringResource(R.string.screenrecord_stop_label), icon = loadIcon( viewModel = viewModel, resId = R.drawable.ic_stop, contentDescription = null, ) .value, contentPadding = PaddingValues(horizontal = 14.dp), iconPadding = 4.dp, colors = ButtonDefaults.buttonColors( containerColor = MaterialTheme.colorScheme.error, contentColor = MaterialTheme.colorScheme.onError, ), modifier = modifier, ) } else { PrimaryButton( onClick = onClick, text = stringResource(R.string.screen_capture_toolbar_record_button), icon = loadIcon( viewModel = viewModel, resId = R.drawable.ic_screenrecord, contentDescription = null, ) .value, contentPadding = PaddingValues(horizontal = 14.dp), iconPadding = 4.dp, colors = ButtonDefaults.buttonColors( containerColor = MaterialTheme.colorScheme.primary, contentColor = MaterialTheme.colorScheme.onPrimary, ), modifier = modifier, ) } } } packages/SystemUI/src/com/android/systemui/screencapture/record/smallscreen/ui/viewmodel/SmallScreenCaptureRecordViewModel.kt +25 −12 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.screencapture.record.smallscreen.ui.viewmodel import android.media.projection.StopReason import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue Loading Loading @@ -53,6 +54,14 @@ constructor( val recordDetailsTargetViewModel: RecordDetailsTargetViewModel = recordDetailsTargetViewModelFactory.create() val isRecording: Boolean by screenRecordingServiceInteractor.status .map { it.isRecording } .hydratedStateOf( traceName = "SmallScreenCaptureRecordViewModel#isRecording", initialValue = screenRecordingServiceInteractor.status.value.isRecording, ) var detailsPopup: RecordDetailsPopupType by mutableStateOf(RecordDetailsPopupType.Settings) private set Loading Loading @@ -107,7 +116,10 @@ constructor( screenCaptureUiInteractor.hide(ScreenCaptureType.RECORD) } fun startRecording() { fun onPrimaryButtonTapped() { if (screenRecordingServiceInteractor.status.value.isRecording) { screenRecordingServiceInteractor.stopRecording(StopReason.STOP_HOST_APP) } else { val shouldShowTaps = recordDetailsParametersViewModel.shouldShowTaps ?: return val audioSource = recordDetailsParametersViewModel.audioSource ?: return // TODO(b/428686600) pass actual parameters Loading @@ -121,6 +133,7 @@ constructor( ) dismiss() } } fun shouldShowSettings(visible: Boolean) { if (shouldShowSettingsButton) { Loading Loading
packages/SystemUI/res/drawable/ic_stop.xml 0 → 100644 +29 −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. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="20dp" android:height="20dp" android:viewportWidth="20" android:viewportHeight="20"> <group> <clip-path android:pathData="M0,0h20v20h-20z"/> <path android:pathData="M4,14V6C4,5.45 4.192,4.983 4.575,4.6C4.975,4.2 5.45,4 6,4H14C14.55,4 15.017,4.2 15.4,4.6C15.8,4.983 16,5.45 16,6V14C16,14.55 15.8,15.025 15.4,15.425C15.017,15.808 14.55,16 14,16H6C5.45,16 4.975,15.808 4.575,15.425C4.192,15.025 4,14.55 4,14Z" android:fillColor="#ffffff"/> </group> </vector>
packages/SystemUI/src/com/android/systemui/screencapture/common/ui/compose/PrimaryButton.kt +9 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,9 @@ package com.android.systemui.screencapture.common.ui.compose import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.size import androidx.compose.material3.ButtonColors import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment Loading @@ -41,11 +44,17 @@ fun PrimaryButton( icon: IconModel? = null, contentPadding: PaddingValues = ButtonPaddings, iconPadding: Dp = 5.dp, colors: ButtonColors = ButtonDefaults.buttonColors( containerColor = MaterialTheme.colorScheme.primary, contentColor = MaterialTheme.colorScheme.onPrimary, ), ) { PlatformButton( onClick = onClick, modifier = modifier, enabled = enabled, colors = colors, contentPadding = contentPadding, ) { if (icon != null) { Loading
packages/SystemUI/src/com/android/systemui/screencapture/record/smallscreen/ui/compose/SmallScreenCaptureRecordContent.kt +58 −12 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.FloatingToolbarDefaults import androidx.compose.material3.IconButtonDefaults Loading @@ -66,6 +67,7 @@ import com.android.systemui.screencapture.common.ui.compose.LoadingIcon import com.android.systemui.screencapture.common.ui.compose.PrimaryButton import com.android.systemui.screencapture.common.ui.compose.ScreenCaptureContent import com.android.systemui.screencapture.common.ui.compose.loadIcon import com.android.systemui.screencapture.common.ui.viewmodel.DrawableLoaderViewModel import com.android.systemui.screencapture.record.smallscreen.ui.viewmodel.RecordDetailsPopupType import com.android.systemui.screencapture.record.smallscreen.ui.viewmodel.SmallScreenCaptureRecordViewModel import javax.inject.Inject Loading Loading @@ -135,18 +137,10 @@ constructor(private val viewModelFactory: SmallScreenCaptureRecordViewModel.Fact ) } Spacer(Modifier.width(12.dp)) val recordIcon by loadIcon( ToolbarPrimaryButton( recording = viewModel.isRecording, onClick = { viewModel.onPrimaryButtonTapped() }, viewModel = viewModel, resId = R.drawable.ic_screenrecord, contentDescription = null, ) PrimaryButton( onClick = { viewModel.startRecording() }, text = stringResource(R.string.screen_capture_toolbar_record_button), icon = recordIcon, contentPadding = PaddingValues(horizontal = 14.dp), iconPadding = 4.dp, modifier = Modifier.height(40.dp), ) } Loading Loading @@ -228,3 +222,55 @@ private fun ToggleToolbarButton( } } } @Composable private fun ToolbarPrimaryButton( recording: Boolean, viewModel: DrawableLoaderViewModel, onClick: () -> Unit, modifier: Modifier = Modifier, ) { AnimatedContent(targetState = recording) { isRecording -> if (isRecording) { PrimaryButton( onClick = onClick, text = stringResource(R.string.screenrecord_stop_label), icon = loadIcon( viewModel = viewModel, resId = R.drawable.ic_stop, contentDescription = null, ) .value, contentPadding = PaddingValues(horizontal = 14.dp), iconPadding = 4.dp, colors = ButtonDefaults.buttonColors( containerColor = MaterialTheme.colorScheme.error, contentColor = MaterialTheme.colorScheme.onError, ), modifier = modifier, ) } else { PrimaryButton( onClick = onClick, text = stringResource(R.string.screen_capture_toolbar_record_button), icon = loadIcon( viewModel = viewModel, resId = R.drawable.ic_screenrecord, contentDescription = null, ) .value, contentPadding = PaddingValues(horizontal = 14.dp), iconPadding = 4.dp, colors = ButtonDefaults.buttonColors( containerColor = MaterialTheme.colorScheme.primary, contentColor = MaterialTheme.colorScheme.onPrimary, ), modifier = modifier, ) } } }
packages/SystemUI/src/com/android/systemui/screencapture/record/smallscreen/ui/viewmodel/SmallScreenCaptureRecordViewModel.kt +25 −12 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.screencapture.record.smallscreen.ui.viewmodel import android.media.projection.StopReason import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue Loading Loading @@ -53,6 +54,14 @@ constructor( val recordDetailsTargetViewModel: RecordDetailsTargetViewModel = recordDetailsTargetViewModelFactory.create() val isRecording: Boolean by screenRecordingServiceInteractor.status .map { it.isRecording } .hydratedStateOf( traceName = "SmallScreenCaptureRecordViewModel#isRecording", initialValue = screenRecordingServiceInteractor.status.value.isRecording, ) var detailsPopup: RecordDetailsPopupType by mutableStateOf(RecordDetailsPopupType.Settings) private set Loading Loading @@ -107,7 +116,10 @@ constructor( screenCaptureUiInteractor.hide(ScreenCaptureType.RECORD) } fun startRecording() { fun onPrimaryButtonTapped() { if (screenRecordingServiceInteractor.status.value.isRecording) { screenRecordingServiceInteractor.stopRecording(StopReason.STOP_HOST_APP) } else { val shouldShowTaps = recordDetailsParametersViewModel.shouldShowTaps ?: return val audioSource = recordDetailsParametersViewModel.audioSource ?: return // TODO(b/428686600) pass actual parameters Loading @@ -121,6 +133,7 @@ constructor( ) dismiss() } } fun shouldShowSettings(visible: Boolean) { if (shouldShowSettingsButton) { Loading