diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2018-04-26 07:20:54 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2018-04-26 07:20:54 +0000 |
commit | bc494a8827042319f5d60c683311f10e438004df (patch) | |
tree | 1d021f8bc1af282bf48a1080c56a47c9e8365d30 | |
parent | 9f07c6c37dc0d26178ade6e6c6f54e3743e07c39 (diff) | |
parent | 5289168183d65b16813447c2b160adab799f1ac8 (diff) | |
download | Media-bc494a8827042319f5d60c683311f10e438004df.tar.gz |
Snap for 4745538 from 5289168183d65b16813447c2b160adab799f1ac8 to pi-release
Change-Id: I880283151f2c973d4be1d226cdd2c7dec62196cd
29 files changed, 432 insertions, 794 deletions
diff --git a/res/drawable/ic_overflow_activated.xml b/res/drawable/ic_overflow_activated.xml deleted file mode 100644 index 1649b7cc..00000000 --- a/res/drawable/ic_overflow_activated.xml +++ /dev/null @@ -1,39 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="56dp" - android:height="56dp" - android:viewportWidth="24" - android:viewportHeight="24"> - - <group - android:translateX="-0.750000" - android:translateY="-0.750000"> - <path - android:strokeWidth="1" - android:pathData="M 0.75 24.75 L 24.75 24.75 L 24.75 0.75 L 0.75 0.75 Z" /> - <path - android:fillColor="#000000" - android:strokeWidth="1" - android:pathData="M12.75,0.75 C6.123,0.75 0.75,6.123 0.75,12.75 C0.75,19.377 6.123,24.75 -12.75,24.75 C19.377,24.75 24.75,19.377 24.75,12.75 C24.75,6.123 19.377,0.75 -12.75,0.75 M12.75,2.036 C18.658,2.036 23.464,6.842 23.464,12.75 C23.464,18.658 -18.658,23.464 12.75,23.464 C6.842,23.464 2.036,18.658 2.036,12.75 C2.036,6.842 -6.842,2.036 12.75,2.036" /> - <path - android:fillColor="#000000" - android:strokeWidth="1" - android:pathData="M12.75,10.1666667 C13.4604167,10.1666667 14.0416667,9.58541667 14.0416667,8.875 -C14.0416667,8.16458333 13.4604167,7.58333333 12.75,7.58333333 -C12.0395833,7.58333333 11.4583333,8.16458333 11.4583333,8.875 -C11.4583333,9.58541667 12.0395833,10.1666667 12.75,10.1666667 L12.75,10.1666667 -Z M12.75,11.4583333 C12.0395833,11.4583333 11.4583333,12.0395833 -11.4583333,12.75 C11.4583333,13.4604167 12.0395833,14.0416667 12.75,14.0416667 -C13.4604167,14.0416667 14.0416667,13.4604167 14.0416667,12.75 -C14.0416667,12.0395833 13.4604167,11.4583333 12.75,11.4583333 L12.75,11.4583333 -Z M12.75,15.3333333 C12.0395833,15.3333333 11.4583333,15.9145833 -11.4583333,16.625 C11.4583333,17.3354167 12.0395833,17.9166667 12.75,17.9166667 -C13.4604167,17.9166667 14.0416667,17.3354167 14.0416667,16.625 -C14.0416667,15.9145833 13.4604167,15.3333333 12.75,15.3333333 L12.75,15.3333333 -Z" /> - </group> -</vector> diff --git a/res/drawable/ic_overflow_normal.xml b/res/drawable/ic_overflow_normal.xml deleted file mode 100644 index de7b761c..00000000 --- a/res/drawable/ic_overflow_normal.xml +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="56dp" - android:height="56dp" - android:viewportWidth="24" - android:viewportHeight="24"> - - <group - android:translateX="-0.750000" - android:translateY="-0.750000"> - <path - android:strokeWidth="1" - android:pathData="M 0.75 24.75 L 24.75 24.75 L 24.75 0.75 L 0.75 0.75 Z" /> - <path - android:fillColor="#000000" - android:strokeWidth="1" - android:pathData="M12.75,10.1666667 C13.4604167,10.1666667 14.0416667,9.58541667 14.0416667,8.875 -C14.0416667,8.16458333 13.4604167,7.58333333 12.75,7.58333333 -C12.0395833,7.58333333 11.4583333,8.16458333 11.4583333,8.875 -C11.4583333,9.58541667 12.0395833,10.1666667 12.75,10.1666667 L12.75,10.1666667 -Z M12.75,11.4583333 C12.0395833,11.4583333 11.4583333,12.0395833 -11.4583333,12.75 C11.4583333,13.4604167 12.0395833,14.0416667 12.75,14.0416667 -C13.4604167,14.0416667 14.0416667,13.4604167 14.0416667,12.75 -C14.0416667,12.0395833 13.4604167,11.4583333 12.75,11.4583333 L12.75,11.4583333 -Z M12.75,15.3333333 C12.0395833,15.3333333 11.4583333,15.9145833 -11.4583333,16.625 C11.4583333,17.3354167 12.0395833,17.9166667 12.75,17.9166667 -C13.4604167,17.9166667 14.0416667,17.3354167 14.0416667,16.625 -C14.0416667,15.9145833 13.4604167,15.3333333 12.75,15.3333333 L12.75,15.3333333 -Z" /> - </group> -</vector> diff --git a/res/drawable/ic_pause.xml b/res/drawable/ic_pause.xml deleted file mode 100644 index 3e80cd11..00000000 --- a/res/drawable/ic_pause.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="56dp" - android:height="56dp" - android:viewportWidth="48" - android:viewportHeight="48"> - - <path - android:fillColor="#000000" - android:pathData="M12 38h8V10h-8v28zm16-28v28h8V10h-8z" /> - <path - android:pathData="M0 0h48v48H0z" /> -</vector> diff --git a/res/drawable/ic_play_arrow.xml b/res/drawable/ic_play_arrow.xml deleted file mode 100644 index d15c1213..00000000 --- a/res/drawable/ic_play_arrow.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="56dp" - android:height="56dp" - android:viewportWidth="48" - android:viewportHeight="48"> - - <path - android:pathData="M-838-2232H562v3600H-838z" /> - <path - android:fillColor="#000000" - android:pathData="M16 10v28l22-14z" /> - <path - android:pathData="M0 0h48v48H0z" /> -</vector> diff --git a/res/drawable/ic_play_arrow_off.xml b/res/drawable/ic_play_arrow_off.xml deleted file mode 100644 index 33b70ca9..00000000 --- a/res/drawable/ic_play_arrow_off.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="56dp" - android:height="56dp" - android:viewportWidth="24" - android:viewportHeight="24"> - - <group - android:translateX="3.000000" - android:translateY="3.000000"> - <path - android:fillColor="#000000" - android:strokeWidth="1" - android:pathData="M16,9 L7.249,3.431 L14.048,10.242 L16,9 Z" /> - <path - android:fillColor="#000000" - android:strokeWidth="1" - android:pathData="M18,16.73 L1.27,0 L0,1.27 L5,6.27 L5,16 L10.946,12.216 L16.73,18 L18,16.73 Z" /> - </group> -</vector> diff --git a/res/drawable/ic_play_pause_stop.xml b/res/drawable/ic_play_pause_stop.xml deleted file mode 100644 index 937a5fc7..00000000 --- a/res/drawable/ic_play_pause_stop.xml +++ /dev/null @@ -1,42 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright 2016, 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. ---> -<selector - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:gearhead="http://schemas.android.com/apk/res-auto" > - <item - gearhead:state_playing_to_pause="true" - android:drawable="@drawable/ic_pause" /> - <item - gearhead:state_playing_to_stop="true" - android:drawable="@drawable/ic_stop" /> - <item - gearhead:state_paused="true" - android:drawable="@drawable/ic_play_arrow" /> - <item - gearhead:state_buffering_to_pause="true" - android:drawable="@drawable/ic_pause" /> - <item - gearhead:state_buffering_to_stop="true" - android:drawable="@drawable/ic_stop" /> - <item - gearhead:state_stopped="true" - android:drawable="@drawable/ic_play_arrow" /> - <item - gearhead:state_disabled="true" - android:drawable="@drawable/ic_play_arrow_off" /> - <item android:drawable="@drawable/ic_play_arrow" /> -</selector> diff --git a/res/drawable/ic_skip_next.xml b/res/drawable/ic_skip_next.xml deleted file mode 100644 index 5ac0d548..00000000 --- a/res/drawable/ic_skip_next.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="56dp" - android:height="56dp" - android:viewportWidth="24" - android:viewportHeight="24"> - - <path - android:fillColor="#000000" - android:pathData="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z" /> - <path - android:pathData="M0 0h24v24H0z" /> -</vector> diff --git a/res/drawable/ic_skip_previous.xml b/res/drawable/ic_skip_previous.xml deleted file mode 100644 index f943f888..00000000 --- a/res/drawable/ic_skip_previous.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="56dp" - android:height="56dp" - android:viewportWidth="24" - android:viewportHeight="24"> - - <path - android:fillColor="#000000" - android:pathData="M6 6h2v12H6zm3.5 6l8.5 6V6z" /> - <path - android:pathData="M0 0h24v24H0z" /> -</vector> diff --git a/res/drawable/ic_stop.xml b/res/drawable/ic_stop.xml deleted file mode 100644 index ae018446..00000000 --- a/res/drawable/ic_stop.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="56dp" - android:height="56dp" - android:viewportWidth="48" - android:viewportHeight="48"> - - <path - android:pathData="M0 0h48v48H0z" /> - <path - android:fillColor="#000000" - android:pathData="M12 12h24v24H12z" /> -</vector> diff --git a/res/drawable/seekbar_background.xml b/res/drawable/seekbar_background.xml index bdb03aae..b66f6eec 100644 --- a/res/drawable/seekbar_background.xml +++ b/res/drawable/seekbar_background.xml @@ -17,16 +17,10 @@ <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@android:id/background" - android:drawable="@android:color/transparent" /> - - <item android:id="@android:id/secondaryProgress"> - <scale android:scaleWidth="100%" - android:drawable="@android:color/transparent" /> - </item> + android:drawable="@color/progress_bar_background" /> <item android:id="@android:id/progress"> - <scale android:scaleWidth="100%" - android:drawable="@drawable/progressbar" /> + <clip android:drawable="@color/progress_bar_highlight" /> </item> </layer-list> diff --git a/res/drawable/seekbar_thumb.xml b/res/drawable/seekbar_thumb.xml new file mode 100644 index 00000000..d7dea4fb --- /dev/null +++ b/res/drawable/seekbar_thumb.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <!-- Transparent thumb, used to leave a gap between the two segments of the progress bar --> + <solid android:color="@android:color/transparent"/> + <size + android:width="@dimen/playback_seekbar_thumb_width" + android:height="@dimen/playback_seekbar_height"/> +</shape>
\ No newline at end of file diff --git a/res/layout/fragment_playback.xml b/res/layout/fragment_playback.xml index f3a3ee28..59f34bc2 100644 --- a/res/layout/fragment_playback.xml +++ b/res/layout/fragment_playback.xml @@ -22,31 +22,47 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - <android.support.v4.widget.Space - android:id="@+id/app_bar_space" - android:layout_width="match_parent" - android:layout_height="@dimen/car_app_bar_height" - app:layout_constraintTop_toTopOf="parent"/> - - <FrameLayout + <LinearLayout android:id="@+id/metadata_container" + android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" - android:fitsSystemWindows="true" + android:paddingTop="@dimen/car_padding_4" + android:paddingBottom="@dimen/car_padding_4" android:layout_marginLeft="@dimen/car_margin" android:layout_marginRight="@dimen/car_margin" - app:layout_constraintTop_toBottomOf="@+id/app_bar_space"> + android:gravity="center_vertical" + app:layout_constraintTop_toTopOf="parent"> + + <ImageView + android:id="@+id/album_art" + android:contentDescription="@string/album_art" + android:layout_marginStart="@dimen/car_keyline_1" + android:layout_marginEnd="@dimen/car_keyline_1" + android:layout_width="@dimen/playback_album_art_height" + android:layout_height="@dimen/playback_album_art_width" + android:scaleType="centerCrop" + android:transitionName="@string/album_art"/> - <include layout="@layout/view_metadata"/> + <com.android.car.media.widgets.MetadataView + android:id="@+id/metadata" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/car_keyline_1" + android:layout_weight="1" + android:focusable="false" + app:style="normal"/> - </FrameLayout> + </LinearLayout> <androidx.car.widget.PagedListView android:id="@+id/queue_list" android:layout_width="match_parent" android:layout_height="0dp" android:layout_marginBottom="@dimen/car_padding_4" - app:showPagedListViewDivider="false" + app:listDividerColor="@color/car_list_divider_inverse" + app:dividerStartMargin="@dimen/car_keyline_1" + app:dividerEndMargin="@dimen/car_keyline_1" app:layout_behavior="@string/appbar_scrolling_view_behavior" app:layout_constraintTop_toBottomOf="@+id/metadata_container" app:layout_constraintBottom_toTopOf="@+id/playback_controls"/> diff --git a/res/layout/media_activity.xml b/res/layout/media_activity.xml index e92308d1..73d7cf32 100644 --- a/res/layout/media_activity.xml +++ b/res/layout/media_activity.xml @@ -46,6 +46,7 @@ android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="@dimen/browse_tab_height" + android:layout_marginTop="@dimen/car_padding_4" app:tabIndicatorHeight="0dp" app:tabGravity="fill" app:tabMode="fixed" @@ -57,7 +58,34 @@ android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="0dp" + android:layout_marginTop="@dimen/car_padding_4" app:layout_constraintTop_toBottomOf="@+id/tabs" - app:layout_constraintBottom_toBottomOf="parent"/> + app:layout_constraintBottom_toTopOf="@+id/browse_controls_container"/> + <LinearLayout + android:id="@+id/browse_controls_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:padding="@dimen/car_padding_4" + android:background="@color/browse_playback_bg" + android:orientation="horizontal" + android:gravity="center_vertical" + app:layout_constraintBottom_toBottomOf="parent"> + + <com.android.car.media.common.PlaybackControls + android:id="@+id/controls" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="0.5" + android:layout_marginRight="@dimen/car_padding_4" + app:columns="3"/> + + <com.android.car.media.widgets.MetadataView + android:id="@+id/metadata" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="0.5" + app:style="compact"/> + + </LinearLayout> </android.support.constraint.ConstraintLayout> diff --git a/res/layout/media_controls.xml b/res/layout/media_controls.xml deleted file mode 100644 index 93bc8287..00000000 --- a/res/layout/media_controls.xml +++ /dev/null @@ -1,166 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2016 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. ---> -<android.support.v7.widget.CardView - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - android:id="@+id/music_panel" - android:layout_width="match_parent" - android:layout_height="@dimen/car_action_bar_height" - android:elevation="@dimen/music_panel_elevation" - android:layout_gravity="bottom" - android:visibility="gone" - app:cardCornerRadius="@dimen/car_radius_1" > - <LinearLayout - android:id="@+id/controls" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="horizontal" - android:background="@color/car_card" - android:gravity="center" > - <ImageButton - android:id="@+id/play_queue" - android:visibility="invisible" - android:layout_width="@dimen/controls_tap_target_width" - android:layout_height="@dimen/controls_tap_target_height" - android:layout_marginLeft="@dimen/controls_margin" - android:background="@drawable/music_action_background" - android:tint="@color/car_tint" /> - <Space - android:layout_width="@dimen/controls_spacing_outer" - android:layout_height="match_parent" /> - <ImageButton - android:id="@+id/prev" - android:visibility="invisible" - android:layout_width="@dimen/controls_tap_target_width" - android:layout_height="@dimen/controls_tap_target_height" - android:background="@drawable/music_action_background" - android:tint="@color/car_tint"/> - <Space - android:layout_width="@dimen/controls_spacing_inner" - android:layout_height="match_parent"/> - <FrameLayout - android:id="@+id/play_pause_container" - android:layout_width="wrap_content" - android:layout_height="wrap_content"> - <com.android.car.media.util.widgets.PlayPauseStopImageView - android:id="@+id/play_pause" - android:layout_width="@dimen/stream_fab_size" - android:layout_height="@dimen/stream_fab_size" - android:layout_gravity="center" - android:scaleType="centerInside" - android:src="@drawable/ic_play_pause_stop" - android:focusable="true" - android:elevation="@dimen/play_pause_elevation" - android:stateListAnimator="@anim/car_fab_state_list_animator" /> - <ProgressBar - android:id="@+id/spinner" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:padding="9dp" - android:indeterminateDrawable="@drawable/music_buffering" - android:visibility="gone" /> - </FrameLayout> - <Space - android:layout_width="@dimen/controls_spacing_inner" - android:layout_height="match_parent"/> - <ImageButton - android:id="@+id/next" - android:visibility="invisible" - android:layout_width="@dimen/controls_tap_target_width" - android:layout_height="@dimen/controls_tap_target_height" - android:background="@drawable/music_action_background" - android:tint="@color/car_tint" /> - <Space - android:layout_width="@dimen/controls_spacing_outer" - android:layout_height="match_parent" /> - <ImageButton - android:id="@+id/overflow_on" - android:visibility="invisible" - android:layout_width="@dimen/controls_tap_target_width" - android:layout_height="@dimen/controls_tap_target_height" - android:layout_marginRight="@dimen/controls_margin" - android:background="@drawable/music_action_background" - android:tint="@color/car_tint" /> - </LinearLayout> - <LinearLayout - android:id="@+id/overflow_items" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="horizontal" - android:background="@color/car_card" - android:gravity="center" - android:visibility="gone" - android:alpha="0.0" > - <ImageButton - android:id="@+id/custom_action_1" - android:visibility="invisible" - android:layout_width="@dimen/controls_tap_target_width" - android:layout_height="@dimen/controls_tap_target_height" - android:layout_marginLeft="@dimen/overflow_margin" - android:background="@drawable/music_overflow_action_background" - android:tint="@color/car_tint_light" /> - <Space - android:layout_width="@dimen/overflow_spacing_outer" - android:layout_height="match_parent" /> - <ImageButton - android:id="@+id/custom_action_2" - android:visibility="invisible" - android:layout_width="@dimen/controls_tap_target_width" - android:layout_height="@dimen/controls_tap_target_height" - android:background="@drawable/music_overflow_action_background" - android:tint="@color/car_tint_light" /> - <Space - android:layout_width="@dimen/overflow_spacing_inner" - android:layout_height="match_parent" /> - <ImageButton - android:id="@+id/custom_action_3" - android:visibility="invisible" - android:layout_width="@dimen/controls_tap_target_width" - android:layout_height="@dimen/controls_tap_target_height" - android:background="@drawable/music_overflow_action_background" - android:tint="@color/car_tint_light" /> - <Space - android:layout_width="@dimen/overflow_spacing_inner" - android:layout_height="match_parent" /> - <ImageButton - android:id="@+id/custom_action_4" - android:visibility="invisible" - android:layout_width="@dimen/controls_tap_target_width" - android:layout_height="@dimen/controls_tap_target_height" - android:background="@drawable/music_overflow_action_background" - android:tint="@color/car_tint_light" /> - <Space - android:layout_width="@dimen/overflow_spacing_outer" - android:layout_height="match_parent" /> - <ImageButton - android:id="@+id/overflow_off" - android:layout_width="@dimen/controls_tap_target_width" - android:layout_height="@dimen/controls_tap_target_height" - android:layout_marginRight="@dimen/overflow_margin" - android:background="@drawable/music_overflow_action_background" - android:tint="@color/car_tint_light" /> - </LinearLayout> - <SeekBar - android:id="@+id/seek_bar" - android:layout_width="match_parent" - android:layout_height="@dimen/seek_bar_height" - android:layout_gravity="top" - android:focusable="false" - android:paddingStart="0dp" - android:paddingEnd="0dp" - android:progressDrawable="@drawable/seekbar_background" - android:thumb="@null" /> -</android.support.v7.widget.CardView> diff --git a/res/layout/metadata_compact.xml b/res/layout/metadata_compact.xml new file mode 100644 index 00000000..3d772a18 --- /dev/null +++ b/res/layout/metadata_compact.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2018, 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. +--> +<merge + xmlns:android="http://schemas.android.com/apk/res/android" > + + <TextView + android:id="@+id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/car_padding_1" + android:textAppearance="@style/TextAppearance.Car.Body1.Light" + android:maxLines="1" + android:ellipsize="end" + android:includeFontPadding="false"/> + <TextView + android:id="@+id/subtitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@+id/title" + android:layout_marginBottom="@dimen/car_padding_1" + android:textAppearance="@style/TextAppearance.Car.Body2.Light" + android:maxLines="1" + android:ellipsize="end" + android:includeFontPadding="false"/> + <SeekBar + android:id="@+id/seek_bar" + android:layout_width="match_parent" + android:layout_height="@dimen/playback_seekbar_height" + android:layout_below="@+id/subtitle" + android:paddingStart="0dp" + android:paddingEnd="0dp" + android:visibility="invisible" + android:progressDrawable="@drawable/seekbar_background" + android:thumb="@drawable/seekbar_thumb"/> + +</merge>
\ No newline at end of file diff --git a/res/layout/metadata_normal.xml b/res/layout/metadata_normal.xml new file mode 100644 index 00000000..cdb63c48 --- /dev/null +++ b/res/layout/metadata_normal.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2018, 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. +--> +<merge + xmlns:android="http://schemas.android.com/apk/res/android" > + + <TextView + android:id="@+id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/car_padding_1" + android:textAppearance="@style/TextAppearance.Car.Body1.Light" + android:maxLines="@integer/playback_title_text_max_lines" + android:ellipsize="end" + android:includeFontPadding="false"/> + <TextView + android:id="@+id/subtitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@+id/title" + android:layout_marginBottom="@dimen/car_padding_4" + android:textAppearance="@style/TextAppearance.Car.Body2.Light" + android:maxLines="@integer/playback_subtitle_text_max_lines" + android:ellipsize="end" + android:includeFontPadding="false"/> + <TextView + android:id="@+id/time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentEnd="true" + android:layout_below="@+id/title" + android:textAppearance="@style/TextAppearance.Car.Body2.Light" + android:maxLines="1" + android:ellipsize="end" + android:includeFontPadding="false"/> + <SeekBar + android:id="@+id/seek_bar" + android:layout_width="match_parent" + android:layout_height="@dimen/playback_seekbar_height" + android:layout_below="@+id/subtitle" + android:paddingStart="0dp" + android:paddingEnd="0dp" + android:visibility="invisible" + android:progressDrawable="@drawable/seekbar_background" + android:thumb="@drawable/seekbar_thumb"/> + +</merge>
\ No newline at end of file diff --git a/res/layout/tab_view.xml b/res/layout/tab_view.xml index 68fef69a..0abc1287 100644 --- a/res/layout/tab_view.xml +++ b/res/layout/tab_view.xml @@ -21,19 +21,19 @@ android:id="@+id/icon" android:layout_width="@dimen/car_primary_icon_size" android:layout_height="@dimen/car_primary_icon_size" + android:layout_marginBottom="@dimen/car_padding_0" android:scaleType="fitCenter" android:layout_gravity="center_horizontal" - android:tint="@color/car_tint_inverse" - android:layout_marginTop="@dimen/car_padding_2"/> + android:tint="@color/car_tint_inverse"/> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" - android:layout_marginBottom="@dimen/car_padding_1" android:maxLines="1" android:ellipsize="end" + android:includeFontPadding="false" android:textAppearance="@style/TextAppearance.Car.Body5.Light"/> </merge>
\ No newline at end of file diff --git a/res/layout/view_metadata.xml b/res/layout/view_metadata.xml deleted file mode 100644 index 3b4341dc..00000000 --- a/res/layout/view_metadata.xml +++ /dev/null @@ -1,88 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright 2018, 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. ---> -<LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/metadata" - android:orientation="horizontal" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="@dimen/car_keyline_2" - android:layout_marginBottom="@dimen/car_keyline_2" - android:gravity="center" - android:layout_centerVertical="true"> - - <ImageView - android:id="@+id/album_art" - android:contentDescription="@string/album_art" - android:layout_marginStart="@dimen/car_keyline_1" - android:layout_marginEnd="@dimen/car_keyline_1" - android:layout_width="@dimen/playback_album_art_height" - android:layout_height="@dimen/playback_album_art_width" - android:scaleType="centerCrop" - android:transitionName="@string/album_art"/> - - <RelativeLayout - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginEnd="@dimen/car_keyline_1" - android:layout_weight="1" - android:focusable="false"> - - <TextView - android:id="@+id/title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/car_padding_1" - android:textAppearance="@style/TextAppearance.Car.Body1.Light" - android:maxLines="@integer/playback_title_text_max_lines" - android:ellipsize="end" - android:includeFontPadding="false"/> - <TextView - android:id="@+id/subtitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_below="@+id/title" - android:layout_marginBottom="@dimen/car_padding_2" - android:textAppearance="@style/TextAppearance.Car.Body2.Light" - android:maxLines="@integer/playback_subtitle_text_max_lines" - android:ellipsize="end" - android:includeFontPadding="false"/> - <TextView - android:id="@+id/time" - android:text="3:27 / 4:03" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentEnd="true" - android:layout_below="@+id/title" - android:textAppearance="@style/TextAppearance.Car.Body2.Light" - android:maxLines="@integer/playback_subtitle_text_max_lines" - android:ellipsize="end" - android:includeFontPadding="false"/> - <SeekBar - android:id="@+id/seek_bar" - android:layout_width="match_parent" - android:layout_height="@dimen/playback_seekbar_height" - android:layout_below="@+id/subtitle" - android:paddingStart="0dp" - android:paddingEnd="0dp" - android:visibility="invisible" - android:progressDrawable="@drawable/seekbar_background" - android:background="@color/car_grey_900" - android:thumb="@null"/> - - </RelativeLayout> -</LinearLayout> diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 857d8f4a..f77c9ced 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Copyright 2016, The Android Open Source Project + Copyright 2018, 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. @@ -15,66 +15,13 @@ limitations under the License. --> <resources> - <declare-styleable name="ImageButtonWithAlphaFade"> - <!-- Fade duration in ms --> - <attr name="fadeDuration" format="integer" /> - <attr name="alphaNormal" format="float" /> - <attr name="alphaSelected" format="float" /> - <attr name="fadeColor" format="integer" /> - </declare-styleable> - - <declare-styleable name="BrowseItemView"> - <attr name="detailAnimation" format="reference" /> - </declare-styleable> - - <declare-styleable name="PlayingState"> - <attr name="state_paused" format="boolean"/> - <attr name="state_playing_to_pause" format="boolean"/> - <attr name="state_playing_to_stop" format="boolean"/> - <attr name="state_buffering_to_pause" format="boolean"/> - <attr name="state_buffering_to_stop" format="boolean"/> - <attr name="state_stopped" format="boolean"/> - <attr name="state_disabled" format="boolean"/> - </declare-styleable> - - <!-- IME stuff --> - <!-- Modified KeyboardView --> - <declare-styleable name="KeyboardView"> - <attr name="keyBackground" format="reference"/> - <attr name="keyTextSize" format="dimension"/> - <attr name="keyTextColorPrimary" format="color"/> - <attr name="keyTextColorSecondary" format="color"/> - <attr name="labelTextSize" format="dimension"/> - <attr name="fontFamily" format="string" /> - <attr name="textStyle" format="enum"> - <enum name="normal" value="0" /> - <enum name="bold" value="1" /> - <enum name="italic" value="2" /> - <enum name="bold_italic" value="3" /> + <declare-styleable name="MetadataView"> + <!-- Style of media item metadata view --> + <attr name="style" format="enum"> + <!-- Compact version (to be included in the bottom bar during browsing --> + <enum name="compact" value="0"/> + <!-- Normal version (to be included in the playback screen --> + <enum name="normal" value="1"/> </attr> </declare-styleable> - - <declare-styleable name="RotaryKeyboardLayout"> - <attr name="selectedKeyTextColor" format="color" /> - <attr name="selectedKeyTextSize" format="dimension" /> - <attr name="selectedCircleColor" format="dimension" /> - <attr name="selectedCircleRadius" format="dimension" /> - <attr name="clickedCircleRadius" format="dimension" /> - <attr name="movedCircleRadius" format="dimension" /> - <attr name="ringKeySpacing" format="dimension" /> - <attr name="ringKeyTextColor" format="color" /> - <attr name="ringKeyTextSize" format="dimension" /> - <attr name="selectedKeyMargin" format="dimension" /> - <attr name="selectedKeygroupTextSize" format="dimension" /> - <attr name="keyGroupTextSize" format="dimension" /> - <attr name="keyGroupCircleRadius" format="dimension" /> - <attr name="keyGroupCircleColor" format="color" /> - <attr name="keyGroupSpacing" format="dimension" /> - </declare-styleable> - - <declare-styleable name="PageIndicator"> - <attr name="dotPadding" format="dimension" /> - <attr name="inactiveDotSrc" format="reference" /> - <attr name="activeDotSrc" format="reference" /> - </declare-styleable> </resources> diff --git a/res/values/colors.xml b/res/values/colors.xml index 30f7d003..a3c9bd91 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -27,4 +27,8 @@ <color name="media_template_background">@color/car_dark_blue_grey_800</color> <!-- Scrim displayed on top of playback album art background --> <color name="media_scrim_background">@color/car_dark_blue_grey_900</color> + <!-- Color used on the progress bar background --> + <color name="progress_bar_background">@color/car_grey_900</color> + <!-- Color used on the progress bar --> + <color name="progress_bar_highlight">#fafafa</color> </resources> diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 254ebd54..6144b7ba 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -35,6 +35,8 @@ <!-- Playback seekbar height --> <dimen name="playback_seekbar_height">8dp</dimen> + <!-- Size of the thumb in the playback seekbar --> + <dimen name="playback_seekbar_thumb_width">6dp</dimen> <!-- Height of the gradient scrim over the background image --> <dimen name="playback_scrim_transition_height">256dp</dimen> <!-- Image size used to generate the background --> @@ -44,11 +46,13 @@ <!-- Scale to apply to images before blurring them to create the playback background --> <item name="playback_background_blur_scale" format="float" type="dimen">1</item> <!-- Size of the album art thumbnail --> - <dimen name="playback_album_art_height">190dp</dimen> - <dimen name="playback_album_art_width">200dp</dimen> + <dimen name="playback_album_art_height">156dp</dimen> + <dimen name="playback_album_art_width">156dp</dimen> <!-- Tab height --> - <dimen name="browse_tab_height">100dp</dimen> + <dimen name="browse_tab_height">76dp</dimen> <!-- Tab max width --> <dimen name="browse_tab_width">92dp</dimen> + <!-- Browse playback controls size --> + <dimen name="browse_playback_controls_height">192dp</dimen> </resources> diff --git a/src/com/android/car/media/BrowseFragment.java b/src/com/android/car/media/BrowseFragment.java index 64c5eaa5..3c56c0e7 100644 --- a/src/com/android/car/media/BrowseFragment.java +++ b/src/com/android/car/media/BrowseFragment.java @@ -273,4 +273,4 @@ public class BrowseFragment extends Fragment { return mBrowseStack.lastElement(); } } -}
\ No newline at end of file +} diff --git a/src/com/android/car/media/CarClientServiceAdapter.java b/src/com/android/car/media/CarClientServiceAdapter.java deleted file mode 100644 index ae2c0afb..00000000 --- a/src/com/android/car/media/CarClientServiceAdapter.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2016 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.car.media; - -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import java.util.List; - -/** - * A Media Manager adapter which uses the car api client to query for allowed media services. - * - * @deprecated This adapter will be removed as we are not sharing this code with the projected - * team. - */ -@Deprecated -public class CarClientServiceAdapter implements MediaManager.ServiceAdapter { - private PackageManager mPackageManager; - - public CarClientServiceAdapter(PackageManager packageManager) { - mPackageManager = packageManager; - } - - @Override - public List<ResolveInfo> queryAllowedServices(Intent providerIntent) { - return mPackageManager.queryIntentServices(providerIntent, 0); - } -} diff --git a/src/com/android/car/media/MediaActivity.java b/src/com/android/car/media/MediaActivity.java index 9723d4de..3ac5396c 100644 --- a/src/com/android/car/media/MediaActivity.java +++ b/src/com/android/car/media/MediaActivity.java @@ -26,13 +26,16 @@ import android.support.v4.app.FragmentManager; import android.util.Log; import android.util.TypedValue; import android.view.View; +import android.view.ViewGroup; import com.android.car.media.common.CrossfadeImageView; import com.android.car.media.common.MediaItemMetadata; import com.android.car.media.common.MediaSource; +import com.android.car.media.common.PlaybackControls; import com.android.car.media.common.PlaybackModel; import com.android.car.media.drawer.MediaDrawerController; -import com.android.car.media.util.widgets.MediaItemTabView; +import com.android.car.media.widgets.MediaItemTabView; +import com.android.car.media.widgets.MetadataView; import java.util.ArrayList; import java.util.List; @@ -70,6 +73,10 @@ public class MediaActivity extends CarDrawerActivity implements BrowseFragment.C private PlaybackFragment mPlaybackFragment; private AppBarLayout mAppBarLayout; private View mBrowseScrim; + private PlaybackControls mPlaybackControls; + private MetadataView mMetadataView; + private ViewGroup mBrowseControlsContainer; + /** Current state */ private MediaItemMetadata mCurrentMetadata; @@ -106,6 +113,7 @@ public class MediaActivity extends CarDrawerActivity implements BrowseFragment.C new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { + Log.i(TAG, "onTabSelected: " + tab.getTag()); mMode = Mode.BROWSING; updateBrowseFragment((MediaItemMetadata) tab.getTag()); updateMetadata(); @@ -118,6 +126,7 @@ public class MediaActivity extends CarDrawerActivity implements BrowseFragment.C @Override public void onTabReselected(TabLayout.Tab tab) { + Log.i(TAG, "onTabReselected: " + tab.getTag()); mMode = Mode.BROWSING; updateBrowseFragment((MediaItemMetadata) tab.getTag()); updateMetadata(); @@ -151,6 +160,12 @@ public class MediaActivity extends CarDrawerActivity implements BrowseFragment.C mAppBarLayout = findViewById(androidx.car.R.id.appbar); mAlbumBackground = findViewById(R.id.media_background); mBrowseScrim = findViewById(R.id.browse_scrim); + mPlaybackControls = findViewById(R.id.controls); + mPlaybackControls.setModel(mPlaybackModel); + mMetadataView = findViewById(R.id.metadata); + mMetadataView.setModel(mPlaybackModel); + mBrowseControlsContainer = findViewById(R.id.browse_controls_container); + mBrowseControlsContainer.setOnClickListener(view -> switchToMode(Mode.PLAYBACK)); TypedValue outValue = new TypedValue(); getResources().getValue(R.dimen.playback_background_blur_radius, outValue, true); mBackgroundBlurRadius = outValue.getFloat(); @@ -174,6 +189,8 @@ public class MediaActivity extends CarDrawerActivity implements BrowseFragment.C public void onDestroy() { super.onDestroy(); mDrawerController.cleanup(); + mPlaybackControls.setModel(null); + mMetadataView.setModel(null); } @Override @@ -202,7 +219,7 @@ public class MediaActivity extends CarDrawerActivity implements BrowseFragment.C @Override protected void onResumeFragments() { super.onResumeFragments(); - updateBrowseSource(); + handleIntent(); } private void onBrowseConnected(boolean success) { @@ -215,10 +232,10 @@ public class MediaActivity extends CarDrawerActivity implements BrowseFragment.C } private void handleIntent() { - updateBrowseSource(); switchToMode(getRequestedMediaPackageName() == null || !mContentForwardBrowseEnabled ? Mode.PLAYBACK : Mode.BROWSING); + updateBrowseSource(); } /** @@ -297,6 +314,8 @@ public class MediaActivity extends CarDrawerActivity implements BrowseFragment.C && browsableTopLevel.size() <= mMaxBrowserTabs)) { mAppBarLayout.setVisibility(View.GONE); mTabLayout.setVisibility(View.VISIBLE); + // Temporarily removing the listener, to prevent initial tab selection event. + mTabLayout.removeOnTabSelectedListener(mTabSelectedListener); int count = 0; for (MediaItemMetadata item : browsableTopLevel) { MediaItemTabView tab = new MediaItemTabView(this, item); @@ -306,6 +325,7 @@ public class MediaActivity extends CarDrawerActivity implements BrowseFragment.C break; } } + mTabLayout.addOnTabSelectedListener(mTabSelectedListener); updateBrowseFragment(browsableTopLevel.get(0)); } else { mAppBarLayout.setVisibility(View.VISIBLE); @@ -315,17 +335,13 @@ public class MediaActivity extends CarDrawerActivity implements BrowseFragment.C } private void switchToMode(Mode mode) { + Log.i(TAG, "Switch mode to " + mode + " (intent package: " + + getRequestedMediaPackageName() + ")"); mMode = mode; - switch(mode) { - case PLAYBACK: - showFragment(mPlaybackFragment); - break; - case BROWSING: - // Browse fragment will be loaded once we have the top level items. - showFragment(null); - updateMetadata(); - break; - } + updateMetadata(); + showFragment(mode == Mode.PLAYBACK + ? mPlaybackFragment + : null); // Browse fragment will be loaded once we have the top level items. } private void updateBrowseFragment(MediaItemMetadata topItem) { @@ -340,9 +356,12 @@ public class MediaActivity extends CarDrawerActivity implements BrowseFragment.C private void updateMetadata() { if (isCurrentMediaSourcePlaying()) { mAlbumBackground.setVisibility(View.VISIBLE); - mBrowseScrim.setVisibility(mCurrentFragment == mPlaybackFragment + mBrowseScrim.setVisibility(mMode == Mode.PLAYBACK + ? View.GONE + : View.VISIBLE); + mBrowseControlsContainer.setVisibility(mMode == Mode.PLAYBACK ? View.GONE - : View. VISIBLE); + : View.VISIBLE); MediaItemMetadata metadata = mPlaybackModel.getMetadata(); if (Objects.equals(mCurrentMetadata, metadata)) { return; @@ -359,8 +378,9 @@ public class MediaActivity extends CarDrawerActivity implements BrowseFragment.C mAlbumBackground.setImageBitmap(null, true); } } else { - mAlbumBackground.setVisibility(View.GONE); + mAlbumBackground.setVisibility(View.INVISIBLE); mBrowseScrim.setVisibility(View.GONE); + mBrowseControlsContainer.setVisibility(View.GONE); } } diff --git a/src/com/android/car/media/PlaybackFragment.java b/src/com/android/car/media/PlaybackFragment.java index c5772a57..42c28250 100644 --- a/src/com/android/car/media/PlaybackFragment.java +++ b/src/com/android/car/media/PlaybackFragment.java @@ -17,33 +17,22 @@ package com.android.car.media; import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.PorterDuff; import android.os.Bundle; -import android.os.Handler; import android.support.v4.app.Fragment; -import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; -import android.util.Log; -import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; -import android.widget.SeekBar; -import android.widget.TextView; -import com.android.car.media.browse.BrowseAdapter; -import com.android.car.media.browse.ContentForwardStrategy; -import com.android.car.media.common.GridSpacingItemDecoration; import com.android.car.media.common.MediaItemMetadata; import com.android.car.media.common.MediaSource; import com.android.car.media.common.PlaybackControls; import com.android.car.media.common.PlaybackModel; +import com.android.car.media.widgets.MetadataView; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Objects; @@ -66,10 +55,7 @@ public class PlaybackFragment extends Fragment { private PlaybackModel mModel; private PlaybackControls mPlaybackControls; private ImageView mAlbumArt; - private TextView mTitle; - private TextView mTime; - private TextView mSubtitle; - private SeekBar mSeekbar; + private MetadataView mMetadataView; private PagedListView mQueueList; private QueueItemsAdapter mQueueAdapter; private MediaItemMetadata mCurrentMetadata; @@ -138,10 +124,7 @@ public class PlaybackFragment extends Fragment { ViewGroup playbackContainer = view.findViewById(R.id.playback_container); mPlaybackControls.setAnimationViewGroup(playbackContainer); mAlbumArt = view.findViewById(R.id.album_art); - mTitle = view.findViewById(R.id.title); - mSubtitle = view.findViewById(R.id.subtitle); - mSeekbar = view.findViewById(R.id.seek_bar); - mTime = view.findViewById(R.id.time); + mMetadataView = view.findViewById(R.id.metadata); mQueueList = view.findViewById(R.id.queue_list); RecyclerView recyclerView = mQueueList.getRecyclerView(); recyclerView.setVerticalFadingEdgeEnabled(true); @@ -157,24 +140,18 @@ public class PlaybackFragment extends Fragment { public void onStart() { super.onStart(); mModel.registerObserver(mPlaybackObserver); + mMetadataView.setModel(mModel); } @Override public void onStop() { super.onStop(); mModel.unregisterObserver(mPlaybackObserver); + mMetadataView.setModel(null); mCurrentMetadata = null; } private void updateState() { - updateProgress(); - - if (mModel.isPlaying()) { - mSeekbar.post(mSeekBarRunnable); - } else { - mSeekbar.removeCallbacks(mSeekBarRunnable); - } - mQueueAdapter.refresh(); } @@ -184,8 +161,6 @@ public class PlaybackFragment extends Fragment { return; } mCurrentMetadata = metadata; - mTitle.setText(metadata != null ? metadata.getTitle() : null); - mSubtitle.setText(metadata != null ? metadata.getSubtitle() : null); MediaItemMetadata.updateImageView(getContext(), metadata, mAlbumArt, 0); } @@ -193,34 +168,7 @@ public class PlaybackFragment extends Fragment { int defaultColor = getResources().getColor(android.R.color.background_dark, null); MediaSource mediaSource = mModel.getMediaSource(); int color = mediaSource == null ? defaultColor : mediaSource.getAccentColor(defaultColor); - mSeekbar.getProgressDrawable().setColorFilter(color, PorterDuff.Mode.SRC_IN); - } - - private static final long SEEK_BAR_UPDATE_TIME_INTERVAL_MS = 500; - - private final Runnable mSeekBarRunnable = new Runnable() { - @Override - public void run() { - if (!mModel.isPlaying()) { - return; - } - updateProgress(); - mSeekbar.postDelayed(this, SEEK_BAR_UPDATE_TIME_INTERVAL_MS); - - } - }; - - private void updateProgress() { - long maxProgress = mModel.getMaxProgress(); - int visibility = maxProgress > 0 ? View.VISIBLE : View.INVISIBLE; - String time = String.format("%s / %s", - TIME_FORMAT.format(new Date(mModel.getProgress())), - TIME_FORMAT.format(new Date(maxProgress))); - mTime.setVisibility(visibility); - mTime.setText(time); - mSeekbar.setVisibility(visibility); - mSeekbar.setMax((int) mModel.getMaxProgress()); - mSeekbar.setProgress((int) mModel.getProgress()); + // TODO: Update queue color } private void onQueueItemClicked(MediaItemMetadata item) { diff --git a/src/com/android/car/media/drawer/MediaDrawerController.java b/src/com/android/car/media/drawer/MediaDrawerController.java index 06b20685..077cd740 100644 --- a/src/com/android/car/media/drawer/MediaDrawerController.java +++ b/src/com/android/car/media/drawer/MediaDrawerController.java @@ -149,7 +149,7 @@ public class MediaDrawerController implements MediaDrawerAdapter.MediaFetchCallb mDrawerController.removeDrawerListener(mQueueDrawerListener); mRootAdapter.cleanup(); mMediaPlaybackModel.removeListener(mModelListener); - mMediaPlaybackModel.stop(); + mMediaPlaybackModel.stop(); } /** diff --git a/src/com/android/car/media/util/widgets/PlayPauseStopImageView.java b/src/com/android/car/media/util/widgets/PlayPauseStopImageView.java deleted file mode 100644 index 7289bbc3..00000000 --- a/src/com/android/car/media/util/widgets/PlayPauseStopImageView.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2016 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.car.media.util.widgets; - -import android.content.Context; -import android.graphics.PorterDuff; -import android.media.session.PlaybackState; -import android.support.annotation.IntDef; -import android.util.AttributeSet; -import android.util.Log; -import android.widget.ImageView; -import com.android.car.media.R; - -import com.android.car.apps.common.ColorChecker; -import com.android.car.apps.common.FabDrawable; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Custom {@link android.widget.ImageButton} that has three custom states: - * state_playing - * state_paused - * state_buffering - * state_stopped - */ -public class PlayPauseStopImageView extends ImageView { - private static final String TAG = "GH.PlayPauseImageView"; - /** - * All existing play states in {@link android.media.session.PlaybackState} are - * positive integers. - */ - public static final int PLAYBACKSTATE_DISABLED = -2; - - @Retention(RetentionPolicy.SOURCE) - @IntDef({MODE_PAUSE, MODE_STOP}) - @interface ActionModes {} - public static final int MODE_PAUSE = 1; - public static final int MODE_STOP = 2; - - private final int[] STATE_PLAYING_TO_PAUSE = {R.attr.state_playing_to_pause}; - private final int[] STATE_PLAYING_TO_STOP = {R.attr.state_playing_to_stop}; - private final int[] STATE_PAUSED = {R.attr.state_paused}; - private final int[] STATE_BUFFERING_TO_PAUSE = {R.attr.state_buffering_to_pause}; - private final int[] STATE_BUFFERING_TO_STOP = {R.attr.state_buffering_to_stop}; - private final int[] STATE_STOPPED = {R.attr.state_stopped}; - private final int[] STATE_DISABLED = {R.attr.state_disabled}; - - private int mPlaybackState = -1; - // Set pause mode as default, so it will show pause icon if the mode flag doesn't change. - private int mMode = MODE_PAUSE; - - public PlayPauseStopImageView(Context context, AttributeSet attrs) { - super(context, attrs); - setBackground(new FabDrawable(context)); - } - - /** - * Sets the current play state to be represented by this Button. - * - * @param playState One of the values returned by {@link PlaybackState#getState()}. - */ - public void setPlayState(int playState) { - mPlaybackState = playState; - } - - public void setMode(@ActionModes int mode) { - mMode = mode; - } - - @Override - public int[] onCreateDrawableState(int extraSpace) { - // + 1 so we can potentially add our custom PlayState - final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); - - switch(mPlaybackState) { - case PlaybackState.STATE_PLAYING: - if (mMode == MODE_STOP) { - mergeDrawableStates(drawableState, STATE_PLAYING_TO_STOP); - } else { - mergeDrawableStates(drawableState, STATE_PLAYING_TO_PAUSE); - } - break; - case PlaybackState.STATE_PAUSED: - mergeDrawableStates(drawableState, STATE_PAUSED); - break; - case PlaybackState.STATE_BUFFERING: - case PlaybackState.STATE_CONNECTING: - case PlaybackState.STATE_FAST_FORWARDING: - case PlaybackState.STATE_REWINDING: - case PlaybackState.STATE_SKIPPING_TO_NEXT: - case PlaybackState.STATE_SKIPPING_TO_PREVIOUS: - if (mMode == MODE_STOP) { - mergeDrawableStates(drawableState, STATE_BUFFERING_TO_STOP); - } else { - mergeDrawableStates(drawableState, STATE_BUFFERING_TO_PAUSE); - } - break; - case PlaybackState.STATE_STOPPED: - mergeDrawableStates(drawableState, STATE_STOPPED); - break; - case PLAYBACKSTATE_DISABLED: - mergeDrawableStates(drawableState, STATE_DISABLED); - break; - default: - Log.e(TAG, "Unknown PlaybackState: " + mPlaybackState); - } - if (getBackground() != null) { - getBackground().setState(drawableState); - } - return drawableState; - } - - public void setPrimaryActionColor(int color) { - ((FabDrawable) getBackground()).setFabAndStrokeColor(color); - if (getDrawable() != null) { - int tintColor = ColorChecker.getTintColor(getContext(), color); - getDrawable().setColorFilter(tintColor, PorterDuff.Mode.SRC_IN); - } - } -} diff --git a/src/com/android/car/media/util/widgets/MediaItemTabView.java b/src/com/android/car/media/widgets/MediaItemTabView.java index 2bcd4d48..c70cdffa 100644 --- a/src/com/android/car/media/util/widgets/MediaItemTabView.java +++ b/src/com/android/car/media/widgets/MediaItemTabView.java @@ -14,10 +14,9 @@ * limitations under the License. */ -package com.android.car.media.util.widgets; +package com.android.car.media.widgets; import android.content.Context; -import android.util.AttributeSet; import android.view.LayoutInflater; import android.widget.ImageView; import android.widget.LinearLayout; diff --git a/src/com/android/car/media/widgets/MetadataView.java b/src/com/android/car/media/widgets/MetadataView.java new file mode 100644 index 00000000..4b3fb38b --- /dev/null +++ b/src/com/android/car/media/widgets/MetadataView.java @@ -0,0 +1,187 @@ +package com.android.car.media.widgets; + +import static java.lang.annotation.RetentionPolicy.SOURCE; + +import android.annotation.IntDef; +import android.annotation.Nullable; +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.RelativeLayout; +import android.widget.SeekBar; +import android.widget.TextView; + +import com.android.car.media.R; +import com.android.car.media.common.MediaItemMetadata; +import com.android.car.media.common.PlaybackModel; + +import java.lang.annotation.Retention; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.Objects; + +/** + * A view that can be used to display the metadata and playback progress of a media item. + * This view can be styled using the "MetadataView" styleable attributes. + */ +public class MetadataView extends RelativeLayout { + private static final DateFormat TIME_FORMAT = new SimpleDateFormat("m:ss", Locale.US); + + @Nullable + private MediaItemMetadata mCurrentMetadata; + private TextView mTitle; + private TextView mTime; + private TextView mSubtitle; + private SeekBar mSeekbar; + @Nullable + private PlaybackModel mModel; + + private PlaybackModel.PlaybackObserver mPlaybackObserver = + new PlaybackModel.PlaybackObserver() { + @Override + public void onPlaybackStateChanged() { + updateState(); + } + + @Override + public void onSourceChanged() { + updateState(); + updateMetadata(); + } + + @Override + public void onMetadataChanged() { + updateMetadata(); + } + }; + + /** + * The possible styles of this widget. + */ + @IntDef({ + MetadataView.Style.COMPACT, + MetadataView.Style.NORMAL + }) + @Retention(SOURCE) + public @interface Style { + /** Compact style (small space between elements, no time progress indicator) */ + int COMPACT = 0; + /** Normal style (normal spacing and progress indicator) */ + int NORMAL = 1; + } + + public MetadataView(Context context) { + super(context); + init(context, null, 0, 0); + } + + public MetadataView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context, attrs, 0, 0); + } + + public MetadataView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs, defStyleAttr, 0); + } + + public MetadataView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(context, attrs, defStyleAttr, defStyleRes); + } + + private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + TypedArray ta = context.obtainStyledAttributes( + attrs, R.styleable.MetadataView, defStyleAttr, defStyleRes); + @Style int style = ta.getInteger(R.styleable.MetadataView_style, Style.NORMAL); + ta.recycle(); + + int layoutId = style == Style.COMPACT + ? R.layout.metadata_compact + : R.layout.metadata_normal; + + LayoutInflater inflater = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + inflater.inflate(layoutId, this, true); + + mTitle = findViewById(R.id.title); + mSubtitle = findViewById(R.id.subtitle); + mSeekbar = findViewById(R.id.seek_bar); + mTime = findViewById(R.id.time); + } + + /** + * Registers the {@link PlaybackModel} this widget will use to follow playback state. + * Consumers of this class must unregister the {@link PlaybackModel} by calling this method with + * null. + * + * @param model {@link PlaybackModel} to subscribe, or null to unsubscribe. + */ + public void setModel(@Nullable PlaybackModel model) { + if (mModel != null) { + mModel.unregisterObserver(mPlaybackObserver); + } + mModel = model; + if (mModel != null) { + mModel.registerObserver(mPlaybackObserver); + } + } + + private void updateState() { + updateProgress(); + + if (mModel != null && mModel.isPlaying()) { + mSeekbar.post(mSeekBarRunnable); + } else { + mSeekbar.removeCallbacks(mSeekBarRunnable); + } + } + + private void updateMetadata() { + MediaItemMetadata metadata = mModel != null ? mModel.getMetadata() : null; + if (Objects.equals(mCurrentMetadata, metadata)) { + return; + } + mCurrentMetadata = metadata; + mTitle.setText(metadata != null ? metadata.getTitle() : null); + mSubtitle.setText(metadata != null ? metadata.getSubtitle() : null); + } + + private static final long SEEK_BAR_UPDATE_TIME_INTERVAL_MS = 1000; + + private final Runnable mSeekBarRunnable = new Runnable() { + @Override + public void run() { + if (mModel == null || !mModel.isPlaying()) { + return; + } + updateProgress(); + mSeekbar.postDelayed(this, SEEK_BAR_UPDATE_TIME_INTERVAL_MS); + + } + }; + + private void updateProgress() { + if (mModel == null) { + mTime.setVisibility(View.INVISIBLE); + mSeekbar.setVisibility(View.INVISIBLE); + return; + } + long maxProgress = mModel.getMaxProgress(); + int visibility = maxProgress > 0 ? View.VISIBLE : View.INVISIBLE; + if (mTime != null) { + String time = String.format("%s / %s", + TIME_FORMAT.format(new Date(mModel.getProgress())), + TIME_FORMAT.format(new Date(maxProgress))); + mTime.setVisibility(visibility); + mTime.setText(time); + } + mSeekbar.setVisibility(visibility); + mSeekbar.setMax((int) mModel.getMaxProgress()); + mSeekbar.setProgress((int) mModel.getProgress()); + } +} |