Merge "Redesigns the volume panel, take 2!" into sc-dev

This commit is contained in:
Julia Reynolds
2021-02-26 15:16:25 +00:00
committed by Android (Google) Code Review
13 changed files with 953 additions and 188 deletions

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 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="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?android:attr/colorBackgroundFloating" >
<path
android:pathData="M6 10c-1.1 0-2 0.9-2 2s0.9 2 2 2 2-0.9 2-2-0.9-2-2-2zm12 0c-1.1 0-2 0.9-2 2s0.9 2 2 2 2-0.9 2-2-0.9-2-2-2zm-6 0c-1.1 0-2 0.9-2 2s0.9 2 2 2 2-0.9 2-2-0.9-2-2-2z"
android:fillColor="@android:color/white" />
</vector>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2021 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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingMode="stack" >
<size android:width="@dimen/volume_ringer_drawer_item_size" />
<solid android:color="?android:attr/colorBackgroundFloating" />
<corners android:radius="@dimen/volume_ringer_drawer_item_size_half" />
</shape>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2021 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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingMode="stack" >
<size
android:height="@dimen/volume_ringer_drawer_item_size"
android:width="@dimen/volume_ringer_drawer_item_size" />
<solid android:color="?android:attr/colorAccent" />
<corners android:radius="@dimen/volume_ringer_drawer_item_size_half" />
</shape>

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2021 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.
-->
<!-- SeekBar drawable for volume rows. This contains a background layer (with a solid round rect,
and a bottom-aligned icon) and a progress layer (with an accent-colored round rect and icon)
that moves up and down with the progress value. -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingMode="stack" >
<item android:id="@android:id/background"
android:gravity="center_vertical|fill_horizontal">
<layer-list>
<item android:id="@+id/volume_seekbar_background_solid">
<shape>
<size android:height="@dimen/volume_dialog_panel_width" />
<solid android:color="?android:attr/colorBackgroundFloating" />
<corners android:radius="@dimen/volume_dialog_panel_width_half" />
</shape>
</item>
<item
android:id="@+id/volume_seekbar_background_icon"
android:gravity="center_vertical|left"
android:height="@dimen/rounded_slider_icon_size"
android:width="@dimen/rounded_slider_icon_size"
android:left="@dimen/rounded_slider_icon_inset">
<rotate
android:fromDegrees="-270"
android:toDegrees="-270">
<!-- A placeholder drawable is required here - it'll be replaced in code. -->
<com.android.systemui.util.AlphaTintDrawableWrapper
android:drawable="@drawable/ic_volume_media"
android:tint="?android:attr/colorAccent" />
</rotate>
</item>
</layer-list>
</item>
<item android:id="@android:id/progress"
android:gravity="center_vertical|fill_horizontal">
<com.android.systemui.util.RoundedCornerProgressDrawable
android:drawable="@drawable/volume_row_seekbar_progress"
/>
</item>
</layer-list>

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2021 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.
-->
<!-- Progress drawable for volume row SeekBars. This is the accent-colored round rect that moves up
and down as the progress value changes. -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:autoMirrored="true">
<item android:id="@+id/volume_seekbar_progress_solid">
<shape>
<size android:height="@dimen/volume_dialog_panel_width" />
<solid android:color="?android:attr/colorAccent" />
<corners android:radius="@dimen/volume_dialog_panel_width_half"/>
</shape>
</item>
<item
android:id="@+id/volume_seekbar_progress_icon"
android:gravity="center_vertical|right"
android:height="@dimen/rounded_slider_icon_size"
android:width="@dimen/rounded_slider_icon_size"
android:right="@dimen/rounded_slider_icon_inset">
<rotate
android:fromDegrees="-270"
android:toDegrees="-270">
<!-- A placeholder drawable is required here - it'll be replaced in code. -->
<com.android.systemui.util.AlphaTintDrawableWrapper
android:drawable="@drawable/ic_volume_media"
android:tint="?android:attr/colorBackgroundFloating" />
</rotate>
</item>
</layer-list>

View File

@@ -32,105 +32,124 @@
android:gravity="right"
android:layout_gravity="right"
android:background="@android:color/transparent"
android:paddingRight="@dimen/volume_dialog_panel_transparent_padding_right"
android:paddingTop="@dimen/volume_dialog_panel_transparent_padding"
android:paddingBottom="@dimen/volume_dialog_panel_transparent_padding"
android:paddingRight="@dimen/volume_dialog_stream_padding"
android:paddingLeft="@dimen/volume_dialog_panel_transparent_padding"
android:clipToPadding="false">
<FrameLayout
android:id="@+id/ringer"
android:layout_width="@dimen/volume_dialog_ringer_size"
android:layout_height="@dimen/volume_dialog_ringer_size"
android:layout_marginBottom="@dimen/volume_dialog_spacer"
android:gravity="right"
android:layout_gravity="right"
android:translationZ="@dimen/volume_dialog_elevation"
android:clipToPadding="false"
android:background="@drawable/rounded_bg_full">
<com.android.keyguard.AlphaOptimizedImageButton
android:id="@+id/ringer_icon"
style="@style/VolumeButtons"
android:background="@drawable/rounded_ripple"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"
android:padding="@dimen/volume_dialog_ringer_icon_padding"
android:tint="@color/accent_tint_color_selector"
android:layout_gravity="center"
android:soundEffectsEnabled="false" />
<include layout="@layout/volume_dnd_icon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/volume_dialog_stream_padding"
android:layout_marginTop="6dp"/>
</FrameLayout>
<!--
Container for a) the ringer drawer and the caption button next to b) the volume rows.
-->
<LinearLayout
android:id="@+id/main"
android:layout_width="wrap_content"
android:minWidth="@dimen/volume_dialog_panel_width"
android:layout_height="wrap_content"
android:layout_marginTop="68dp"
android:gravity="right"
android:layout_gravity="right"
android:orientation="vertical"
android:translationZ="@dimen/volume_dialog_elevation"
android:orientation="horizontal"
android:clipChildren="false"
android:clipToPadding="false"
android:background="@drawable/rounded_bg_full" >
<LinearLayout
android:id="@+id/volume_dialog_rows"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="@dimen/volume_dialog_panel_width"
android:gravity="center"
android:orientation="horizontal"
android:paddingRight="@dimen/volume_dialog_stream_padding"
android:paddingLeft="@dimen/volume_dialog_stream_padding">
<!-- volume rows added and removed here! :-) -->
</LinearLayout>
<FrameLayout
android:id="@+id/settings_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/rounded_bg_bottom_background">
<com.android.keyguard.AlphaOptimizedImageButton
android:id="@+id/settings"
android:src="@drawable/ic_tune_black_16dp"
android:layout_width="@dimen/volume_dialog_tap_target_size"
android:layout_height="@dimen/volume_dialog_tap_target_size"
android:layout_gravity="center"
android:contentDescription="@string/accessibility_volume_settings"
android:background="@drawable/ripple_drawable_20dp"
android:tint="?android:attr/textColorSecondary"
android:soundEffectsEnabled="false" />
</FrameLayout>
</LinearLayout>
android:clipToPadding="false">
<FrameLayout
android:id="@+id/odi_captions"
android:layout_width="@dimen/volume_dialog_caption_size"
android:layout_height="@dimen/volume_dialog_caption_size"
android:layout_marginRight="68dp"
android:gravity="right"
android:layout_gravity="right"
android:clipToPadding="false"
android:translationZ="@dimen/volume_dialog_elevation"
android:background="@drawable/rounded_bg_full">
<com.android.systemui.volume.CaptionsToggleImageButton
android:id="@+id/odi_captions_icon"
android:src="@drawable/ic_volume_odi_captions_disabled"
style="@style/VolumeButtons"
android:background="@drawable/rounded_ripple"
android:layout_width="match_parent"
<!-- The ringer drawer and the caption button. -->
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:tint="@color/caption_tint_color_selector"
android:layout_gravity="center"
android:soundEffectsEnabled="false"
sysui:optedOut="false"/>
</FrameLayout>
android:paddingRight="@dimen/volume_dialog_stream_padding"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical">
<include layout="@layout/volume_ringer_drawer"
android:layout_gravity="top|right"/>
<FrameLayout
android:id="@+id/odi_captions"
android:layout_width="@dimen/volume_dialog_caption_size"
android:layout_height="@dimen/volume_dialog_caption_size"
android:gravity="center"
android:layout_gravity="bottom|right"
android:layout_marginBottom="@dimen/volume_dialog_tap_target_size"
android:clipToPadding="false">
<com.android.systemui.volume.CaptionsToggleImageButton
android:id="@+id/odi_captions_icon"
android:src="@drawable/ic_volume_odi_captions_disabled"
style="@style/VolumeButtons"
android:background="@drawable/rounded_ripple"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:tint="@color/caption_tint_color_selector"
android:layout_gravity="center"
android:soundEffectsEnabled="false"
sysui:optedOut="false"/>
</FrameLayout>
</FrameLayout>
<FrameLayout
android:visibility="gone"
android:id="@+id/ringer"
android:layout_width="@dimen/volume_dialog_ringer_size"
android:layout_height="@dimen/volume_dialog_ringer_size"
android:layout_marginBottom="@dimen/volume_dialog_spacer"
android:gravity="right"
android:layout_gravity="right"
android:translationZ="@dimen/volume_dialog_elevation"
android:clipToPadding="false"
android:background="@drawable/rounded_bg_full">
<com.android.keyguard.AlphaOptimizedImageButton
android:id="@+id/ringer_icon"
style="@style/VolumeButtons"
android:background="@drawable/rounded_ripple"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"
android:padding="@dimen/volume_dialog_ringer_icon_padding"
android:tint="@color/accent_tint_color_selector"
android:layout_gravity="center"
android:soundEffectsEnabled="false" />
<include layout="@layout/volume_dnd_icon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/volume_dialog_stream_padding"
android:layout_marginTop="6dp"/>
</FrameLayout>
<LinearLayout
android:id="@+id/main"
android:layout_width="wrap_content"
android:minWidth="@dimen/volume_dialog_panel_width"
android:layout_height="wrap_content"
android:gravity="right"
android:layout_gravity="right"
android:orientation="vertical"
android:clipChildren="false"
android:clipToPadding="false">
<LinearLayout
android:id="@+id/volume_dialog_rows"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="@dimen/volume_dialog_panel_width"
android:gravity="center"
android:orientation="horizontal">
<!-- volume rows added and removed here! :-) -->
</LinearLayout>
<FrameLayout
android:id="@+id/settings_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.android.keyguard.AlphaOptimizedImageButton
android:id="@+id/settings"
android:src="@drawable/horizontal_ellipsis"
android:layout_width="@dimen/volume_dialog_tap_target_size"
android:layout_height="@dimen/volume_dialog_tap_target_size"
android:layout_gravity="center"
android:contentDescription="@string/accessibility_volume_settings"
android:background="@drawable/ripple_drawable_20dp"
android:tint="?android:attr/colorBackgroundFloating"
android:soundEffectsEnabled="false" />
</FrameLayout>
</LinearLayout>
</LinearLayout>
<ViewStub
android:id="@+id/odi_captions_tooltip_stub"

View File

@@ -21,6 +21,8 @@
android:layout_height="wrap_content"
android:gravity="right"
android:layout_gravity="right"
android:paddingRight="@dimen/volume_dialog_stream_padding"
android:clipToPadding="false"
android:background="@android:color/transparent"
android:theme="@style/volume_dialog_theme">
@@ -34,13 +36,15 @@
android:layout_gravity="right"
android:background="@android:color/transparent"
android:paddingRight="@dimen/volume_dialog_panel_transparent_padding_right"
android:paddingTop="@dimen/volume_dialog_panel_transparent_padding"
android:paddingBottom="@dimen/volume_dialog_panel_transparent_padding"
android:paddingLeft="@dimen/volume_dialog_panel_transparent_padding"
android:orientation="vertical"
android:clipToPadding="false">
android:clipToPadding="false"
android:clipChildren="false">
<include layout="@layout/volume_ringer_drawer" />
<FrameLayout
android:visibility="gone"
android:id="@+id/ringer"
android:layout_width="@dimen/volume_dialog_ringer_size"
android:layout_height="@dimen/volume_dialog_ringer_size"
@@ -77,10 +81,8 @@
android:gravity="right"
android:layout_gravity="right"
android:orientation="vertical"
android:translationZ="@dimen/volume_dialog_elevation"
android:clipChildren="false"
android:clipToPadding="false"
android:background="@drawable/rounded_bg_full" >
android:clipToPadding="false" >
<LinearLayout
android:id="@+id/volume_dialog_rows"
android:layout_width="wrap_content"
@@ -88,24 +90,22 @@
android:minWidth="@dimen/volume_dialog_panel_width"
android:gravity="center"
android:orientation="horizontal"
android:paddingRight="@dimen/volume_dialog_stream_padding"
android:paddingLeft="@dimen/volume_dialog_stream_padding">
android:layout_marginTop="@dimen/volume_row_slider_padding_start">
<!-- volume rows added and removed here! :-) -->
</LinearLayout>
<FrameLayout
android:id="@+id/settings_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/rounded_bg_bottom_background">
android:layout_height="wrap_content">
<com.android.keyguard.AlphaOptimizedImageButton
android:id="@+id/settings"
android:src="@drawable/ic_tune_black_16dp"
android:src="@drawable/horizontal_ellipsis"
android:layout_width="@dimen/volume_dialog_tap_target_size"
android:layout_height="@dimen/volume_dialog_tap_target_size"
android:layout_gravity="center"
android:contentDescription="@string/accessibility_volume_settings"
android:background="@drawable/ripple_drawable_20dp"
android:tint="?android:attr/textColorPrimary"
android:tint="?android:attr/colorBackgroundFloating"
android:soundEffectsEnabled="false" />
</FrameLayout>
</LinearLayout>
@@ -118,7 +118,6 @@
android:gravity="right"
android:layout_gravity="right"
android:clipToPadding="false"
android:translationZ="@dimen/volume_dialog_elevation"
android:background="@drawable/rounded_bg_full">
<com.android.systemui.volume.CaptionsToggleImageButton
android:id="@+id/odi_captions_icon"
@@ -127,7 +126,7 @@
android:background="@drawable/rounded_ripple"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:tint="?android:attr/textColorPrimary"
android:tint="?android:attr/colorAccent"
android:layout_gravity="center"
android:soundEffectsEnabled="false"
sysui:optedOut="false"/>

View File

@@ -20,11 +20,12 @@
android:layout_width="@dimen/volume_dialog_panel_width"
android:clipChildren="false"
android:clipToPadding="false"
android:translationZ="@dimen/volume_dialog_elevation"
android:theme="@style/volume_dialog_theme">
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_width="@dimen/volume_dialog_panel_width"
android:gravity="center"
android:layout_gravity="center"
android:orientation="vertical" >
@@ -41,21 +42,23 @@
<FrameLayout
android:id="@+id/volume_row_slider_frame"
android:layout_width="match_parent"
android:layout_marginTop="@dimen/volume_dialog_slider_margin_top"
android:layout_marginBottom="@dimen/volume_dialog_slider_margin_bottom"
android:layoutDirection="rtl"
android:layout_height="@dimen/volume_dialog_slider_height">
android:layout_height="@dimen/volume_row_slider_height">
<include layout="@layout/volume_dnd_icon"/>
<SeekBar
android:id="@+id/volume_row_slider"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:paddingStart="0dp"
android:paddingEnd="0dp"
android:clickable="true"
android:layout_width="@dimen/volume_dialog_slider_height"
android:layout_width="@dimen/volume_row_slider_height"
android:layout_height="match_parent"
android:layoutDirection="rtl"
android:layout_gravity="center"
android:rotation="90" />
android:rotation="270" />
</FrameLayout>
<com.android.keyguard.AlphaOptimizedImageButton
android:visibility="gone"
android:id="@+id/volume_row_icon"
style="@style/VolumeButtons"
android:layout_width="@dimen/volume_dialog_tap_target_size"
@@ -66,6 +69,4 @@
android:soundEffectsEnabled="false" />
</LinearLayout>
<include layout="@layout/volume_dnd_icon"/>
</FrameLayout>

View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2021 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.
-->
<!-- Contains the active ringer icon and a hidden drawer containing all three ringer options. -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:clipToPadding="false"
android:clipChildren="false">
<!-- Drawer view, invisible by default. -->
<FrameLayout
android:id="@+id/volume_drawer_container"
android:alpha="0.0"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/volume_drawer_bg"
android:orientation="vertical">
<!-- View that is animated to a tapped ringer selection, so it appears selected. -->
<FrameLayout
android:id="@+id/volume_drawer_selection_background"
android:alpha="0.0"
android:layout_width="@dimen/volume_ringer_drawer_item_size"
android:layout_height="@dimen/volume_ringer_drawer_item_size"
android:layout_gravity="bottom|right"
android:background="@drawable/volume_drawer_selection_bg" />
<LinearLayout
android:id="@+id/volume_drawer_options"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<FrameLayout
android:id="@+id/volume_drawer_vibrate"
android:layout_width="@dimen/volume_ringer_drawer_item_size"
android:layout_height="@dimen/volume_ringer_drawer_item_size"
android:description="@string/volume_ringer_hint_vibrate"
android:gravity="center">
<ImageView
android:id="@+id/volume_drawer_vibrate_icon"
android:layout_width="@dimen/volume_ringer_drawer_icon_size"
android:layout_height="@dimen/volume_ringer_drawer_icon_size"
android:layout_gravity="center"
android:tint="?android:attr/colorAccent"
android:src="@drawable/ic_volume_ringer_vibrate" />
</FrameLayout>
<FrameLayout
android:id="@+id/volume_drawer_mute"
android:layout_width="@dimen/volume_ringer_drawer_item_size"
android:layout_height="@dimen/volume_ringer_drawer_item_size"
android:description="@string/volume_ringer_hint_mute"
android:gravity="center">
<ImageView
android:id="@+id/volume_drawer_mute_icon"
android:layout_width="@dimen/volume_ringer_drawer_icon_size"
android:layout_height="@dimen/volume_ringer_drawer_icon_size"
android:layout_gravity="center"
android:tint="?android:attr/colorAccent"
android:src="@drawable/ic_volume_ringer_mute" />
</FrameLayout>
<FrameLayout
android:id="@+id/volume_drawer_normal"
android:layout_width="@dimen/volume_ringer_drawer_item_size"
android:layout_height="@dimen/volume_ringer_drawer_item_size"
android:description="@string/volume_ringer_hint_unmute"
android:gravity="center">
<ImageView
android:id="@+id/volume_drawer_normal_icon"
android:layout_width="@dimen/volume_ringer_drawer_icon_size"
android:layout_height="@dimen/volume_ringer_drawer_icon_size"
android:layout_gravity="center"
android:tint="?android:attr/colorAccent"
android:src="@drawable/ic_volume_ringer" />
</FrameLayout>
</LinearLayout>
</FrameLayout>
<!-- The current ringer selection. When the drawer is opened, this animates to the corresponding
position in the drawer. When the drawer is closed, it animates back. -->
<FrameLayout
android:id="@+id/volume_new_ringer_active_icon_container"
android:layout_width="@dimen/volume_ringer_drawer_item_size"
android:layout_height="@dimen/volume_ringer_drawer_item_size"
android:layout_gravity="bottom|right"
android:description="@string/volume_ringer_change"
android:background="@drawable/volume_drawer_selection_bg">
<ImageView
android:id="@+id/volume_new_ringer_active_icon"
android:layout_width="@dimen/volume_ringer_drawer_icon_size"
android:layout_height="@dimen/volume_ringer_drawer_icon_size"
android:layout_gravity="center"
android:tint="?android:attr/colorBackgroundFloating"
android:src="@drawable/ic_volume_media" />
</FrameLayout>
</FrameLayout>

View File

@@ -456,10 +456,12 @@
<dimen name="volume_dialog_panel_transparent_padding">20dp</dimen>
<dimen name="volume_dialog_stream_padding">8dp</dimen>
<dimen name="volume_dialog_stream_padding">12dp</dimen>
<dimen name="volume_dialog_panel_width">64dp</dimen>
<dimen name="volume_dialog_panel_width_half">32dp</dimen>
<dimen name="volume_dialog_slider_height">116dp</dimen>
<dimen name="volume_dialog_ringer_size">64dp</dimen>
@@ -486,6 +488,13 @@
<dimen name="volume_tool_tip_arrow_corner_radius">2dp</dimen>
<!-- Size of each item in the ringer selector drawer. -->
<dimen name="volume_ringer_drawer_item_size">64dp</dimen>
<dimen name="volume_ringer_drawer_item_size_half">32dp</dimen>
<!-- Size of the icon inside each item in the ringer selector drawer. -->
<dimen name="volume_ringer_drawer_icon_size">24dp</dimen>
<!-- Gravity for the notification panel -->
<integer name="notification_panel_layout_gravity">0x31</integer><!-- center_horizontal|top -->
@@ -966,7 +975,7 @@
<dimen name="volume_row_padding_start">4dp</dimen>
<dimen name="volume_row_header_padding_start">16dp</dimen>
<dimen name="volume_row_height">64dp</dimen>
<dimen name="volume_row_slider_height">48dp</dimen>
<dimen name="volume_row_slider_height">192dp</dimen>
<dimen name="volume_row_slider_padding_start">12dp</dimen>
<dimen name="volume_expander_margin_end">2dp</dimen>

View File

@@ -1558,6 +1558,8 @@
<string name="volume_stream_content_description_vibrate_a11y">%1$s. Tap to set to vibrate.</string>
<string name="volume_stream_content_description_mute_a11y">%1$s. Tap to mute.</string>
<string name="volume_ringer_change">Tap to change ringer mode</string>
<!-- Hint for accessibility. For example: double tap to mute [CHAR_LIMIT=NONE] -->
<string name="volume_ringer_hint_mute">mute</string>
<!-- Hint for accessibility. For example: double tap to unmute [CHAR_LIMIT=NONE] -->

View File

@@ -33,7 +33,11 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static com.android.systemui.volume.Events.DISMISS_REASON_SETTINGS_CLICKED;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.Dialog;
@@ -51,6 +55,9 @@ import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Region;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.RotateDrawable;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.os.Debug;
@@ -81,6 +88,8 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
@@ -88,6 +97,7 @@ import android.widget.Toast;
import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.media.dialog.MediaOutputDialogFactory;
@@ -99,6 +109,8 @@ import com.android.systemui.plugins.VolumeDialogController.StreamState;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.util.AlphaTintDrawableWrapper;
import com.android.systemui.util.RoundedCornerProgressDrawable;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -124,8 +136,14 @@ public class VolumeDialogImpl implements VolumeDialog,
static final int DIALOG_ODI_CAPTIONS_TOOLTIP_TIMEOUT_MILLIS = 5000;
static final int DIALOG_HOVERING_TIMEOUT_MILLIS = 16000;
private static final int DRAWER_ANIMATION_DURATION_SHORT = 175;
private static final int DRAWER_ANIMATION_DURATION = 250;
private final int mDialogShowAnimationDurationMs;
private final int mDialogHideAnimationDurationMs;
private final int mRingerDrawerItemSize;
private final boolean mShowVibrate;
private final int mRingerCount;
private final boolean mShowLowMediaVolumeIcon;
private final boolean mChangeVolumeRowTintWhenInactive;
@@ -140,6 +158,30 @@ public class VolumeDialogImpl implements VolumeDialog,
private ViewGroup mDialogView;
private ViewGroup mDialogRowsView;
private ViewGroup mRinger;
private ViewGroup mSelectedRingerContainer;
private ImageView mSelectedRingerIcon;
private ViewGroup mRingerDrawerContainer;
private ViewGroup mRingerDrawerMute;
private ViewGroup mRingerDrawerVibrate;
private ViewGroup mRingerDrawerNormal;
private ImageView mRingerDrawerMuteIcon;
private ImageView mRingerDrawerVibrateIcon;
private ImageView mRingerDrawerNormalIcon;
/**
* View that draws the 'selected' background behind one of the three ringer choices in the
* drawer.
*/
private ViewGroup mRingerDrawerNewSelectionBg;
private final ValueAnimator mRingerDrawerIconColorAnimator = ValueAnimator.ofFloat(0f, 1f);
private ImageView mRingerDrawerIconAnimatingSelected;
private ImageView mRingerDrawerIconAnimatingDeselected;
private boolean mIsRingerDrawerOpen = false;
private ImageButton mRingerIcon;
private ViewGroup mODICaptionsView;
private CaptionsToggleImageButton mODICaptionsIcon;
@@ -191,6 +233,12 @@ public class VolumeDialogImpl implements VolumeDialog,
mContext.getResources().getInteger(R.integer.config_dialogShowAnimationDurationMs);
mDialogHideAnimationDurationMs =
mContext.getResources().getInteger(R.integer.config_dialogHideAnimationDurationMs);
mRingerDrawerItemSize = mContext.getResources().getDimensionPixelSize(
R.dimen.volume_ringer_drawer_item_size);
mShowVibrate = mController.hasVibrator();
// Normal, mute, and possibly vibrate.
mRingerCount = mShowVibrate ? 3 : 2;
}
@Override
@@ -314,6 +362,20 @@ public class VolumeDialogImpl implements VolumeDialog,
mZenIcon = mRinger.findViewById(R.id.dnd_icon);
}
mSelectedRingerIcon = mDialog.findViewById(R.id.volume_new_ringer_active_icon);
mSelectedRingerContainer = mDialog.findViewById(
R.id.volume_new_ringer_active_icon_container);
mRingerDrawerMute = mDialog.findViewById(R.id.volume_drawer_mute);
mRingerDrawerNormal = mDialog.findViewById(R.id.volume_drawer_normal);
mRingerDrawerVibrate = mDialog.findViewById(R.id.volume_drawer_vibrate);
mRingerDrawerMuteIcon = mDialog.findViewById(R.id.volume_drawer_mute_icon);
mRingerDrawerVibrateIcon = mDialog.findViewById(R.id.volume_drawer_vibrate_icon);
mRingerDrawerNormalIcon = mDialog.findViewById(R.id.volume_drawer_normal_icon);
mRingerDrawerNewSelectionBg = mDialog.findViewById(R.id.volume_drawer_selection_background);
setupRingerDrawer();
mODICaptionsView = mDialog.findViewById(R.id.odi_captions);
if (mODICaptionsView != null) {
mODICaptionsIcon = mODICaptionsView.findViewById(R.id.odi_captions_icon);
@@ -475,40 +537,275 @@ public class VolumeDialogImpl implements VolumeDialog,
row.anim = null;
final LayerDrawable seekbarDrawable =
(LayerDrawable) mContext.getDrawable(R.drawable.volume_row_seekbar);
final LayerDrawable seekbarBgDrawable =
(LayerDrawable) seekbarDrawable.findDrawableByLayerId(android.R.id.background);
row.sliderBgSolid = seekbarBgDrawable.findDrawableByLayerId(
R.id.volume_seekbar_background_solid);
row.sliderBgIcon = (AlphaTintDrawableWrapper)
((RotateDrawable) seekbarBgDrawable.findDrawableByLayerId(
R.id.volume_seekbar_background_icon)).getDrawable();
final LayerDrawable seekbarProgressDrawable = (LayerDrawable)
((RoundedCornerProgressDrawable) seekbarDrawable.findDrawableByLayerId(
android.R.id.progress)).getDrawable();
row.sliderProgressSolid = seekbarProgressDrawable.findDrawableByLayerId(
R.id.volume_seekbar_progress_solid);
row.sliderProgressIcon = (AlphaTintDrawableWrapper)
((RotateDrawable) seekbarProgressDrawable.findDrawableByLayerId(
R.id.volume_seekbar_progress_icon)).getDrawable();
row.slider.setProgressDrawable(seekbarDrawable);
row.slider.setThumb(null);
row.icon = row.view.findViewById(R.id.volume_row_icon);
row.icon.setImageResource(iconRes);
if (row.stream != AudioSystem.STREAM_ACCESSIBILITY) {
row.icon.setOnClickListener(v -> {
Events.writeEvent(Events.EVENT_ICON_CLICK, row.stream, row.iconState);
mController.setActiveStream(row.stream);
if (row.stream == AudioManager.STREAM_RING) {
final boolean hasVibrator = mController.hasVibrator();
if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
if (hasVibrator) {
mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
row.setIcon(iconRes, mContext.getTheme());
if (row.icon != null) {
if (row.stream != AudioSystem.STREAM_ACCESSIBILITY) {
row.icon.setOnClickListener(v -> {
Events.writeEvent(Events.EVENT_ICON_CLICK, row.stream, row.iconState);
mController.setActiveStream(row.stream);
if (row.stream == AudioManager.STREAM_RING) {
final boolean hasVibrator = mController.hasVibrator();
if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
if (hasVibrator) {
mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
} else {
final boolean wasZero = row.ss.level == 0;
mController.setStreamVolume(stream,
wasZero ? row.lastAudibleLevel : 0);
}
} else {
final boolean wasZero = row.ss.level == 0;
mController.setStreamVolume(stream,
wasZero ? row.lastAudibleLevel : 0);
mController.setRingerMode(
AudioManager.RINGER_MODE_NORMAL, false);
if (row.ss.level == 0) {
mController.setStreamVolume(stream, 1);
}
}
} else {
mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
if (row.ss.level == 0) {
mController.setStreamVolume(stream, 1);
}
final boolean vmute = row.ss.level == row.ss.levelMin;
mController.setStreamVolume(stream,
vmute ? row.lastAudibleLevel : row.ss.levelMin);
}
} else {
final boolean vmute = row.ss.level == row.ss.levelMin;
mController.setStreamVolume(stream,
vmute ? row.lastAudibleLevel : row.ss.levelMin);
}
row.userAttempt = 0; // reset the grace period, slider updates immediately
});
} else {
row.icon.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
row.userAttempt = 0; // reset the grace period, slider updates immediately
});
} else {
row.icon.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
}
}
}
private void setRingerMode(int newRingerMode) {
Events.writeEvent(Events.EVENT_RINGER_TOGGLE, newRingerMode);
incrementManualToggleCount();
updateRingerH();
provideTouchFeedbackH(newRingerMode);
mController.setRingerMode(newRingerMode, false);
maybeShowToastH(newRingerMode);
}
private void setupRingerDrawer() {
mRingerDrawerContainer = mDialog.findViewById(R.id.volume_drawer_container);
if (mRingerDrawerContainer == null) {
return;
}
if (!mShowVibrate) {
mRingerDrawerVibrate.setVisibility(GONE);
}
// In portrait, add padding to the bottom to account for the height of the open ringer
// drawer.
if (!isLandscape()) {
mDialogView.setPadding(
mDialogView.getPaddingLeft(),
mDialogView.getPaddingTop(),
mDialogView.getPaddingRight(),
mDialogView.getPaddingBottom() + (mRingerCount - 1) * mRingerDrawerItemSize);
} else {
mDialogView.setPadding(
mDialogView.getPaddingLeft() + (mRingerCount - 1) * mRingerDrawerItemSize,
mDialogView.getPaddingTop(),
mDialogView.getPaddingRight(),
mDialogView.getPaddingBottom());
}
((LinearLayout) mRingerDrawerContainer.findViewById(R.id.volume_drawer_options))
.setOrientation(isLandscape() ? LinearLayout.HORIZONTAL : LinearLayout.VERTICAL);
mSelectedRingerContainer.setOnClickListener(view -> {
if (mIsRingerDrawerOpen) {
hideRingerDrawer();
} else {
showRingerDrawer();
}
});
mRingerDrawerVibrate.setOnClickListener(
new RingerDrawerItemClickListener(RINGER_MODE_VIBRATE));
mRingerDrawerMute.setOnClickListener(
new RingerDrawerItemClickListener(RINGER_MODE_SILENT));
mRingerDrawerNormal.setOnClickListener(
new RingerDrawerItemClickListener(RINGER_MODE_NORMAL));
final int unselectedColor = Utils.getColorAccentDefaultColor(mContext);
final int selectedColor = Utils.getColorAttrDefaultColor(
mContext, android.R.attr.colorBackgroundFloating);
// Add an update listener that animates the deselected icon to the unselected color, and the
// selected icon to the selected color.
mRingerDrawerIconColorAnimator.addUpdateListener(
anim -> {
final float currentValue = (float) anim.getAnimatedValue();
final int curUnselectedColor = (int) ArgbEvaluator.getInstance().evaluate(
currentValue, selectedColor, unselectedColor);
final int curSelectedColor = (int) ArgbEvaluator.getInstance().evaluate(
currentValue, unselectedColor, selectedColor);
mRingerDrawerIconAnimatingDeselected.setColorFilter(curUnselectedColor);
mRingerDrawerIconAnimatingSelected.setColorFilter(curSelectedColor);
});
mRingerDrawerIconColorAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mRingerDrawerIconAnimatingDeselected.clearColorFilter();
mRingerDrawerIconAnimatingSelected.clearColorFilter();
}
});
mRingerDrawerIconColorAnimator.setDuration(DRAWER_ANIMATION_DURATION_SHORT);
}
private ImageView getDrawerIconViewForMode(int mode) {
if (mode == RINGER_MODE_VIBRATE) {
return mRingerDrawerVibrateIcon;
} else if (mode == RINGER_MODE_SILENT) {
return mRingerDrawerMuteIcon;
} else {
return mRingerDrawerNormalIcon;
}
}
/**
* Translation to apply form the origin (either top or left) to overlap the selection background
* with the given mode in the drawer.
*/
private float getTranslationInDrawerForRingerMode(int mode) {
return mode == RINGER_MODE_VIBRATE
? -mRingerDrawerItemSize * 2
: mode == RINGER_MODE_SILENT
? -mRingerDrawerItemSize
: 0;
}
/** Animates in the ringer drawer. */
private void showRingerDrawer() {
// Show all ringer icons except the currently selected one, since we're going to animate the
// ringer button to that position.
mRingerDrawerVibrateIcon.setVisibility(
mState.ringerModeInternal == RINGER_MODE_VIBRATE ? INVISIBLE : VISIBLE);
mRingerDrawerMuteIcon.setVisibility(
mState.ringerModeInternal == RINGER_MODE_SILENT ? INVISIBLE : VISIBLE);
mRingerDrawerNormalIcon.setVisibility(
mState.ringerModeInternal == RINGER_MODE_NORMAL ? INVISIBLE : VISIBLE);
// Hide the selection background - we use this to show a selection when one is
// tapped, so it should be invisible until that happens. However, position it below
// the currently selected ringer so that it's ready to animate.
mRingerDrawerNewSelectionBg.setAlpha(0f);
if (!isLandscape()) {
mRingerDrawerNewSelectionBg.setTranslationY(
getTranslationInDrawerForRingerMode(mState.ringerModeInternal));
} else {
mRingerDrawerNewSelectionBg.setTranslationX(
getTranslationInDrawerForRingerMode(mState.ringerModeInternal));
}
// Move the drawer so that the top/rightmost ringer choice overlaps with the selected ringer
// icon.
if (!isLandscape()) {
mRingerDrawerContainer.setTranslationY(mRingerDrawerItemSize * (mRingerCount - 1));
} else {
mRingerDrawerContainer.setTranslationX(mRingerDrawerItemSize * (mRingerCount - 1));
}
mRingerDrawerContainer.setAlpha(0f);
mRingerDrawerContainer.setVisibility(VISIBLE);
// Animate the drawer up and visible.
mRingerDrawerContainer.animate()
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
// Vibrate is way farther up, so give the selected ringer icon a head start if
// vibrate is selected.
.setDuration(mState.ringerModeInternal == RINGER_MODE_VIBRATE
? DRAWER_ANIMATION_DURATION_SHORT
: DRAWER_ANIMATION_DURATION)
.setStartDelay(mState.ringerModeInternal == RINGER_MODE_VIBRATE
? DRAWER_ANIMATION_DURATION - DRAWER_ANIMATION_DURATION_SHORT
: 0)
.alpha(1f)
.translationX(0f)
.translationY(0f)
.start();
// Animate the selected ringer view up to that ringer's position in the drawer.
mSelectedRingerContainer.animate()
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.setDuration(DRAWER_ANIMATION_DURATION)
.withEndAction(() ->
getDrawerIconViewForMode(mState.ringerModeInternal).setVisibility(VISIBLE));
if (!isLandscape()) {
mSelectedRingerContainer.animate()
.translationY(getTranslationInDrawerForRingerMode(mState.ringerModeInternal))
.start();
} else {
mSelectedRingerContainer.animate()
.translationX(getTranslationInDrawerForRingerMode(mState.ringerModeInternal))
.start();
}
mIsRingerDrawerOpen = true;
}
/** Animates away the ringer drawer. */
private void hideRingerDrawer() {
// Hide the drawer icon for the selected ringer - it's visible in the ringer button and we
// don't want to be able to see it while it animates away.
getDrawerIconViewForMode(mState.ringerModeInternal).setVisibility(INVISIBLE);
mRingerDrawerContainer.animate()
.alpha(0f)
.setDuration(DRAWER_ANIMATION_DURATION)
.setStartDelay(0)
.withEndAction(() -> mRingerDrawerContainer.setVisibility(INVISIBLE));
if (!isLandscape()) {
mRingerDrawerContainer.animate()
.translationY(mRingerDrawerItemSize * 2)
.start();
} else {
mRingerDrawerContainer.animate()
.translationX(mRingerDrawerItemSize * 2)
.start();
}
mSelectedRingerContainer.animate()
.translationX(0f)
.translationY(0f)
.start();
mIsRingerDrawerOpen = false;
}
public void initSettingsH() {
if (mSettingsView != null) {
mSettingsView.setVisibility(
@@ -555,12 +852,8 @@ public class VolumeDialogImpl implements VolumeDialog,
mController.setStreamVolume(AudioManager.STREAM_RING, 1);
}
}
Events.writeEvent(Events.EVENT_RINGER_TOGGLE, newRingerMode);
incrementManualToggleCount();
updateRingerH();
provideTouchFeedbackH(newRingerMode);
mController.setRingerMode(newRingerMode, false);
maybeShowToastH(newRingerMode);
setRingerMode(newRingerMode);
});
}
updateRingerH();
@@ -809,6 +1102,8 @@ public class VolumeDialogImpl implements VolumeDialog,
mDialog.dismiss();
tryToRemoveCaptionsTooltip();
mIsAnimatingDismiss = false;
hideRingerDrawer();
}, 50));
if (!isLandscape()) animator.translationX(mDialogView.getWidth() / 2.0f);
animator.start();
@@ -889,12 +1184,14 @@ public class VolumeDialogImpl implements VolumeDialog,
switch (mState.ringerModeInternal) {
case AudioManager.RINGER_MODE_VIBRATE:
mRingerIcon.setImageResource(R.drawable.ic_volume_ringer_vibrate);
mSelectedRingerIcon.setImageResource(R.drawable.ic_volume_ringer_vibrate);
addAccessibilityDescription(mRingerIcon, RINGER_MODE_VIBRATE,
mContext.getString(R.string.volume_ringer_hint_mute));
mRingerIcon.setTag(Events.ICON_STATE_VIBRATE);
break;
case AudioManager.RINGER_MODE_SILENT:
mRingerIcon.setImageResource(R.drawable.ic_volume_ringer_mute);
mSelectedRingerIcon.setImageResource(R.drawable.ic_volume_ringer_mute);
mRingerIcon.setTag(Events.ICON_STATE_MUTE);
addAccessibilityDescription(mRingerIcon, RINGER_MODE_SILENT,
mContext.getString(R.string.volume_ringer_hint_unmute));
@@ -904,11 +1201,13 @@ public class VolumeDialogImpl implements VolumeDialog,
boolean muted = (mAutomute && ss.level == 0) || ss.muted;
if (!isZenMuted && muted) {
mRingerIcon.setImageResource(R.drawable.ic_volume_ringer_mute);
mSelectedRingerIcon.setImageResource(R.drawable.ic_volume_ringer_mute);
addAccessibilityDescription(mRingerIcon, RINGER_MODE_NORMAL,
mContext.getString(R.string.volume_ringer_hint_unmute));
mRingerIcon.setTag(Events.ICON_STATE_MUTE);
} else {
mRingerIcon.setImageResource(R.drawable.ic_volume_ringer);
mSelectedRingerIcon.setImageResource(R.drawable.ic_volume_ringer);
if (mController.hasVibrator()) {
addAccessibilityDescription(mRingerIcon, RINGER_MODE_NORMAL,
mContext.getString(R.string.volume_ringer_hint_vibrate));
@@ -1075,8 +1374,6 @@ public class VolumeDialogImpl implements VolumeDialog,
// update icon
final boolean iconEnabled = (mAutomute || ss.muteSupported) && !zenMuted;
row.icon.setEnabled(iconEnabled);
row.icon.setAlpha(iconEnabled ? 1 : 0.5f);
final int iconRes;
if (isRingVibrate) {
iconRes = R.drawable.ic_volume_ringer_vibrate;
@@ -1092,7 +1389,7 @@ public class VolumeDialogImpl implements VolumeDialog,
? R.drawable.ic_volume_media_low : row.iconRes;
}
row.icon.setImageResource(iconRes);
row.setIcon(iconRes, mContext.getTheme());
row.iconState =
iconRes == R.drawable.ic_volume_ringer_vibrate ? Events.ICON_STATE_VIBRATE
: (iconRes == R.drawable.ic_volume_media_bt_mute || iconRes == row.iconMuteRes)
@@ -1101,18 +1398,35 @@ public class VolumeDialogImpl implements VolumeDialog,
|| iconRes == R.drawable.ic_volume_media_low)
? Events.ICON_STATE_UNMUTE
: Events.ICON_STATE_UNKNOWN;
if (iconEnabled) {
if (isRingStream) {
if (isRingVibrate) {
row.icon.setContentDescription(mContext.getString(
R.string.volume_stream_content_description_unmute,
getStreamLabelH(ss)));
} else {
if (mController.hasVibrator()) {
if (row.icon != null) {
if (iconEnabled) {
if (isRingStream) {
if (isRingVibrate) {
row.icon.setContentDescription(mContext.getString(
mShowA11yStream
? R.string.volume_stream_content_description_vibrate_a11y
: R.string.volume_stream_content_description_vibrate,
R.string.volume_stream_content_description_unmute,
getStreamLabelH(ss)));
} else {
if (mController.hasVibrator()) {
row.icon.setContentDescription(mContext.getString(
mShowA11yStream
? R.string.volume_stream_content_description_vibrate_a11y
: R.string.volume_stream_content_description_vibrate,
getStreamLabelH(ss)));
} else {
row.icon.setContentDescription(mContext.getString(
mShowA11yStream
? R.string.volume_stream_content_description_mute_a11y
: R.string.volume_stream_content_description_mute,
getStreamLabelH(ss)));
}
}
} else if (isA11yStream) {
row.icon.setContentDescription(getStreamLabelH(ss));
} else {
if (ss.muted || mAutomute && ss.level == 0) {
row.icon.setContentDescription(mContext.getString(
R.string.volume_stream_content_description_unmute,
getStreamLabelH(ss)));
} else {
row.icon.setContentDescription(mContext.getString(
@@ -1122,23 +1436,9 @@ public class VolumeDialogImpl implements VolumeDialog,
getStreamLabelH(ss)));
}
}
} else if (isA11yStream) {
row.icon.setContentDescription(getStreamLabelH(ss));
} else {
if (ss.muted || mAutomute && ss.level == 0) {
row.icon.setContentDescription(mContext.getString(
R.string.volume_stream_content_description_unmute,
getStreamLabelH(ss)));
} else {
row.icon.setContentDescription(mContext.getString(
mShowA11yStream
? R.string.volume_stream_content_description_mute_a11y
: R.string.volume_stream_content_description_mute,
getStreamLabelH(ss)));
}
row.icon.setContentDescription(getStreamLabelH(ss));
}
} else {
row.icon.setContentDescription(getStreamLabelH(ss));
}
// ensure tracking is disabled if zenMuted
@@ -1167,22 +1467,29 @@ public class VolumeDialogImpl implements VolumeDialog,
if (!useActiveColoring && !mChangeVolumeRowTintWhenInactive) {
return;
}
final ColorStateList tint = useActiveColoring
final ColorStateList colorTint = useActiveColoring
? Utils.getColorAccent(mContext)
: Utils.getColorAttr(mContext, android.R.attr.colorForeground);
final int alpha = useActiveColoring
? Color.alpha(tint.getDefaultColor())
? Color.alpha(colorTint.getDefaultColor())
: getAlphaAttr(android.R.attr.secondaryContentAlpha);
if (tint == row.cachedTint) return;
row.slider.setProgressTintList(tint);
row.slider.setThumbTintList(tint);
row.slider.setProgressBackgroundTintList(tint);
row.slider.setAlpha(((float) alpha) / 255);
row.icon.setImageTintList(tint);
row.icon.setImageAlpha(alpha);
row.cachedTint = tint;
final ColorStateList bgTint = Utils.getColorAttr(
mContext, android.R.attr.colorBackgroundFloating);
row.sliderProgressSolid.setTintList(colorTint);
row.sliderBgIcon.setTintList(colorTint);
row.sliderBgSolid.setTintList(bgTint);
row.sliderProgressIcon.setTintList(bgTint);
if (row.icon != null) {
row.icon.setImageTintList(colorTint);
row.icon.setImageAlpha(alpha);
}
if (row.number != null) {
row.number.setTextColor(tint);
row.number.setTextColor(colorTint);
row.number.setAlpha(alpha);
}
}
@@ -1538,6 +1845,10 @@ public class VolumeDialogImpl implements VolumeDialog,
private View view;
private TextView header;
private ImageButton icon;
private Drawable sliderBgSolid;
private AlphaTintDrawableWrapper sliderBgIcon;
private Drawable sliderProgressSolid;
private AlphaTintDrawableWrapper sliderProgressIcon;
private SeekBar slider;
private TextView number;
private int stream;
@@ -1555,5 +1866,69 @@ public class VolumeDialogImpl implements VolumeDialog,
private int animTargetProgress;
private int lastAudibleLevel = 1;
private FrameLayout dndIcon;
void setIcon(int iconRes, Resources.Theme theme) {
if (icon != null) {
icon.setImageResource(iconRes);
}
sliderProgressIcon.setDrawable(view.getResources().getDrawable(iconRes, theme));
sliderBgIcon.setDrawable(view.getResources().getDrawable(iconRes, theme));
}
}
/**
* Click listener added to each ringer option in the drawer. This will initiate the animation to
* select and then close the ringer drawer, and actually change the ringer mode.
*/
private class RingerDrawerItemClickListener implements View.OnClickListener {
private final int mClickedRingerMode;
RingerDrawerItemClickListener(int clickedRingerMode) {
mClickedRingerMode = clickedRingerMode;
}
@Override
public void onClick(View view) {
setRingerMode(mClickedRingerMode);
mRingerDrawerIconAnimatingSelected = getDrawerIconViewForMode(mClickedRingerMode);
mRingerDrawerIconAnimatingDeselected = getDrawerIconViewForMode(
mState.ringerModeInternal);
// Begin switching the selected icon and deselected icon colors since the background is
// going to animate behind the new selection.
mRingerDrawerIconColorAnimator.start();
mSelectedRingerContainer.setVisibility(View.INVISIBLE);
mRingerDrawerNewSelectionBg.setAlpha(1f);
mRingerDrawerNewSelectionBg.animate()
.setInterpolator(Interpolators.ACCELERATE_DECELERATE)
.setDuration(DRAWER_ANIMATION_DURATION_SHORT)
.withEndAction(() -> {
mRingerDrawerNewSelectionBg.setAlpha(0f);
if (!isLandscape()) {
mSelectedRingerContainer.setTranslationY(
getTranslationInDrawerForRingerMode(mClickedRingerMode));
} else {
mSelectedRingerContainer.setTranslationX(
getTranslationInDrawerForRingerMode(mClickedRingerMode));
}
mSelectedRingerContainer.setVisibility(VISIBLE);
hideRingerDrawer();
});
if (!isLandscape()) {
mRingerDrawerNewSelectionBg.animate()
.translationY(getTranslationInDrawerForRingerMode(mClickedRingerMode))
.start();
} else {
mRingerDrawerNewSelectionBg.animate()
.translationX(getTranslationInDrawerForRingerMode(mClickedRingerMode))
.start();
}
}
}
}

View File

@@ -22,6 +22,7 @@ import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.app.KeyguardManager;
@@ -37,6 +38,8 @@ import android.view.accessibility.AccessibilityManager;
import androidx.test.filters.SmallTest;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.plugins.VolumeDialogController.State;
@@ -58,6 +61,11 @@ import java.util.function.Predicate;
public class VolumeDialogImplTest extends SysuiTestCase {
VolumeDialogImpl mDialog;
View mActiveRinger;
View mDrawerContainer;
View mDrawerVibrate;
View mDrawerMute;
View mDrawerNormal;
@Mock
VolumeDialogController mController;
@@ -80,6 +88,17 @@ public class VolumeDialogImplTest extends SysuiTestCase {
mDialog.init(0, null);
State state = createShellState();
mDialog.onStateChangedH(state);
mActiveRinger = mDialog.getDialogView().findViewById(
R.id.volume_new_ringer_active_icon_container);
mDrawerContainer = mDialog.getDialogView().findViewById(R.id.volume_drawer_container);
mDrawerVibrate = mDrawerContainer.findViewById(R.id.volume_drawer_vibrate);
mDrawerMute = mDrawerContainer.findViewById(R.id.volume_drawer_mute);
mDrawerNormal = mDrawerContainer.findViewById(R.id.volume_drawer_normal);
Prefs.putInt(mContext,
Prefs.Key.SEEN_RINGER_GUIDANCE_COUNT,
VolumePrefs.SHOW_RINGER_TOAST_COUNT + 1);
}
private State createShellState() {
@@ -207,6 +226,48 @@ public class VolumeDialogImplTest extends SysuiTestCase {
verify(mController, never()).vibrate(any());
}
@Test
public void testSelectVibrateFromDrawer() {
final State initialUnsetState = new State();
initialUnsetState.ringerModeInternal = AudioManager.RINGER_MODE_NORMAL;
mDialog.onStateChangedH(initialUnsetState);
mActiveRinger.performClick();
mDrawerVibrate.performClick();
// Make sure we've actually changed the ringer mode.
verify(mController, times(1)).setRingerMode(
AudioManager.RINGER_MODE_VIBRATE, false);
}
@Test
public void testSelectMuteFromDrawer() {
final State initialUnsetState = new State();
initialUnsetState.ringerModeInternal = AudioManager.RINGER_MODE_NORMAL;
mDialog.onStateChangedH(initialUnsetState);
mActiveRinger.performClick();
mDrawerMute.performClick();
// Make sure we've actually changed the ringer mode.
verify(mController, times(1)).setRingerMode(
AudioManager.RINGER_MODE_SILENT, false);
}
@Test
public void testSelectNormalFromDrawer() {
final State initialUnsetState = new State();
initialUnsetState.ringerModeInternal = AudioManager.RINGER_MODE_VIBRATE;
mDialog.onStateChangedH(initialUnsetState);
mActiveRinger.performClick();
mDrawerNormal.performClick();
// Make sure we've actually changed the ringer mode.
verify(mController, times(1)).setRingerMode(
AudioManager.RINGER_MODE_NORMAL, false);
}
/*
@Test
public void testContentDescriptions() {