diff --git a/.idea/misc.xml b/.idea/misc.xml
index 8d1cf2da..33b2e19b 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -77,6 +77,8 @@
+
+
@@ -112,7 +114,7 @@
-
+
diff --git a/app/build.gradle b/app/build.gradle
index 82f75f2c..4cc0ef5a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -66,6 +66,7 @@ dependencies {
// Exoplayer
implementation 'com.google.android.exoplayer:exoplayer:2.12.2'
+ implementation 'androidx.legacy:legacy-support-v4:1.0.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
annotationProcessor 'androidx.room:room-compiler:2.4.0'
diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/PlayerNowPlayingSongAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/PlayerNowPlayingSongAdapter.java
index f02c5c20..acedcbc3 100644
--- a/app/src/main/java/com/cappielloantonio/play/adapter/PlayerNowPlayingSongAdapter.java
+++ b/app/src/main/java/com/cappielloantonio/play/adapter/PlayerNowPlayingSongAdapter.java
@@ -1,91 +1,34 @@
package com.cappielloantonio.play.adapter;
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-
import androidx.annotation.NonNull;
-import androidx.recyclerview.widget.RecyclerView;
+import androidx.fragment.app.Fragment;
+import androidx.viewpager2.adapter.FragmentStateAdapter;
-import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
-import com.cappielloantonio.play.R;
-import com.cappielloantonio.play.glide.CustomGlideRequest;
-import com.cappielloantonio.play.model.Song;
-import com.cappielloantonio.play.service.MusicPlayerRemote;
+import com.cappielloantonio.play.ui.fragment.PlayerCoverFragment;
+import com.cappielloantonio.play.ui.fragment.PlayerLyricsFragment;
-import java.util.ArrayList;
-import java.util.List;
+public class PlayerNowPlayingSongAdapter extends FragmentStateAdapter {
+ private static final String TAG = "PlayerNowPlayingSongInfoAdapter";
-public class PlayerNowPlayingSongAdapter extends RecyclerView.Adapter {
- private static final String TAG = "PlayerNowPlayingSongAdapter";
-
- private final LayoutInflater inflater;
- private final Context context;
-
- private List songs;
-
- public PlayerNowPlayingSongAdapter(Context context) {
- this.context = context;
- this.inflater = LayoutInflater.from(context);
- this.songs = new ArrayList<>();
+ public PlayerNowPlayingSongAdapter(@NonNull Fragment fragment) {
+ super(fragment);
}
@NonNull
@Override
- public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
- View view = inflater.inflate(R.layout.item_player_now_playing_song, parent, false);
- return new ViewHolder(view);
- }
+ public Fragment createFragment(int position) {
+ switch (position) {
+ case 0:
+ return new PlayerCoverFragment();
+ case 1:
+ return new PlayerLyricsFragment();
+ }
- @Override
- public void onBindViewHolder(ViewHolder holder, int position) {
- Song song = songs.get(position);
-
- CustomGlideRequest.Builder
- .from(context, song.getId(), CustomGlideRequest.SONG_PIC, null)
- .build()
- .transform(new RoundedCorners(CustomGlideRequest.CORNER_RADIUS))
- .into(holder.cover);
+ return new PlayerCoverFragment();
}
@Override
public int getItemCount() {
- return songs.size();
- }
-
- public Song getItem(int position) {
- try {
- return songs.get(position);
- } catch (IndexOutOfBoundsException e) {
- return null;
- }
- }
-
- public void setItems(List songs) {
- this.songs = songs;
- notifyDataSetChanged();
- }
-
- public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
- ImageView cover;
-
- ViewHolder(View itemView) {
- super(itemView);
-
- cover = itemView.findViewById(R.id.now_playing_song_cover_image_view);
-
- itemView.setOnClickListener(this);
- }
-
- @Override
- public void onClick(View view) {
- if (MusicPlayerRemote.isPlaying()) {
- MusicPlayerRemote.pauseSong();
- } else {
- MusicPlayerRemote.resumePlaying();
- }
- }
+ return 2;
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/PlayerSongQueueAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/PlayerSongQueueAdapter.java
index 9dc4244d..99d94a70 100644
--- a/app/src/main/java/com/cappielloantonio/play/adapter/PlayerSongQueueAdapter.java
+++ b/app/src/main/java/com/cappielloantonio/play/adapter/PlayerSongQueueAdapter.java
@@ -101,7 +101,7 @@ public class PlayerSongQueueAdapter extends RecyclerView.Adapter activity.collapseBottomSheet());
}
- private void initLyricsView() {
- /*playerBottomSheetViewModel.getLyrics().observe(requireActivity(), lyrics -> {
- if (lyrics != null && !lyrics.trim().equals("")) {
- bodyBind.playerSongLyricsCardview.setVisibility(View.VISIBLE);
- } else {
- bodyBind.playerSongLyricsCardview.setVisibility(View.GONE);
- }
-
- bodyBind.playerSongLyricsTextView.setText(MusicUtil.getReadableString(lyrics));
- });
-
- bodyBind.playerSongLyricsLabelClickable.setOnClickListener(view -> {
- if (bodyBind.playerSongLyricsTextView.getVisibility() == View.INVISIBLE || bodyBind.playerSongLyricsTextView.getVisibility() == View.GONE) {
- setLyricsTextViewVisibility(true);
- } else {
- setLyricsTextViewVisibility(false);
- }
- });*/
- }
-
- private void initQueueSlideView() {
+ private void initCoverLyricsSlideView() {
bodyBind.playerSongCoverViewPager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
-
- playerNowPlayingSongAdapter = new PlayerNowPlayingSongAdapter(requireContext());
- bodyBind.playerSongCoverViewPager.setAdapter(playerNowPlayingSongAdapter);
- playerBottomSheetViewModel.getQueueSong().observe(requireActivity(), queue -> playerNowPlayingSongAdapter.setItems(MappingUtil.mapQueue(queue)));
-
- bodyBind.playerSongCoverViewPager.setOffscreenPageLimit(3);
- bodyBind.playerSongCoverViewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
- // 0 = IDLE
- // 1 = DRAGGING
- // 2 = SETTLING
- // -1 = NEW
- int pageState = -1;
-
- @Override
- public void onPageScrollStateChanged(int state) {
- super.onPageScrollStateChanged(state);
- pageState = state;
- }
-
- @Override
- public void onPageSelected(int position) {
- super.onPageSelected(position);
-
- if (pageState != -1) {
- MusicPlayerRemote.playSongAt(position);
- pageState = -1;
- }
- }
- });
-
- setViewPageDelayed(PreferenceUtil.getInstance(requireContext()).getPosition());
+ bodyBind.playerSongCoverViewPager.setAdapter(new PlayerNowPlayingSongAdapter(this));
}
private void initQueueRecyclerView() {
@@ -326,17 +275,8 @@ public class PlayerBottomSheetFragment extends Fragment implements MusicServiceE
});
}
- private void setViewPageDelayed(int position) {
- final Handler handler = new Handler();
- final Runnable r = () -> {
- if (bind != null) bodyBind.playerSongCoverViewPager.setCurrentItem(position, false);
- };
- handler.postDelayed(r, 100);
- }
-
- private void setSongInfo(Song song) {
- // setLyricsTextViewVisibility(false);
- playerBottomSheetViewModel.refreshSongLyrics(requireActivity(), song);
+ public void setSongInfo(Song song) {
+ playerBottomSheetViewModel.refreshSongInfo(requireActivity(), song);
bodyBind.playerSongTitleLabel.setText(MusicUtil.getReadableString(song.getTitle()));
bodyBind.playerArtistNameLabel.setText(MusicUtil.getReadableString(song.getArtistName()));
@@ -354,7 +294,7 @@ public class PlayerBottomSheetFragment extends Fragment implements MusicServiceE
}
public void setPlayerCommandViewVisibility(boolean isVisible) {
- if(isVisible) {
+ if (isVisible) {
bodyBind.playerCommandCardview.setVisibility(View.VISIBLE);
} else {
bodyBind.playerCommandCardview.setVisibility(View.GONE);
@@ -377,11 +317,6 @@ public class PlayerBottomSheetFragment extends Fragment implements MusicServiceE
bind.playerNestedScrollView.fullScroll(ScrollView.FOCUS_UP);
}
- public void scrollPager(Song song, int page, boolean smoothScroll) {
- bodyBind.playerSongCoverViewPager.setCurrentItem(page, smoothScroll);
- setSongInfo(song);
- }
-
@Override
public void onServiceConnected() {
setSongInfo(Objects.requireNonNull(MusicPlayerRemote.getCurrentSong()));
@@ -400,7 +335,6 @@ public class PlayerBottomSheetFragment extends Fragment implements MusicServiceE
@Override
public void onPlayMetadataChanged() {
- setViewPageDelayed(MusicPlayerRemote.getPosition());
setSongInfo(Objects.requireNonNull(MusicPlayerRemote.getCurrentSong()));
}
diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerCoverFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerCoverFragment.java
new file mode 100644
index 00000000..743ed579
--- /dev/null
+++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerCoverFragment.java
@@ -0,0 +1,51 @@
+package com.cappielloantonio.play.ui.fragment;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
+
+import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
+import com.cappielloantonio.play.databinding.FragmentPlayerCoverBinding;
+import com.cappielloantonio.play.glide.CustomGlideRequest;
+import com.cappielloantonio.play.viewmodel.PlayerBottomSheetViewModel;
+
+public class PlayerCoverFragment extends Fragment {
+ private static final String TAG = "PlayerCoverFragment";
+
+ private FragmentPlayerCoverBinding bind;
+ private PlayerBottomSheetViewModel playerBottomSheetViewModel;
+
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ bind = FragmentPlayerCoverBinding.inflate(inflater, container, false);
+ View view = bind.getRoot();
+ playerBottomSheetViewModel = new ViewModelProvider(requireActivity()).get(PlayerBottomSheetViewModel.class);
+
+ init();
+
+ return view;
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ bind = null;
+ }
+
+ private void init() {
+ playerBottomSheetViewModel.getLiveSong().observe(requireActivity(), song -> {
+ if (song != null) {
+ CustomGlideRequest.Builder
+ .from(requireContext(), song.getId(), CustomGlideRequest.SONG_PIC, null)
+ .build()
+ .transform(new RoundedCorners(CustomGlideRequest.CORNER_RADIUS))
+ .into(bind.nowPlayingSongCoverImageView);
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerLyricsFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerLyricsFragment.java
new file mode 100644
index 00000000..819a4170
--- /dev/null
+++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlayerLyricsFragment.java
@@ -0,0 +1,52 @@
+package com.cappielloantonio.play.ui.fragment;
+
+import android.annotation.SuppressLint;
+import android.os.Bundle;
+import android.text.method.ScrollingMovementMethod;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.ViewModelProvider;
+
+import com.cappielloantonio.play.R;
+import com.cappielloantonio.play.databinding.FragmentPlayerLyricsBinding;
+import com.cappielloantonio.play.util.MusicUtil;
+import com.cappielloantonio.play.viewmodel.PlayerBottomSheetViewModel;
+
+public class PlayerLyricsFragment extends Fragment {
+ private static final String TAG = "PlayerLyricsFragment";
+
+ private FragmentPlayerLyricsBinding bind;
+ private PlayerBottomSheetViewModel playerBottomSheetViewModel;
+
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ bind = FragmentPlayerLyricsBinding.inflate(inflater, container, false);
+ View view = bind.getRoot();
+ playerBottomSheetViewModel = new ViewModelProvider(requireActivity()).get(PlayerBottomSheetViewModel.class);
+
+ initLyrics();
+
+ return view;
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ bind = null;
+ }
+
+ private void initLyrics() {
+ playerBottomSheetViewModel.getLiveLyrics().observe(requireActivity(), lyrics -> {
+ if (lyrics == null || lyrics.trim().equals("")) {
+ bind.nowPlayingSongLyricsTextView.setText(R.string.player_song_lyrics_none_available_label);
+ } else {
+ bind.nowPlayingSongLyricsTextView.setText(MusicUtil.getReadableString(lyrics));
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/PlayerBottomSheetViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/PlayerBottomSheetViewModel.java
index 06ab7b4e..f43ebac0 100644
--- a/app/src/main/java/com/cappielloantonio/play/viewmodel/PlayerBottomSheetViewModel.java
+++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/PlayerBottomSheetViewModel.java
@@ -29,7 +29,9 @@ public class PlayerBottomSheetViewModel extends AndroidViewModel {
private final ArtistRepository artistRepository;
private final QueueRepository queueRepository;
- private final MutableLiveData songLyrics = new MutableLiveData<>(null);
+ private final MutableLiveData lyricsLiveData = new MutableLiveData<>(null);
+ private final MutableLiveData songLiveData = new MutableLiveData<>(null);
+
private final LiveData> queueSong;
public PlayerBottomSheetViewModel(@NonNull Application application) {
@@ -81,11 +83,17 @@ public class PlayerBottomSheetViewModel extends AndroidViewModel {
return artistRepository.getArtist(song.getArtistId());
}
- public LiveData getLyrics() {
- return songLyrics;
+ public LiveData getLiveSong() {
+ return songLiveData;
}
- public void refreshSongLyrics(LifecycleOwner owner, Song song) {
- songRepository.getSongLyrics(song).observe(owner, songLyrics::postValue);
+ public LiveData getLiveLyrics() {
+ return lyricsLiveData;
}
+
+ public void refreshSongInfo(LifecycleOwner owner, Song song) {
+ songLiveData.postValue(song);
+ songRepository.getSongLyrics(song).observe(owner, lyricsLiveData::postValue);
+ }
+
}
diff --git a/app/src/main/res/layout/fragment_player_cover.xml b/app/src/main/res/layout/fragment_player_cover.xml
new file mode 100644
index 00000000..e0bf3ebe
--- /dev/null
+++ b/app/src/main/res/layout/fragment_player_cover.xml
@@ -0,0 +1,6 @@
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_player_lyrics.xml b/app/src/main/res/layout/fragment_player_lyrics.xml
new file mode 100644
index 00000000..01aa9bd2
--- /dev/null
+++ b/app/src/main/res/layout/fragment_player_lyrics.xml
@@ -0,0 +1,12 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/player_body_bottom_sheet.xml b/app/src/main/res/layout/player_body_bottom_sheet.xml
index b12b9143..dc7d7ba0 100644
--- a/app/src/main/res/layout/player_body_bottom_sheet.xml
+++ b/app/src/main/res/layout/player_body_bottom_sheet.xml
@@ -2,6 +2,7 @@
#DADADA
#CFCFCF
#CCCCCC
- #080808
+ #404040
#CFCFCF
#1D1D1D
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 08e45380..91b08027 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -114,6 +114,7 @@
Hide
Show
Lyrics
+ No lyrics available
The playing notification provides actions for play/pause etc.
Playing Notification
Playlist Catalogue
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index a0a07bb5..f0262d0d 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -129,6 +129,12 @@
- @color/titleTextColor
+
+