diff options
author | Peter Li <pyli@google.com> | 2019-05-30 18:11:35 -0700 |
---|---|---|
committer | Peter Li <pyli@google.com> | 2019-05-31 14:14:18 -0700 |
commit | 5970b3de51391c5786a8e26757f1843bbe265f4a (patch) | |
tree | a9097518b9debcd2f641da514497b4e20bbe796e | |
parent | ba1dbeb96efe8ecf6be933a30992e868ff248f52 (diff) | |
download | Cluster-5970b3de51391c5786a8e26757f1843bbe265f4a.tar.gz |
Refactor music facet, use MetadataController
Fix: 131720177
Test: Manual
Change-Id: Ib11a9592990211a18d23a2873419bfedc78e6eb8
-rw-r--r-- | res/layout/fragment_music.xml | 19 | ||||
-rw-r--r-- | res/layout/metadata_normal.xml | 38 | ||||
-rw-r--r-- | res/values/dimens.xml | 5 | ||||
-rw-r--r-- | src/android/car/cluster/MusicFragment.java | 49 | ||||
-rw-r--r-- | src/android/car/cluster/MusicFragmentViewModel.java | 84 |
5 files changed, 70 insertions, 125 deletions
diff --git a/res/layout/fragment_music.xml b/res/layout/fragment_music.xml index f9c72f7..8317253 100644 --- a/res/layout/fragment_music.xml +++ b/res/layout/fragment_music.xml @@ -23,13 +23,6 @@ app:cardElevation="0dp" app:cardCornerRadius="6dp"> - <com.android.car.apps.common.CrossfadeImageView - android:id="@+id/album_background" - android:foreground="?android:attr/selectableItemBackground" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:scaleType="fitStart" /> - <View android:id="@+id/playback_scrim" android:layout_width="match_parent" @@ -46,7 +39,7 @@ <TextView android:id="@+id/app_name" - android:layout_width="0dp" + android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="@dimen/playback_fragment_text_margin_top" android:layout_marginLeft="@dimen/playback_fragment_text_margin_x" @@ -56,7 +49,15 @@ android:maxLines="1" android:includeFontPadding="false" app:layout_constraintLeft_toLeftOf="parent" - app:layout_constraintRight_toRightOf="parent" + app:layout_constraintTop_toTopOf="parent"/> + + <ImageView + android:id="@+id/app_icon" + android:layout_width="@dimen/playback_app_icon_size" + android:layout_height="@dimen/playback_app_icon_size" + android:layout_marginTop="@dimen/playback_fragment_icon_margin_top" + android:layout_marginLeft="@dimen/playback_fragment_icon_margin_x" + app:layout_constraintStart_toEndOf="@+id/app_name" app:layout_constraintTop_toTopOf="parent"/> <androidx.constraintlayout.widget.Guideline diff --git a/res/layout/metadata_normal.xml b/res/layout/metadata_normal.xml index 5cb75a6..ee1de38 100644 --- a/res/layout/metadata_normal.xml +++ b/res/layout/metadata_normal.xml @@ -48,18 +48,38 @@ app:layout_constraintEnd_toStartOf="@+id/time" app:layout_constraintTop_toBottomOf="@+id/title" tools:text="Body 2"/> - <TextView - android:id="@+id/time" - android:layout_width="wrap_content" + <LinearLayout + android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="@dimen/metadata_normal_time_margin_top" - android:ellipsize="end" - android:maxLines="@integer/playback_subtitle_text_max_lines" - android:gravity="end" - android:textAppearance="?android:attr/textAppearanceMedium" + android:orientation="horizontal" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@+id/title" - tools:text="3:27 / 4:03"/> + android:gravity="end" + android:layout_marginTop="@dimen/metadata_normal_time_margin_top"> + + <TextView + android:id="@+id/time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:maxLines="@integer/playback_subtitle_text_max_lines" + android:textAppearance="?android:attr/textAppearanceMedium" + tools:text="3:27"/> + <TextView + android:id="@+id/time_separator" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:maxLines="@integer/playback_subtitle_text_max_lines" + android:textAppearance="?android:attr/textAppearanceMedium" + android:text=" / " + tools:text=" / "/> + <TextView + android:id="@+id/track_length" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:maxLines="@integer/playback_subtitle_text_max_lines" + android:textAppearance="?android:attr/textAppearanceMedium" + tools:text="3:27"/> + </LinearLayout> <SeekBar android:id="@+id/seek_bar" android:layout_width="0dp" diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 21aec67..4fa9e22 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -70,6 +70,11 @@ <dimen name="metadata_normal_seek_margin_top">@*android:dimen/car_padding_4</dimen> <dimen name="metadata_normal_subtitle_margin_end">@*android:dimen/car_padding_3</dimen> + <!-- Size of the selected app's icon --> + <dimen name="playback_app_icon_size">25dp</dimen> + <dimen name="playback_fragment_icon_margin_x">15dp</dimen> + <dimen name="playback_fragment_icon_margin_top">29dp</dimen> + <!-- Size of the album art thumbnail --> <dimen name="playback_album_art_size_normal">156dp</dimen> diff --git a/src/android/car/cluster/MusicFragment.java b/src/android/car/cluster/MusicFragment.java index f5a2303..b4e0039 100644 --- a/src/android/car/cluster/MusicFragment.java +++ b/src/android/car/cluster/MusicFragment.java @@ -29,10 +29,12 @@ import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import androidx.lifecycle.ViewModelProviders; -import com.android.car.apps.common.BackgroundImageView; +import com.android.car.media.common.MetadataController; import com.android.car.media.common.playback.PlaybackViewModel; import com.android.car.media.common.source.MediaSourceViewModel; +import com.bumptech.glide.request.target.Target; + /** * Displays information on the current media item selected. */ @@ -54,42 +56,39 @@ public class MusicFragment extends Fragment { MusicFragmentViewModel innerViewModel = ViewModelProviders.of(activity).get( MusicFragmentViewModel.class); - innerViewModel.init(mMediaSourceViewModel, playbackViewModel); + innerViewModel.init(mMediaSourceViewModel); View view = inflater.inflate(R.layout.fragment_music, container, false); TextView appName = view.findViewById(R.id.app_name); innerViewModel.getAppName().observe(getViewLifecycleOwner(), appName::setText); - TextView title = view.findViewById(R.id.title); - innerViewModel.getTitle().observe(getViewLifecycleOwner(), title::setText); + ImageView appIcon = view.findViewById(R.id.app_icon); + innerViewModel.getAppIcon().observe(getViewLifecycleOwner(), appIcon::setImageBitmap); + TextView title = view.findViewById(R.id.title); TextView subtitle = view.findViewById(R.id.subtitle); - innerViewModel.getSubtitle().observe(getViewLifecycleOwner(), subtitle::setText); - SeekBar seekBar = view.findViewById(R.id.seek_bar); - innerViewModel.getMaxProgress().observe(getViewLifecycleOwner(), - maxProgress -> seekBar.setMax(maxProgress != null ? maxProgress.intValue() : 0)); - innerViewModel.getProgress().observe(getViewLifecycleOwner(), - progress -> seekBar.setProgress((int) progress.getProgress())); - innerViewModel.hasTime().observe(getViewLifecycleOwner(), - hasTime -> seekBar.setVisibility(hasTime ? View.VISIBLE : View.INVISIBLE)); - TextView time = view.findViewById(R.id.time); + TextView timeSeparator = view.findViewById(R.id.time_separator); + TextView trackLength = view.findViewById(R.id.track_length); - innerViewModel.getTimeText().observe(getViewLifecycleOwner(), - timeText -> time.setText(timeText)); - - BackgroundImageView albumBackground = view.findViewById(R.id.album_background); ImageView albumIcon = view.findViewById(R.id.album_art); - innerViewModel.getAlbumArt().observe(getViewLifecycleOwner(), albumArt -> { - albumBackground.setBackgroundImage(albumArt, true); - if (albumArt == null) { - albumIcon.setImageDrawable(getContext().getDrawable(R.drawable.ic_person)); - } else { - albumIcon.setImageBitmap(albumArt); - } - }); + + new MetadataController( + getViewLifecycleOwner(), + playbackViewModel, + title, + subtitle, + null, + null, + time, + timeSeparator, + trackLength, + seekBar, + albumIcon, + Target.SIZE_ORIGINAL + ); return view; } diff --git a/src/android/car/cluster/MusicFragmentViewModel.java b/src/android/car/cluster/MusicFragmentViewModel.java index 6923ec3..6e0faef 100644 --- a/src/android/car/cluster/MusicFragmentViewModel.java +++ b/src/android/car/cluster/MusicFragmentViewModel.java @@ -15,30 +15,17 @@ */ package android.car.cluster; -import static androidx.lifecycle.Transformations.map; - -import static com.android.car.arch.common.LiveDataFunctions.combine; import static com.android.car.arch.common.LiveDataFunctions.mapNonNull; -import android.annotation.SuppressLint; import android.app.Application; import android.graphics.Bitmap; -import android.media.session.PlaybackState; import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.LiveData; -import com.android.car.media.common.MediaItemMetadata; -import com.android.car.media.common.playback.AlbumArtLiveData; -import com.android.car.media.common.playback.PlaybackProgress; -import com.android.car.media.common.playback.PlaybackViewModel; import com.android.car.media.common.source.MediaSource; import com.android.car.media.common.source.MediaSourceViewModel; -import com.bumptech.glide.request.target.Target; - -import java.util.concurrent.TimeUnit; - /** * View model for {@link MusicFragment} */ @@ -47,48 +34,21 @@ public final class MusicFragmentViewModel extends AndroidViewModel { private LiveData<MediaSource> mMediaSource; private LiveData<CharSequence> mAppName; private LiveData<Bitmap> mAppIcon; - private LiveData<CharSequence> mTitle; - private LiveData<CharSequence> mSubtitle; - private LiveData<Bitmap> mAlbumArt; - private LiveData<PlaybackProgress> mProgress; - private LiveData<Long> mMaxProgress; - private LiveData<CharSequence> mTimeText; - private LiveData<Boolean> mHasTime; - private PlaybackViewModel mPlaybackViewModel; private MediaSourceViewModel mMediaSourceViewModel; public MusicFragmentViewModel(Application application) { super(application); } - void init(MediaSourceViewModel mediaSourceViewModel, PlaybackViewModel playbackViewModel) { - if (mMediaSourceViewModel == mediaSourceViewModel - && mPlaybackViewModel == playbackViewModel) { + void init(MediaSourceViewModel mediaSourceViewModel) { + if (mMediaSourceViewModel == mediaSourceViewModel) { return; } - mPlaybackViewModel = playbackViewModel; mMediaSourceViewModel = mediaSourceViewModel; mMediaSource = mMediaSourceViewModel.getPrimaryMediaSource(); mAppName = mapNonNull(mMediaSource, MediaSource::getName); mAppIcon = mapNonNull(mMediaSource, MediaSource::getRoundPackageIcon); - mTitle = mapNonNull(playbackViewModel.getMetadata(), MediaItemMetadata::getTitle); - mSubtitle = mapNonNull(playbackViewModel.getMetadata(), MediaItemMetadata::getSubtitle); - mAlbumArt = AlbumArtLiveData.getAlbumArt(getApplication(), - Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL, false, - playbackViewModel.getMetadata()); - mProgress = playbackViewModel.getProgress(); - mMaxProgress = map(playbackViewModel.getPlaybackStateWrapper(), - state -> state != null ? state.getMaxProgress() : 0L); - mTimeText = combine(mProgress, mMaxProgress, (progress, maxProgress) -> { - boolean showHours = TimeUnit.MILLISECONDS.toHours(maxProgress) > 0; - return String.format("%s / %s", - formatTime(progress.getProgress(), showHours), - formatTime(maxProgress, showHours)); - }); - mHasTime = combine(mProgress, mMaxProgress, (progress, maxProgress) -> - maxProgress > 0 - && progress.getProgress() != PlaybackState.PLAYBACK_POSITION_UNKNOWN); } LiveData<CharSequence> getAppName() { @@ -98,44 +58,4 @@ public final class MusicFragmentViewModel extends AndroidViewModel { LiveData<Bitmap> getAppIcon() { return mAppIcon; } - - LiveData<CharSequence> getTitle() { - return mTitle; - } - - LiveData<CharSequence> getSubtitle() { - return mSubtitle; - } - - LiveData<Bitmap> getAlbumArt() { - return mAlbumArt; - } - - LiveData<PlaybackProgress> getProgress() { - return mProgress; - } - - LiveData<Long> getMaxProgress() { - return mMaxProgress; - } - - LiveData<CharSequence> getTimeText() { - return mTimeText; - } - - LiveData<Boolean> hasTime() { - return mHasTime; - } - - @SuppressLint("DefaultLocale") - private static String formatTime(long millis, boolean showHours) { - long hours = TimeUnit.MILLISECONDS.toHours(millis); - long minutes = TimeUnit.MILLISECONDS.toMinutes(millis) % TimeUnit.HOURS.toMinutes(1); - long seconds = TimeUnit.MILLISECONDS.toSeconds(millis) % TimeUnit.MINUTES.toSeconds(1); - if (showHours) { - return String.format("%d:%02d:%02d", hours, minutes, seconds); - } else { - return String.format("%d:%02d", minutes, seconds); - } - } } |