mirror of
https://github.com/antebudimir/tempus.git
synced 2026-01-02 10:23:33 +00:00
feat: implemented synchronized lyrics display
This commit is contained in:
parent
111a17350b
commit
e35aed9cc4
7 changed files with 240 additions and 24 deletions
|
|
@ -249,6 +249,11 @@ public class PlayerBottomSheetFragment extends Fragment {
|
||||||
bind.playerBodyLayout.playerBodyBottomSheetViewPager.setCurrentItem(1, true);
|
bind.playerBodyLayout.playerBodyBottomSheetViewPager.setCurrentItem(1, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPlayerControllerVerticalPagerDraggableState(Boolean isDraggable) {
|
||||||
|
ViewPager2 playerControllerVerticalPager = (ViewPager2) bind.playerBodyLayout.playerBodyBottomSheetViewPager;
|
||||||
|
playerControllerVerticalPager.setUserInputEnabled(isDraggable);
|
||||||
|
}
|
||||||
|
|
||||||
private void defineProgressBarHandler(MediaBrowser mediaBrowser) {
|
private void defineProgressBarHandler(MediaBrowser mediaBrowser) {
|
||||||
progressBarHandler = new Handler();
|
progressBarHandler = new Handler();
|
||||||
progressBarRunnable = () -> {
|
progressBarRunnable = () -> {
|
||||||
|
|
|
||||||
|
|
@ -257,10 +257,20 @@ public class PlayerControllerFragment extends Fragment {
|
||||||
public void onPageSelected(int position) {
|
public void onPageSelected(int position) {
|
||||||
super.onPageSelected(position);
|
super.onPageSelected(position);
|
||||||
|
|
||||||
|
PlayerBottomSheetFragment playerBottomSheetFragment = (PlayerBottomSheetFragment) requireActivity().getSupportFragmentManager().findFragmentByTag("PlayerBottomSheet");
|
||||||
|
|
||||||
if (position == 0) {
|
if (position == 0) {
|
||||||
activity.setBottomSheetDraggableState(true);
|
activity.setBottomSheetDraggableState(true);
|
||||||
|
|
||||||
|
if (playerBottomSheetFragment != null) {
|
||||||
|
playerBottomSheetFragment.setPlayerControllerVerticalPagerDraggableState(true);
|
||||||
|
}
|
||||||
} else if (position == 1) {
|
} else if (position == 1) {
|
||||||
activity.setBottomSheetDraggableState(false);
|
activity.setBottomSheetDraggableState(false);
|
||||||
|
|
||||||
|
if (playerBottomSheetFragment != null) {
|
||||||
|
playerBottomSheetFragment.setPlayerControllerVerticalPagerDraggableState(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,50 @@
|
||||||
package com.cappielloantonio.tempo.ui.fragment;
|
package com.cappielloantonio.tempo.ui.fragment;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.ComponentName;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.text.Spannable;
|
||||||
|
import android.text.SpannableString;
|
||||||
|
import android.text.style.ForegroundColorSpan;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.OptIn;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
import androidx.media3.common.util.UnstableApi;
|
||||||
|
import androidx.media3.session.MediaBrowser;
|
||||||
|
import androidx.media3.session.SessionToken;
|
||||||
|
|
||||||
|
import com.cappielloantonio.tempo.R;
|
||||||
import com.cappielloantonio.tempo.databinding.InnerFragmentPlayerLyricsBinding;
|
import com.cappielloantonio.tempo.databinding.InnerFragmentPlayerLyricsBinding;
|
||||||
|
import com.cappielloantonio.tempo.service.MediaService;
|
||||||
|
import com.cappielloantonio.tempo.subsonic.models.Line;
|
||||||
|
import com.cappielloantonio.tempo.subsonic.models.LyricsList;
|
||||||
import com.cappielloantonio.tempo.util.MusicUtil;
|
import com.cappielloantonio.tempo.util.MusicUtil;
|
||||||
|
import com.cappielloantonio.tempo.util.OpenSubsonicExtensionsUtil;
|
||||||
import com.cappielloantonio.tempo.viewmodel.PlayerBottomSheetViewModel;
|
import com.cappielloantonio.tempo.viewmodel.PlayerBottomSheetViewModel;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
@OptIn(markerClass = UnstableApi.class)
|
||||||
public class PlayerLyricsFragment extends Fragment {
|
public class PlayerLyricsFragment extends Fragment {
|
||||||
private static final String TAG = "PlayerLyricsFragment";
|
private static final String TAG = "PlayerLyricsFragment";
|
||||||
|
|
||||||
private InnerFragmentPlayerLyricsBinding bind;
|
private InnerFragmentPlayerLyricsBinding bind;
|
||||||
private PlayerBottomSheetViewModel playerBottomSheetViewModel;
|
private PlayerBottomSheetViewModel playerBottomSheetViewModel;
|
||||||
|
private ListenableFuture<MediaBrowser> mediaBrowserListenableFuture;
|
||||||
|
private MediaBrowser mediaBrowser;
|
||||||
|
private Handler syncLyricsHandler;
|
||||||
|
private Runnable syncLyricsRunnable;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
|
@ -33,7 +59,32 @@ public class PlayerLyricsFragment extends Fragment {
|
||||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
initLyrics();
|
initPanelContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
initializeBrowser();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
bindMediaController();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
releaseHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStop() {
|
||||||
|
releaseBrowser();
|
||||||
|
super.onStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -42,27 +93,156 @@ public class PlayerLyricsFragment extends Fragment {
|
||||||
bind = null;
|
bind = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initLyrics() {
|
private void initializeBrowser() {
|
||||||
playerBottomSheetViewModel.getLiveLyrics().observe(getViewLifecycleOwner(), lyrics -> {
|
mediaBrowserListenableFuture = new MediaBrowser.Builder(requireContext(), new SessionToken(requireContext(), new ComponentName(requireContext(), MediaService.class))).buildAsync();
|
||||||
playerBottomSheetViewModel.getLiveDescription().observe(getViewLifecycleOwner(), description -> {
|
}
|
||||||
if (bind != null) {
|
|
||||||
if (lyrics != null && !lyrics.trim().equals("")) {
|
private void releaseHandler() {
|
||||||
bind.nowPlayingSongLyricsTextView.setText(MusicUtil.getReadableLyrics(lyrics));
|
if (syncLyricsHandler != null) {
|
||||||
bind.nowPlayingSongLyricsTextView.setVisibility(View.VISIBLE);
|
syncLyricsHandler.removeCallbacks(syncLyricsRunnable);
|
||||||
bind.emptyDescriptionImageView.setVisibility(View.GONE);
|
syncLyricsHandler = null;
|
||||||
bind.titleEmptyDescriptionLabel.setVisibility(View.GONE);
|
}
|
||||||
} else if (description != null && !description.trim().equals("")) {
|
}
|
||||||
bind.nowPlayingSongLyricsTextView.setText(MusicUtil.getReadableLyrics(description));
|
|
||||||
bind.nowPlayingSongLyricsTextView.setVisibility(View.VISIBLE);
|
private void releaseBrowser() {
|
||||||
bind.emptyDescriptionImageView.setVisibility(View.GONE);
|
MediaBrowser.releaseFuture(mediaBrowserListenableFuture);
|
||||||
bind.titleEmptyDescriptionLabel.setVisibility(View.GONE);
|
}
|
||||||
} else {
|
|
||||||
bind.nowPlayingSongLyricsTextView.setVisibility(View.GONE);
|
private void bindMediaController() {
|
||||||
bind.emptyDescriptionImageView.setVisibility(View.VISIBLE);
|
mediaBrowserListenableFuture.addListener(() -> {
|
||||||
bind.titleEmptyDescriptionLabel.setVisibility(View.VISIBLE);
|
try {
|
||||||
}
|
mediaBrowser = mediaBrowserListenableFuture.get();
|
||||||
}
|
defineProgressHandler();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}, MoreExecutors.directExecutor());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initPanelContent() {
|
||||||
|
if (OpenSubsonicExtensionsUtil.isSongLyricsExtensionAvailable()) {
|
||||||
|
playerBottomSheetViewModel.getLiveLyricsList().observe(getViewLifecycleOwner(), lyricsList -> {
|
||||||
|
setPanelContent(null, lyricsList);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
playerBottomSheetViewModel.getLiveLyrics().observe(getViewLifecycleOwner(), lyrics -> {
|
||||||
|
setPanelContent(lyrics, null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPanelContent(String lyrics, LyricsList lyricsList) {
|
||||||
|
playerBottomSheetViewModel.getLiveDescription().observe(getViewLifecycleOwner(), description -> {
|
||||||
|
if (bind != null) {
|
||||||
|
if (lyrics != null && !lyrics.trim().equals("")) {
|
||||||
|
bind.nowPlayingSongLyricsTextView.setText(MusicUtil.getReadableLyrics(lyrics));
|
||||||
|
bind.nowPlayingSongLyricsTextView.setVisibility(View.VISIBLE);
|
||||||
|
bind.emptyDescriptionImageView.setVisibility(View.GONE);
|
||||||
|
bind.titleEmptyDescriptionLabel.setVisibility(View.GONE);
|
||||||
|
} else if (lyricsList != null && lyricsList.getStructuredLyrics() != null) {
|
||||||
|
setSyncLirics(lyricsList);
|
||||||
|
bind.nowPlayingSongLyricsTextView.setVisibility(View.VISIBLE);
|
||||||
|
bind.emptyDescriptionImageView.setVisibility(View.GONE);
|
||||||
|
bind.titleEmptyDescriptionLabel.setVisibility(View.GONE);
|
||||||
|
} else if (description != null && !description.trim().equals("")) {
|
||||||
|
bind.nowPlayingSongLyricsTextView.setText(MusicUtil.getReadableLyrics(description));
|
||||||
|
bind.nowPlayingSongLyricsTextView.setVisibility(View.VISIBLE);
|
||||||
|
bind.emptyDescriptionImageView.setVisibility(View.GONE);
|
||||||
|
bind.titleEmptyDescriptionLabel.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
bind.nowPlayingSongLyricsTextView.setVisibility(View.GONE);
|
||||||
|
bind.emptyDescriptionImageView.setVisibility(View.VISIBLE);
|
||||||
|
bind.titleEmptyDescriptionLabel.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("DefaultLocale")
|
||||||
|
private void setSyncLirics(LyricsList lyricsList) {
|
||||||
|
if (lyricsList.getStructuredLyrics() != null && !lyricsList.getStructuredLyrics().isEmpty() && lyricsList.getStructuredLyrics().get(0).getLine() != null) {
|
||||||
|
StringBuilder lyricsBuilder = new StringBuilder();
|
||||||
|
List<Line> lines = lyricsList.getStructuredLyrics().get(0).getLine();
|
||||||
|
|
||||||
|
if (lines != null) {
|
||||||
|
for (Line line : lines) {
|
||||||
|
lyricsBuilder.append(line.getValue().trim()).append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bind.nowPlayingSongLyricsTextView.setText(lyricsBuilder.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void defineProgressHandler() {
|
||||||
|
playerBottomSheetViewModel.getLiveLyricsList().observe(getViewLifecycleOwner(), lyricsList -> {
|
||||||
|
if (lyricsList != null) {
|
||||||
|
|
||||||
|
if (lyricsList.getStructuredLyrics() != null && lyricsList.getStructuredLyrics().get(0) != null && !lyricsList.getStructuredLyrics().get(0).getSynced()) {
|
||||||
|
releaseHandler();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
syncLyricsHandler = new Handler();
|
||||||
|
syncLyricsRunnable = () -> {
|
||||||
|
if (syncLyricsHandler != null) {
|
||||||
|
if (bind != null) {
|
||||||
|
displaySyncedLyrics();
|
||||||
|
}
|
||||||
|
|
||||||
|
syncLyricsHandler.postDelayed(syncLyricsRunnable, 250);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
syncLyricsHandler.postDelayed(syncLyricsRunnable, 250);
|
||||||
|
} else {
|
||||||
|
releaseHandler();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void displaySyncedLyrics() {
|
||||||
|
LyricsList lyricsList = playerBottomSheetViewModel.getLiveLyricsList().getValue();
|
||||||
|
int timestamp = (int) (mediaBrowser.getCurrentPosition());
|
||||||
|
|
||||||
|
if (lyricsList != null && lyricsList.getStructuredLyrics() != null && !lyricsList.getStructuredLyrics().isEmpty() && lyricsList.getStructuredLyrics().get(0).getLine() != null) {
|
||||||
|
StringBuilder lyricsBuilder = new StringBuilder();
|
||||||
|
List<Line> lines = lyricsList.getStructuredLyrics().get(0).getLine();
|
||||||
|
|
||||||
|
if (lines == null || lines.isEmpty()) return;
|
||||||
|
|
||||||
|
for (Line line : lines) {
|
||||||
|
lyricsBuilder.append(line.getValue().trim()).append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
Line toHighlight = lines.stream().filter(line -> line != null && line.getStart() != null && line.getStart() < timestamp).reduce((first, second) -> second).orElse(null);
|
||||||
|
|
||||||
|
if (toHighlight != null) {
|
||||||
|
String lyrics = lyricsBuilder.toString();
|
||||||
|
Spannable spannableString = new SpannableString(lyrics);
|
||||||
|
|
||||||
|
int startingPosition = getStartPosition(lines, toHighlight);
|
||||||
|
int endingPosition = startingPosition + toHighlight.getValue().length();
|
||||||
|
|
||||||
|
spannableString.setSpan(new ForegroundColorSpan(requireContext().getResources().getColor(R.color.shadowsLyricsTextColor, null)), 0, lyrics.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
spannableString.setSpan(new ForegroundColorSpan(requireContext().getResources().getColor(R.color.lyricsTextColor, null)), startingPosition, endingPosition, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
|
||||||
|
bind.nowPlayingSongLyricsTextView.setText(spannableString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getStartPosition(List<Line> lines, Line toHighlight) {
|
||||||
|
int start = 0;
|
||||||
|
|
||||||
|
for (Line line : lines) {
|
||||||
|
if (line != toHighlight) {
|
||||||
|
start = start + line.getValue().length() + 1;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return start;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -16,15 +16,18 @@ import com.cappielloantonio.tempo.model.Download;
|
||||||
import com.cappielloantonio.tempo.model.Queue;
|
import com.cappielloantonio.tempo.model.Queue;
|
||||||
import com.cappielloantonio.tempo.repository.ArtistRepository;
|
import com.cappielloantonio.tempo.repository.ArtistRepository;
|
||||||
import com.cappielloantonio.tempo.repository.FavoriteRepository;
|
import com.cappielloantonio.tempo.repository.FavoriteRepository;
|
||||||
|
import com.cappielloantonio.tempo.repository.OpenRepository;
|
||||||
import com.cappielloantonio.tempo.repository.QueueRepository;
|
import com.cappielloantonio.tempo.repository.QueueRepository;
|
||||||
import com.cappielloantonio.tempo.repository.SongRepository;
|
import com.cappielloantonio.tempo.repository.SongRepository;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.ArtistID3;
|
import com.cappielloantonio.tempo.subsonic.models.ArtistID3;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.Child;
|
import com.cappielloantonio.tempo.subsonic.models.Child;
|
||||||
|
import com.cappielloantonio.tempo.subsonic.models.LyricsList;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.PlayQueue;
|
import com.cappielloantonio.tempo.subsonic.models.PlayQueue;
|
||||||
import com.cappielloantonio.tempo.util.Constants;
|
import com.cappielloantonio.tempo.util.Constants;
|
||||||
import com.cappielloantonio.tempo.util.DownloadUtil;
|
import com.cappielloantonio.tempo.util.DownloadUtil;
|
||||||
import com.cappielloantonio.tempo.util.MappingUtil;
|
import com.cappielloantonio.tempo.util.MappingUtil;
|
||||||
import com.cappielloantonio.tempo.util.NetworkUtil;
|
import com.cappielloantonio.tempo.util.NetworkUtil;
|
||||||
|
import com.cappielloantonio.tempo.util.OpenSubsonicExtensionsUtil;
|
||||||
import com.cappielloantonio.tempo.util.Preferences;
|
import com.cappielloantonio.tempo.util.Preferences;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
@ -40,10 +43,10 @@ public class PlayerBottomSheetViewModel extends AndroidViewModel {
|
||||||
private final ArtistRepository artistRepository;
|
private final ArtistRepository artistRepository;
|
||||||
private final QueueRepository queueRepository;
|
private final QueueRepository queueRepository;
|
||||||
private final FavoriteRepository favoriteRepository;
|
private final FavoriteRepository favoriteRepository;
|
||||||
|
private final OpenRepository openRepository;
|
||||||
private final MutableLiveData<String> lyricsLiveData = new MutableLiveData<>(null);
|
private final MutableLiveData<String> lyricsLiveData = new MutableLiveData<>(null);
|
||||||
|
private final MutableLiveData<LyricsList> lyricsListLiveData = new MutableLiveData<>(null);
|
||||||
private final MutableLiveData<String> descriptionLiveData = new MutableLiveData<>(null);
|
private final MutableLiveData<String> descriptionLiveData = new MutableLiveData<>(null);
|
||||||
|
|
||||||
private final MutableLiveData<Child> liveMedia = new MutableLiveData<>(null);
|
private final MutableLiveData<Child> liveMedia = new MutableLiveData<>(null);
|
||||||
private final MutableLiveData<ArtistID3> liveArtist = new MutableLiveData<>(null);
|
private final MutableLiveData<ArtistID3> liveArtist = new MutableLiveData<>(null);
|
||||||
private final MutableLiveData<List<Child>> instantMix = new MutableLiveData<>(null);
|
private final MutableLiveData<List<Child>> instantMix = new MutableLiveData<>(null);
|
||||||
|
|
@ -56,6 +59,7 @@ public class PlayerBottomSheetViewModel extends AndroidViewModel {
|
||||||
artistRepository = new ArtistRepository();
|
artistRepository = new ArtistRepository();
|
||||||
queueRepository = new QueueRepository();
|
queueRepository = new QueueRepository();
|
||||||
favoriteRepository = new FavoriteRepository();
|
favoriteRepository = new FavoriteRepository();
|
||||||
|
openRepository = new OpenRepository();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<Queue>> getQueueSong() {
|
public LiveData<List<Queue>> getQueueSong() {
|
||||||
|
|
@ -125,8 +129,18 @@ public class PlayerBottomSheetViewModel extends AndroidViewModel {
|
||||||
return lyricsLiveData;
|
return lyricsLiveData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LiveData<LyricsList> getLiveLyricsList() {
|
||||||
|
return lyricsListLiveData;
|
||||||
|
}
|
||||||
|
|
||||||
public void refreshMediaInfo(LifecycleOwner owner, Child media) {
|
public void refreshMediaInfo(LifecycleOwner owner, Child media) {
|
||||||
songRepository.getSongLyrics(media).observe(owner, lyricsLiveData::postValue);
|
if (OpenSubsonicExtensionsUtil.isSongLyricsExtensionAvailable()) {
|
||||||
|
openRepository.getLyricsBySongId(media.getId()).observe(owner, lyricsListLiveData::postValue);
|
||||||
|
lyricsLiveData.postValue(null);
|
||||||
|
} else {
|
||||||
|
songRepository.getSongLyrics(media).observe(owner, lyricsLiveData::postValue);
|
||||||
|
lyricsListLiveData.postValue(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Child> getLiveMedia() {
|
public LiveData<Child> getLiveMedia() {
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
app:layout_constraintTop_toBottomOf="@+id/empty_description_image_view" />
|
app:layout_constraintTop_toBottomOf="@+id/empty_description_image_view" />
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:id="@+id/now_playing_song_lyrics_sroll_view"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@
|
||||||
<color name="subtitleTextColor">#9B9B9B</color>
|
<color name="subtitleTextColor">#9B9B9B</color>
|
||||||
<color name="dividerColor">#404040</color>
|
<color name="dividerColor">#404040</color>
|
||||||
|
|
||||||
|
<color name="lyricsTextColor">#DADADA</color>
|
||||||
|
<color name="shadowsLyricsTextColor">#606060</color>
|
||||||
|
|
||||||
<color name="searchPlaceholderColor">#CFCFCF</color>
|
<color name="searchPlaceholderColor">#CFCFCF</color>
|
||||||
<color name="searchColor">#DADADA</color>
|
<color name="searchColor">#DADADA</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,9 @@
|
||||||
<color name="dividerColor">#e0e0e0</color>
|
<color name="dividerColor">#e0e0e0</color>
|
||||||
<color name="white">#FFFFFF</color>
|
<color name="white">#FFFFFF</color>
|
||||||
|
|
||||||
|
<color name="lyricsTextColor">#252525</color>
|
||||||
|
<color name="shadowsLyricsTextColor">#B4B4B4</color>
|
||||||
|
|
||||||
<color name="searchPlaceholderColor">#303030</color>
|
<color name="searchPlaceholderColor">#303030</color>
|
||||||
<color name="searchColor">#252525</color>
|
<color name="searchColor">#252525</color>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue