mirror of
https://github.com/antebudimir/tempus.git
synced 2026-01-01 18:03:33 +00:00
Added overlay controllers in CoverFragment
This commit is contained in:
parent
ce4c1631bd
commit
bc4d7251b0
2 changed files with 187 additions and 4 deletions
|
|
@ -3,6 +3,9 @@ package com.cappielloantonio.play.ui.fragment;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.transition.Fade;
|
||||||
|
import android.transition.Transition;
|
||||||
|
import android.transition.TransitionManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
@ -10,28 +13,48 @@ import android.view.ViewGroup;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.media3.common.MediaMetadata;
|
import androidx.media3.common.MediaMetadata;
|
||||||
import androidx.media3.common.Player;
|
import androidx.media3.common.Player;
|
||||||
import androidx.media3.session.MediaBrowser;
|
import androidx.media3.session.MediaBrowser;
|
||||||
import androidx.media3.session.SessionToken;
|
import androidx.media3.session.SessionToken;
|
||||||
|
|
||||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||||
|
import com.cappielloantonio.play.App;
|
||||||
import com.cappielloantonio.play.databinding.InnerFragmentPlayerCoverBinding;
|
import com.cappielloantonio.play.databinding.InnerFragmentPlayerCoverBinding;
|
||||||
import com.cappielloantonio.play.glide.CustomGlideRequest;
|
import com.cappielloantonio.play.glide.CustomGlideRequest;
|
||||||
|
import com.cappielloantonio.play.interfaces.MediaCallback;
|
||||||
|
import com.cappielloantonio.play.model.Song;
|
||||||
|
import com.cappielloantonio.play.repository.SongRepository;
|
||||||
|
import com.cappielloantonio.play.service.MediaManager;
|
||||||
import com.cappielloantonio.play.service.MediaService;
|
import com.cappielloantonio.play.service.MediaService;
|
||||||
|
import com.cappielloantonio.play.ui.dialog.PlaylistChooserDialog;
|
||||||
|
import com.cappielloantonio.play.util.DownloadUtil;
|
||||||
|
import com.cappielloantonio.play.util.MappingUtil;
|
||||||
|
import com.cappielloantonio.play.viewmodel.PlayerBottomSheetViewModel;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.common.util.concurrent.MoreExecutors;
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class PlayerCoverFragment extends Fragment {
|
public class PlayerCoverFragment extends Fragment {
|
||||||
private static final String TAG = "PlayerCoverFragment";
|
private static final String TAG = "PlayerCoverFragment";
|
||||||
|
|
||||||
|
private PlayerBottomSheetViewModel playerBottomSheetViewModel;
|
||||||
private InnerFragmentPlayerCoverBinding bind;
|
private InnerFragmentPlayerCoverBinding bind;
|
||||||
private ListenableFuture<MediaBrowser> mediaBrowserListenableFuture;
|
private ListenableFuture<MediaBrowser> mediaBrowserListenableFuture;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
bind = InnerFragmentPlayerCoverBinding.inflate(inflater, container, false);
|
bind = InnerFragmentPlayerCoverBinding.inflate(inflater, container, false);
|
||||||
return bind.getRoot();
|
View view = bind.getRoot();
|
||||||
|
|
||||||
|
playerBottomSheetViewModel = new ViewModelProvider(requireActivity()).get(PlayerBottomSheetViewModel.class);
|
||||||
|
|
||||||
|
initOverlay();
|
||||||
|
initInnerButton();
|
||||||
|
|
||||||
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -39,6 +62,7 @@ public class PlayerCoverFragment extends Fragment {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
initializeBrowser();
|
initializeBrowser();
|
||||||
bindMediaController();
|
bindMediaController();
|
||||||
|
toggleOverlayVisibility(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -53,6 +77,64 @@ public class PlayerCoverFragment extends Fragment {
|
||||||
bind = null;
|
bind = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initOverlay() {
|
||||||
|
bind.nowPlayingSongCoverImageView.setOnClickListener(view -> toggleOverlayVisibility(true));
|
||||||
|
bind.nowPlayingSongCoverButtonGroup.setOnClickListener(view -> toggleOverlayVisibility(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toggleOverlayVisibility(boolean isVisible) {
|
||||||
|
Transition transition = new Fade();
|
||||||
|
transition.setDuration(200);
|
||||||
|
transition.addTarget(bind.nowPlayingSongCoverButtonGroup);
|
||||||
|
|
||||||
|
TransitionManager.beginDelayedTransition(bind.getRoot(), transition);
|
||||||
|
bind.nowPlayingSongCoverButtonGroup.setVisibility(isVisible ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initInnerButton() {
|
||||||
|
playerBottomSheetViewModel.getLiveSong().observe(requireActivity(), song -> {
|
||||||
|
if (song != null && bind != null) {
|
||||||
|
bind.innerButtonTopLeft.setOnClickListener(view -> {
|
||||||
|
DownloadUtil.getDownloadTracker(requireContext()).download(
|
||||||
|
MappingUtil.mapMediaItem(requireContext(), song, false),
|
||||||
|
MappingUtil.mapDownload(song, null, null)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
bind.innerButtonTopRight.setOnClickListener(view -> {
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putParcelable("song_object", song);
|
||||||
|
|
||||||
|
PlaylistChooserDialog dialog = new PlaylistChooserDialog();
|
||||||
|
dialog.setArguments(bundle);
|
||||||
|
dialog.show(requireActivity().getSupportFragmentManager(), null);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
bind.innerButtonBottomLeft.setOnClickListener(view -> {
|
||||||
|
MediaManager.startQueue(mediaBrowserListenableFuture, requireContext(), song);
|
||||||
|
|
||||||
|
SongRepository songRepository = new SongRepository(App.getInstance());
|
||||||
|
songRepository.getInstantMix(song, 20, new MediaCallback() {
|
||||||
|
@Override
|
||||||
|
public void onError(Exception exception) {
|
||||||
|
Log.e(TAG, "onError() " + exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadMedia(List<?> media) {
|
||||||
|
MediaManager.enqueue(mediaBrowserListenableFuture, requireContext(), (List<Song>) media, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
bind.innerButtonBottomRight.setOnClickListener(view -> {
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("UnsafeOptInUsageError")
|
@SuppressLint("UnsafeOptInUsageError")
|
||||||
private void initializeBrowser() {
|
private void initializeBrowser() {
|
||||||
mediaBrowserListenableFuture = new MediaBrowser.Builder(requireContext(), new SessionToken(requireContext(), new ComponentName(requireContext(), MediaService.class))).buildAsync();
|
mediaBrowserListenableFuture = new MediaBrowser.Builder(requireContext(), new SessionToken(requireContext(), new ComponentName(requireContext(), MediaService.class))).buildAsync();
|
||||||
|
|
@ -82,6 +164,7 @@ public class PlayerCoverFragment extends Fragment {
|
||||||
@Override
|
@Override
|
||||||
public void onMediaMetadataChanged(@NonNull MediaMetadata mediaMetadata) {
|
public void onMediaMetadataChanged(@NonNull MediaMetadata mediaMetadata) {
|
||||||
setCover(mediaMetadata);
|
setCover(mediaMetadata);
|
||||||
|
toggleOverlayVisibility(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,106 @@
|
||||||
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:id="@+id/now_playing_song_cover_image_view"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:paddingStart="24dp"
|
android:paddingStart="24dp"
|
||||||
android:paddingEnd="24dp"/>
|
android:paddingEnd="24dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/now_playing_song_cover_image_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintDimensionRatio="H,1:1"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/now_playing_song_cover_button_group"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:animateLayoutChanges="true"
|
||||||
|
android:background="@drawable/gradient_player_cover_background_image"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintDimensionRatio="H,1:1"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/inner_button_top_left"
|
||||||
|
style="@style/Widget.Material3.Button.TonalButton.Icon"
|
||||||
|
android:layout_width="52dp"
|
||||||
|
android:layout_height="52dp"
|
||||||
|
android:layout_margin="4dp"
|
||||||
|
android:insetLeft="0dp"
|
||||||
|
android:insetTop="0dp"
|
||||||
|
android:insetRight="0dp"
|
||||||
|
android:insetBottom="0dp"
|
||||||
|
app:cornerRadius="30dp"
|
||||||
|
app:icon="@drawable/ic_file_download"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/horizontal_guideline"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/vertical_guideline" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/inner_button_top_right"
|
||||||
|
style="@style/Widget.Material3.Button.TonalButton.Icon"
|
||||||
|
android:layout_width="52dp"
|
||||||
|
android:layout_height="52dp"
|
||||||
|
android:layout_margin="4dp"
|
||||||
|
android:insetLeft="0dp"
|
||||||
|
android:insetTop="0dp"
|
||||||
|
android:insetRight="0dp"
|
||||||
|
android:insetBottom="0dp"
|
||||||
|
app:cornerRadius="30dp"
|
||||||
|
app:icon="@drawable/ic_playlist_add"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/horizontal_guideline"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/vertical_guideline" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.Guideline
|
||||||
|
android:id="@+id/horizontal_guideline"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layout_constraintGuide_percent="0.50" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.Guideline
|
||||||
|
android:id="@+id/vertical_guideline"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintGuide_percent="0.50" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/inner_button_bottom_left"
|
||||||
|
style="@style/Widget.Material3.Button.TonalButton.Icon"
|
||||||
|
android:layout_width="52dp"
|
||||||
|
android:layout_height="52dp"
|
||||||
|
android:layout_margin="4dp"
|
||||||
|
android:insetLeft="0dp"
|
||||||
|
android:insetTop="0dp"
|
||||||
|
android:insetRight="0dp"
|
||||||
|
android:insetBottom="0dp"
|
||||||
|
app:cornerRadius="30dp"
|
||||||
|
app:icon="@drawable/ic_mix_from_here"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/vertical_guideline"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/horizontal_guideline" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/inner_button_bottom_right"
|
||||||
|
style="@style/Widget.Material3.Button.TonalButton.Icon"
|
||||||
|
android:layout_width="52dp"
|
||||||
|
android:layout_height="52dp"
|
||||||
|
android:layout_margin="4dp"
|
||||||
|
android:insetLeft="0dp"
|
||||||
|
android:insetTop="0dp"
|
||||||
|
android:insetRight="0dp"
|
||||||
|
android:insetBottom="0dp"
|
||||||
|
app:cornerRadius="30dp"
|
||||||
|
app:icon="@drawable/ic_lyrics"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/vertical_guideline"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/horizontal_guideline" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue