diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java index 4d018236..68d890dc 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java @@ -13,7 +13,7 @@ import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.helper.MusicPlayerRemote; import com.kabouzeid.gramophone.ui.fragments.player.AbsPlayerFragment; import com.kabouzeid.gramophone.ui.fragments.player.MiniPlayerFragment; -import com.kabouzeid.gramophone.ui.fragments.player.PlayerFragment; +import com.kabouzeid.gramophone.ui.fragments.player.card.CardPlayerFragment; import com.sothree.slidinguppanel.SlidingUpPanelLayout; import butterknife.Bind; @@ -25,7 +25,7 @@ import butterknife.ButterKnife; * Do not use {@link #setContentView(int)}. Instead wrap your layout with * {@link #wrapSlidingMusicPanel(int)} first and then return it in {@link #createContentView()} */ -public abstract class AbsSlidingMusicPanelActivity extends AbsMusicServiceActivity implements SlidingUpPanelLayout.PanelSlideListener, PlayerFragment.Callbacks { +public abstract class AbsSlidingMusicPanelActivity extends AbsMusicServiceActivity implements SlidingUpPanelLayout.PanelSlideListener, CardPlayerFragment.Callbacks { public static final String TAG = AbsSlidingMusicPanelActivity.class.getSimpleName(); @Bind(R.id.sliding_layout) diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/PlayerAlbumCoverFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/PlayerAlbumCoverFragment.java index 1f1838fc..a93cda29 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/PlayerAlbumCoverFragment.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/PlayerAlbumCoverFragment.java @@ -168,7 +168,7 @@ public class PlayerAlbumCoverFragment extends AbsMusicServiceFragment implements callbacks = listener; } - interface Callbacks { + public interface Callbacks { void onColorChanged(int color); void onFavoriteToggled(); diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/PlayerFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java similarity index 90% rename from app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/PlayerFragment.java rename to app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java index bc0bb8b2..5c18e485 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/PlayerFragment.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerFragment.java @@ -1,4 +1,4 @@ -package com.kabouzeid.gramophone.ui.fragments.player; +package com.kabouzeid.gramophone.ui.fragments.player.card; import android.animation.Animator; import android.animation.AnimatorSet; @@ -43,6 +43,8 @@ import com.kabouzeid.gramophone.helper.MusicPlayerRemote; import com.kabouzeid.gramophone.helper.menu.SongMenuHelper; import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.ui.activities.base.AbsSlidingMusicPanelActivity; +import com.kabouzeid.gramophone.ui.fragments.player.AbsPlayerFragment; +import com.kabouzeid.gramophone.ui.fragments.player.PlayerAlbumCoverFragment; import com.kabouzeid.gramophone.util.MusicUtil; import com.kabouzeid.gramophone.util.Util; import com.kabouzeid.gramophone.util.ViewUtil; @@ -57,8 +59,8 @@ import java.io.File; import butterknife.Bind; import butterknife.ButterKnife; -public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCoverFragment.Callbacks, SlidingUpPanelLayout.PanelSlideListener { - public static final String TAG = PlayerFragment.class.getSimpleName(); +public class CardPlayerFragment extends AbsPlayerFragment implements PlayerAlbumCoverFragment.Callbacks, SlidingUpPanelLayout.PanelSlideListener { + public static final String TAG = CardPlayerFragment.class.getSimpleName(); @Bind(R.id.player_toolbar) Toolbar toolbar; @@ -75,7 +77,7 @@ public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCove private int lastColor; - private PlaybackControlsFragment playbackControlsFragment; + private CardPlayerPlaybackControlsFragment playbackControlsFragment; private PlayerAlbumCoverFragment playerAlbumCoverFragment; private LinearLayoutManager layoutManager; @@ -100,7 +102,7 @@ public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCove impl = new PortraitImpl(); } - View view = inflater.inflate(R.layout.fragment_player, container, false); + View view = inflater.inflate(R.layout.fragment_card_player, container, false); ButterKnife.bind(this, view); return view; } @@ -123,7 +125,7 @@ public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCove @Override public void onGlobalLayout() { view.getViewTreeObserver().removeOnGlobalLayoutListener(this); - impl.setUpPanelAndAlbumCoverHeight(PlayerFragment.this); + impl.setUpPanelAndAlbumCoverHeight(CardPlayerFragment.this); } }); @@ -211,7 +213,7 @@ public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCove } private void setUpSubFragments() { - playbackControlsFragment = (PlaybackControlsFragment) getChildFragmentManager().findFragmentById(R.id.playback_controls_fragment); + playbackControlsFragment = (CardPlayerPlaybackControlsFragment) getChildFragmentManager().findFragmentById(R.id.playback_controls_fragment); playerAlbumCoverFragment = (PlayerAlbumCoverFragment) getChildFragmentManager().findFragmentById(R.id.player_album_cover_fragment); playerAlbumCoverFragment.setCallbacks(this); @@ -433,17 +435,17 @@ public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCove } interface Impl { - void init(PlayerFragment fragment); + void init(CardPlayerFragment fragment); - void updateCurrentSong(PlayerFragment fragment, Song song); + void updateCurrentSong(CardPlayerFragment fragment, Song song); - void animateColorChange(PlayerFragment fragment, final int newColor); + void animateColorChange(CardPlayerFragment fragment, final int newColor); - void setUpPanelAndAlbumCoverHeight(PlayerFragment fragment); + void setUpPanelAndAlbumCoverHeight(CardPlayerFragment fragment); } private static abstract class BaseImpl implements Impl { - public AnimatorSet createDefaultColorChangeAnimatorSet(PlayerFragment fragment, int newColor) { + public AnimatorSet createDefaultColorChangeAnimatorSet(CardPlayerFragment fragment, int newColor) { Animator backgroundAnimator; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { int topMargin = fragment.getResources().getDimensionPixelSize(R.dimen.status_bar_padding); @@ -462,8 +464,10 @@ public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCove animatorSet.play(backgroundAnimator); - Animator subHeaderAnimator = ATHUtil.isWindowBackgroundDark(fragment.getActivity()) ? null : ViewUtil.createTextColorTransition(fragment.playerQueueSubHeader, fragment.lastColor, newColor); - if (subHeaderAnimator != null) { + if (!ATHUtil.isWindowBackgroundDark(fragment.getActivity())) { + int adjustedLastColor = ColorUtil.isColorLight(fragment.lastColor) ? ColorUtil.darkenColor(fragment.lastColor) : fragment.lastColor; + int adjustedNewColor = ColorUtil.isColorLight(newColor) ? ColorUtil.darkenColor(newColor) : newColor; + Animator subHeaderAnimator = ViewUtil.createTextColorTransition(fragment.playerQueueSubHeader, adjustedLastColor, adjustedNewColor); animatorSet.play(subHeaderAnimator); } @@ -472,7 +476,7 @@ public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCove } @Override - public void animateColorChange(PlayerFragment fragment, int newColor) { + public void animateColorChange(CardPlayerFragment fragment, int newColor) { if (ATHUtil.isWindowBackgroundDark(fragment.getActivity())) { fragment.playerQueueSubHeader.setTextColor(ThemeStore.textColorSecondary(fragment.getActivity())); } @@ -485,7 +489,7 @@ public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCove Song currentSong = new Song(); @Override - public void init(final PlayerFragment fragment) { + public void init(final CardPlayerFragment fragment) { currentSongViewHolder = new MediaEntryViewHolder(fragment.getView().findViewById(R.id.current_song)); currentSongViewHolder.separator.setVisibility(View.VISIBLE); @@ -530,7 +534,7 @@ public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCove } @Override - public void setUpPanelAndAlbumCoverHeight(PlayerFragment fragment) { + public void setUpPanelAndAlbumCoverHeight(CardPlayerFragment fragment) { WidthFitSquareLayout albumCoverContainer = (WidthFitSquareLayout) fragment.getView().findViewById(R.id.album_cover_container); int topMargin = fragment.getResources().getDimensionPixelSize(R.dimen.status_bar_padding); @@ -546,14 +550,14 @@ public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCove } @Override - public void updateCurrentSong(PlayerFragment fragment, Song song) { + public void updateCurrentSong(CardPlayerFragment fragment, Song song) { currentSong = song; currentSongViewHolder.title.setText(song.title); currentSongViewHolder.text.setText(song.artistName); } @Override - public void animateColorChange(PlayerFragment fragment, int newColor) { + public void animateColorChange(CardPlayerFragment fragment, int newColor) { super.animateColorChange(fragment, newColor); fragment.slidingUpPanelLayout.setBackgroundColor(fragment.lastColor); @@ -565,12 +569,12 @@ public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCove @SuppressWarnings("ConstantConditions") private static class LandscapeImpl extends BaseImpl { @Override - public void init(PlayerFragment fragment) { + public void init(CardPlayerFragment fragment) { } @Override - public void setUpPanelAndAlbumCoverHeight(PlayerFragment fragment) { + public void setUpPanelAndAlbumCoverHeight(CardPlayerFragment fragment) { int topMargin = fragment.getResources().getDimensionPixelSize(R.dimen.status_bar_padding); int panelHeight = fragment.slidingUpPanelLayout.getHeight() - fragment.playbackControlsFragment.getView().getHeight() + topMargin; fragment.slidingUpPanelLayout.setPanelHeight(panelHeight); @@ -579,13 +583,13 @@ public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCove } @Override - public void updateCurrentSong(PlayerFragment fragment, Song song) { + public void updateCurrentSong(CardPlayerFragment fragment, Song song) { fragment.toolbar.setTitle(song.title); fragment.toolbar.setSubtitle(song.artistName); } @Override - public void animateColorChange(PlayerFragment fragment, int newColor) { + public void animateColorChange(CardPlayerFragment fragment, int newColor) { super.animateColorChange(fragment, newColor); fragment.slidingUpPanelLayout.setBackgroundColor(fragment.lastColor); diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/PlaybackControlsFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerPlaybackControlsFragment.java similarity index 97% rename from app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/PlaybackControlsFragment.java rename to app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerPlaybackControlsFragment.java index aba3f45d..57c921bb 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/PlaybackControlsFragment.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/card/CardPlayerPlaybackControlsFragment.java @@ -1,4 +1,4 @@ -package com.kabouzeid.gramophone.ui.fragments.player; +package com.kabouzeid.gramophone.ui.fragments.player.card; import android.graphics.Color; import android.graphics.PorterDuff; @@ -31,7 +31,7 @@ import butterknife.ButterKnife; /** * @author Karim Abou Zeid (kabouzeid) */ -public class PlaybackControlsFragment extends AbsMusicServiceFragment implements MusicProgressViewUpdateHelper.Callback { +public class CardPlayerPlaybackControlsFragment extends AbsMusicServiceFragment implements MusicProgressViewUpdateHelper.Callback { @Bind(R.id.player_play_pause_fab) FloatingActionButton playPauseFab; @@ -67,7 +67,7 @@ public class PlaybackControlsFragment extends AbsMusicServiceFragment implements @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_playback_controls, container, false); + return inflater.inflate(R.layout.fragment_card_player_playback_controls, container, false); } @Override diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java new file mode 100644 index 00000000..63e55fcd --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerFragment.java @@ -0,0 +1,535 @@ +package com.kabouzeid.gramophone.ui.fragments.player.flat; + +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.app.Activity; +import android.graphics.Color; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.annotation.ColorInt; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.Toolbar; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.widget.ImageView; +import android.widget.TextView; + +import com.h6ah4i.android.widget.advrecyclerview.animator.GeneralItemAnimator; +import com.h6ah4i.android.widget.advrecyclerview.animator.RefactoredDefaultItemAnimator; +import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager; +import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils; +import com.kabouzeid.appthemehelper.ThemeStore; +import com.kabouzeid.appthemehelper.util.ATHUtil; +import com.kabouzeid.appthemehelper.util.ColorUtil; +import com.kabouzeid.appthemehelper.util.ToolbarContentTintHelper; +import com.kabouzeid.gramophone.R; +import com.kabouzeid.gramophone.adapter.base.MediaEntryViewHolder; +import com.kabouzeid.gramophone.adapter.song.PlayingQueueAdapter; +import com.kabouzeid.gramophone.dialogs.LyricsDialog; +import com.kabouzeid.gramophone.dialogs.SongShareDialog; +import com.kabouzeid.gramophone.helper.MusicPlayerRemote; +import com.kabouzeid.gramophone.helper.menu.SongMenuHelper; +import com.kabouzeid.gramophone.model.Song; +import com.kabouzeid.gramophone.ui.activities.base.AbsSlidingMusicPanelActivity; +import com.kabouzeid.gramophone.ui.fragments.player.AbsPlayerFragment; +import com.kabouzeid.gramophone.ui.fragments.player.PlayerAlbumCoverFragment; +import com.kabouzeid.gramophone.util.MusicUtil; +import com.kabouzeid.gramophone.util.Util; +import com.kabouzeid.gramophone.util.ViewUtil; +import com.kabouzeid.gramophone.views.WidthFitSquareLayout; +import com.sothree.slidinguppanel.SlidingUpPanelLayout; + +import org.jaudiotagger.audio.AudioFileIO; +import org.jaudiotagger.tag.FieldKey; + +import java.io.File; + +import butterknife.Bind; +import butterknife.ButterKnife; + +public class FlatPlayerFragment extends AbsPlayerFragment implements PlayerAlbumCoverFragment.Callbacks, SlidingUpPanelLayout.PanelSlideListener { + public static final String TAG = FlatPlayerFragment.class.getSimpleName(); + + @Bind(R.id.player_status_bar) + View playerStatusBar; + @Bind(R.id.player_toolbar) + Toolbar toolbar; + @Bind(R.id.player_sliding_layout) + SlidingUpPanelLayout slidingUpPanelLayout; + @Bind(R.id.player_recycler_view) + RecyclerView recyclerView; + @Bind(R.id.player_queue_sub_header) + TextView playerQueueSubHeader; + + private int lastColor; + + private FlatPlayerPlaybackControlsFragment playbackControlsFragment; + private PlayerAlbumCoverFragment playerAlbumCoverFragment; + + private LinearLayoutManager layoutManager; + + private PlayingQueueAdapter playingQueueAdapter; + + private RecyclerView.Adapter wrappedAdapter; + private RecyclerViewDragDropManager recyclerViewDragDropManager; + + private AsyncTask updateIsFavoriteTask; + private AsyncTask updateLyricsAsyncTask; + + private LyricsDialog.LyricInfo lyricsInfo; + + private Impl impl; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + impl = new PortraitImpl(); + + View view = inflater.inflate(R.layout.fragment_flat_player, container, false); + ButterKnife.bind(this, view); + return view; + } + + @Override + public void onViewCreated(final View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + impl.init(this); + + setUpPlayerToolbar(); + setUpSubFragments(); + + setUpRecyclerView(); + + slidingUpPanelLayout.addPanelSlideListener(this); + slidingUpPanelLayout.setAntiDragView(view.findViewById(R.id.draggable_area)); + + view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + view.getViewTreeObserver().removeOnGlobalLayoutListener(this); + impl.setUpPanelAndAlbumCoverHeight(FlatPlayerFragment.this); + } + }); + } + + @Override + public void onDestroyView() { + if (slidingUpPanelLayout != null) { + slidingUpPanelLayout.removePanelSlideListener(this); + } + if (recyclerViewDragDropManager != null) { + recyclerViewDragDropManager.release(); + recyclerViewDragDropManager = null; + } + + if (recyclerView != null) { + recyclerView.setItemAnimator(null); + recyclerView.setAdapter(null); + recyclerView = null; + } + + if (wrappedAdapter != null) { + WrapperAdapterUtils.releaseAll(wrappedAdapter); + wrappedAdapter = null; + } + playingQueueAdapter = null; + layoutManager = null; + super.onDestroyView(); + ButterKnife.unbind(this); + } + + @Override + public void onPause() { + if (recyclerViewDragDropManager != null) { + recyclerViewDragDropManager.cancelDrag(); + } + super.onPause(); + } + + @Override + public void onServiceConnected() { + updateQueue(); + updateCurrentSong(); + updateIsFavorite(); + updateLyrics(); + } + + @Override + public void onPlayingMetaChanged() { + updateCurrentSong(); + updateIsFavorite(); + updateQueuePosition(); + updateLyrics(); + } + + @Override + public void onQueueChanged() { + updateQueue(); + } + + @Override + public void onMediaStoreChanged() { + updateQueue(); + } + + private void updateQueue() { + playingQueueAdapter.swapDataSet(MusicPlayerRemote.getPlayingQueue(), MusicPlayerRemote.getPosition()); + if (slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) { + resetToCurrentPosition(); + } + } + + private void updateQueuePosition() { + playingQueueAdapter.setCurrent(MusicPlayerRemote.getPosition()); + if (slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) { + resetToCurrentPosition(); + } + } + + @SuppressWarnings("ConstantConditions") + private void updateCurrentSong() { + impl.updateCurrentSong(this, MusicPlayerRemote.getCurrentSong()); + } + + private void setUpSubFragments() { + playbackControlsFragment = (FlatPlayerPlaybackControlsFragment) getChildFragmentManager().findFragmentById(R.id.playback_controls_fragment); + playerAlbumCoverFragment = (PlayerAlbumCoverFragment) getChildFragmentManager().findFragmentById(R.id.player_album_cover_fragment); + + playerAlbumCoverFragment.setCallbacks(this); + } + + private void setUpPlayerToolbar() { + toolbar.inflateMenu(R.menu.menu_player); + toolbar.setNavigationIcon(R.drawable.ic_close_white_24dp); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + getActivity().onBackPressed(); + } + }); + toolbar.setOnMenuItemClickListener(this); + } + + @Override + public boolean onMenuItemClick(MenuItem item) { + switch (item.getItemId()) { + case R.id.action_show_lyrics: + if (lyricsInfo != null) + LyricsDialog.create(lyricsInfo).show(getFragmentManager(), "LYRICS"); + return true; + } + return super.onMenuItemClick(item); + } + + private void setUpRecyclerView() { + recyclerViewDragDropManager = new RecyclerViewDragDropManager(); + final GeneralItemAnimator animator = new RefactoredDefaultItemAnimator(); + + playingQueueAdapter = new PlayingQueueAdapter( + ((AppCompatActivity) getActivity()), + MusicPlayerRemote.getPlayingQueue(), + MusicPlayerRemote.getPosition(), + R.layout.item_list, + false, + null); + wrappedAdapter = recyclerViewDragDropManager.createWrappedAdapter(playingQueueAdapter); + + layoutManager = new LinearLayoutManager(getActivity()); + + recyclerView.setLayoutManager(layoutManager); + recyclerView.setAdapter(wrappedAdapter); + recyclerView.setItemAnimator(animator); + + recyclerViewDragDropManager.attachRecyclerView(recyclerView); + + layoutManager.scrollToPositionWithOffset(MusicPlayerRemote.getPosition() + 1, 0); + } + + + private void updateIsFavorite() { + if (updateIsFavoriteTask != null) updateIsFavoriteTask.cancel(false); + updateIsFavoriteTask = new AsyncTask() { + @Override + protected Boolean doInBackground(Song... params) { + Activity activity = getActivity(); + if (activity != null) { + return MusicUtil.isFavorite(getActivity(), params[0]); + } else { + cancel(false); + return null; + } + } + + @Override + protected void onPostExecute(Boolean isFavorite) { + Activity activity = getActivity(); + if (activity != null) { + int res = isFavorite ? R.drawable.ic_favorite_white_24dp : R.drawable.ic_favorite_border_white_24dp; + int color = ToolbarContentTintHelper.toolbarContentColor(activity, Color.TRANSPARENT); + Drawable drawable = Util.getTintedVectorDrawable(activity, res, color); + toolbar.getMenu().findItem(R.id.action_toggle_favorite) + .setIcon(drawable) + .setTitle(isFavorite ? getString(R.string.action_remove_from_favorites) : getString(R.string.action_add_to_favorites)); + } + } + }.execute(MusicPlayerRemote.getCurrentSong()); + } + + private void updateLyrics() { + if (updateLyricsAsyncTask != null) updateLyricsAsyncTask.cancel(false); + final Song song = MusicPlayerRemote.getCurrentSong(); + updateLyricsAsyncTask = new AsyncTask() { + @Override + protected void onPreExecute() { + super.onPreExecute(); + lyricsInfo = null; + toolbar.getMenu().removeItem(R.id.action_show_lyrics); + } + + @Override + protected String doInBackground(Void... params) { + try { + return AudioFileIO.read(new File(song.data)).getTagOrCreateDefault().getFirst(FieldKey.LYRICS); + } catch (Exception e) { + e.printStackTrace(); + cancel(false); + return null; + } + } + + @Override + protected void onPostExecute(String lyrics) { + super.onPostExecute(lyrics); + if (TextUtils.isEmpty(lyrics)) { + lyricsInfo = null; + if (toolbar != null) { + toolbar.getMenu().removeItem(R.id.action_show_lyrics); + } + } else { + lyricsInfo = new LyricsDialog.LyricInfo(song.title, lyrics); + Activity activity = getActivity(); + if (toolbar != null && activity != null) + if (toolbar.getMenu().findItem(R.id.action_show_lyrics) == null) { + int color = ToolbarContentTintHelper.toolbarContentColor(activity, Color.TRANSPARENT); + Drawable drawable = Util.getTintedVectorDrawable(activity, R.drawable.ic_comment_text_outline_white_24dp, color); + toolbar.getMenu() + .add(Menu.NONE, R.id.action_show_lyrics, Menu.NONE, R.string.action_show_lyrics) + .setIcon(drawable) + .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); + } + } + } + + @Override + protected void onCancelled(String s) { + onPostExecute(null); + } + }.execute(); + } + + @Override + @ColorInt + public int getPaletteColor() { + return lastColor; + } + + private void animateColorChange(final int newColor) { + impl.animateColorChange(this, newColor); + lastColor = newColor; + } + + @Override + protected void toggleFavorite(Song song) { + super.toggleFavorite(song); + if (song.id == MusicPlayerRemote.getCurrentSong().id) { + if (MusicUtil.isFavorite(getActivity(), song)) { + playerAlbumCoverFragment.showHeartAnimation(); + } + updateIsFavorite(); + } + } + + @Override + public void onShow() { + playbackControlsFragment.show(); + } + + @Override + public void onHide() { + playbackControlsFragment.hide(); + onBackPressed(); + } + + @Override + public boolean onBackPressed() { + boolean wasExpanded = false; + if (slidingUpPanelLayout != null) { + wasExpanded = slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED; + slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); + } + + return wasExpanded; + } + + @Override + public void onColorChanged(int color) { + animateColorChange(color); + playbackControlsFragment.setDark(ColorUtil.isColorLight(color)); + getCallbacks().onPaletteColorChanged(); + } + + @Override + public void onFavoriteToggled() { + toggleFavorite(MusicPlayerRemote.getCurrentSong()); + } + + @Override + public void onPanelSlide(View view, float slide) { + } + + @Override + public void onPanelStateChanged(View panel, SlidingUpPanelLayout.PanelState previousState, SlidingUpPanelLayout.PanelState newState) { + switch (newState) { + case COLLAPSED: + onPanelCollapsed(panel); + break; + case ANCHORED: + slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); // this fixes a bug where the panel would get stuck for some reason + break; + } + } + + public void onPanelCollapsed(View panel) { + resetToCurrentPosition(); + } + + private void resetToCurrentPosition() { + recyclerView.stopScroll(); + layoutManager.scrollToPositionWithOffset(MusicPlayerRemote.getPosition() + 1, 0); + } + + interface Impl { + void init(FlatPlayerFragment fragment); + + void updateCurrentSong(FlatPlayerFragment fragment, Song song); + + void animateColorChange(FlatPlayerFragment fragment, final int newColor); + + void setUpPanelAndAlbumCoverHeight(FlatPlayerFragment fragment); + } + + private static abstract class BaseImpl implements Impl { + public AnimatorSet createDefaultColorChangeAnimatorSet(FlatPlayerFragment fragment, int newColor) { + Animator backgroundAnimator = ViewUtil.createBackgroundColorTransition(fragment.playbackControlsFragment.getView(), fragment.lastColor, newColor); + Animator statusBarAnimator = ViewUtil.createBackgroundColorTransition(fragment.playerStatusBar, ColorUtil.darkenColor(fragment.lastColor), ColorUtil.darkenColor(newColor)); + + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.playTogether(backgroundAnimator, statusBarAnimator); + + if (!ATHUtil.isWindowBackgroundDark(fragment.getActivity())) { + int adjustedLastColor = ColorUtil.isColorLight(fragment.lastColor) ? ColorUtil.darkenColor(fragment.lastColor) : fragment.lastColor; + int adjustedNewColor = ColorUtil.isColorLight(newColor) ? ColorUtil.darkenColor(newColor) : newColor; + Animator subHeaderAnimator = ViewUtil.createTextColorTransition(fragment.playerQueueSubHeader, adjustedLastColor, adjustedNewColor); + animatorSet.play(subHeaderAnimator); + } + + animatorSet.setDuration(ViewUtil.PHONOGRAPH_ANIM_TIME); + return animatorSet; + } + + @Override + public void animateColorChange(FlatPlayerFragment fragment, int newColor) { + if (ATHUtil.isWindowBackgroundDark(fragment.getActivity())) { + fragment.playerQueueSubHeader.setTextColor(ThemeStore.textColorSecondary(fragment.getActivity())); + } + } + } + + @SuppressWarnings("ConstantConditions") + private static class PortraitImpl extends BaseImpl { + MediaEntryViewHolder currentSongViewHolder; + Song currentSong = new Song(); + + @Override + public void init(final FlatPlayerFragment fragment) { + currentSongViewHolder = new MediaEntryViewHolder(fragment.getView().findViewById(R.id.current_song)); + + currentSongViewHolder.separator.setVisibility(View.VISIBLE); + currentSongViewHolder.shortSeparator.setVisibility(View.GONE); + currentSongViewHolder.image.setScaleType(ImageView.ScaleType.CENTER); + currentSongViewHolder.image.setColorFilter(ATHUtil.resolveColor(fragment.getActivity(), R.attr.iconColor, ThemeStore.textColorSecondary(fragment.getActivity())), PorterDuff.Mode.SRC_IN); + currentSongViewHolder.image.setImageResource(R.drawable.ic_volume_up_white_24dp); + currentSongViewHolder.itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + // toggle the panel + if (fragment.slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) { + fragment.slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED); + } else if (fragment.slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { + fragment.slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); + } + } + }); + currentSongViewHolder.menu.setOnClickListener(new SongMenuHelper.OnClickSongMenu((AppCompatActivity) fragment.getActivity()) { + @Override + public Song getSong() { + return currentSong; + } + + public int getMenuRes() { + return R.menu.menu_item_playing_queue_song; + } + + @Override + public boolean onMenuItemClick(MenuItem item) { + switch (item.getItemId()) { + case R.id.action_remove_from_playing_queue: + MusicPlayerRemote.removeFromQueue(MusicPlayerRemote.getPosition()); + return true; + case R.id.action_share: + SongShareDialog.create(getSong()).show(fragment.getFragmentManager(), "SONG_SHARE_DIALOG"); + return true; + } + return super.onMenuItemClick(item); + } + }); + } + + @Override + public void setUpPanelAndAlbumCoverHeight(FlatPlayerFragment fragment) { + WidthFitSquareLayout albumCoverContainer = (WidthFitSquareLayout) fragment.getView().findViewById(R.id.album_cover_container); + + final int availablePanelHeight = fragment.slidingUpPanelLayout.getHeight() - fragment.getView().findViewById(R.id.player_content).getHeight(); + final int minPanelHeight = (int) ViewUtil.convertDpToPixel(8 + 72 + 24, fragment.getResources()) + fragment.getResources().getDimensionPixelSize(R.dimen.progress_container_height) + fragment.getResources().getDimensionPixelSize(R.dimen.media_controller_container_height); + if (availablePanelHeight < minPanelHeight) { + albumCoverContainer.getLayoutParams().height = albumCoverContainer.getHeight() - (minPanelHeight - availablePanelHeight); + albumCoverContainer.forceSquare(false); + } + fragment.slidingUpPanelLayout.setPanelHeight(Math.max(minPanelHeight, availablePanelHeight)); + + ((AbsSlidingMusicPanelActivity) fragment.getActivity()).setAntiDragView(fragment.slidingUpPanelLayout.findViewById(R.id.player_panel)); + } + + @Override + public void updateCurrentSong(FlatPlayerFragment fragment, Song song) { + currentSong = song; + currentSongViewHolder.title.setText(song.title); + currentSongViewHolder.text.setText(song.artistName); + } + + @Override + public void animateColorChange(FlatPlayerFragment fragment, int newColor) { + super.animateColorChange(fragment, newColor); + createDefaultColorChangeAnimatorSet(fragment, newColor).start(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerPlaybackControlsFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerPlaybackControlsFragment.java new file mode 100644 index 00000000..72fe8579 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/player/flat/FlatPlayerPlaybackControlsFragment.java @@ -0,0 +1,329 @@ +package com.kabouzeid.gramophone.ui.fragments.player.flat; + +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.animation.TimeInterpolator; +import android.graphics.Color; +import android.graphics.PorterDuff; +import android.os.Bundle; +import android.support.v4.view.animation.FastOutSlowInInterpolator; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageButton; +import android.widget.SeekBar; +import android.widget.TextView; + +import com.kabouzeid.appthemehelper.util.MaterialValueHelper; +import com.kabouzeid.gramophone.R; +import com.kabouzeid.gramophone.helper.MusicPlayerRemote; +import com.kabouzeid.gramophone.helper.MusicProgressViewUpdateHelper; +import com.kabouzeid.gramophone.helper.PlayPauseButtonOnClickHandler; +import com.kabouzeid.gramophone.misc.SimpleOnSeekbarChangeListener; +import com.kabouzeid.gramophone.service.MusicService; +import com.kabouzeid.gramophone.ui.fragments.AbsMusicServiceFragment; +import com.kabouzeid.gramophone.util.MusicUtil; +import com.kabouzeid.gramophone.views.PlayPauseDrawable; + +import java.util.Collection; +import java.util.LinkedList; + +import butterknife.Bind; +import butterknife.ButterKnife; + +/** + * @author Karim Abou Zeid (kabouzeid) + */ +public class FlatPlayerPlaybackControlsFragment extends AbsMusicServiceFragment implements MusicProgressViewUpdateHelper.Callback { + + @Bind(R.id.player_play_pause__button) + ImageButton playPauseButton; + @Bind(R.id.player_prev_button) + ImageButton prevButton; + @Bind(R.id.player_next_button) + ImageButton nextButton; + @Bind(R.id.player_repeat_button) + ImageButton repeatButton; + @Bind(R.id.player_shuffle_button) + ImageButton shuffleButton; + + @Bind(R.id.player_progress_slider) + SeekBar progressSlider; + @Bind(R.id.player_song_total_time) + TextView songTotalTime; + @Bind(R.id.player_song_current_progress) + TextView songCurrentProgress; + + private PlayPauseDrawable playPauseDrawable; + + private int lastPlaybackControlsColor; + private int lastDisabledPlaybackControlsColor; + + private MusicProgressViewUpdateHelper progressViewUpdateHelper; + + private AnimatorSet musicControllerAnimationSet; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + progressViewUpdateHelper = new MusicProgressViewUpdateHelper(this); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_flat_player_playback_controls, container, false); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + ButterKnife.bind(this, view); + setUpMusicControllers(); + updateProgressTextColor(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + ButterKnife.unbind(this); + } + + @Override + public void onResume() { + super.onResume(); + progressViewUpdateHelper.start(); + } + + @Override + public void onPause() { + super.onPause(); + progressViewUpdateHelper.stop(); + } + + @Override + public void onServiceConnected() { + updatePlayPauseDrawableState(false); + updateRepeatState(); + updateShuffleState(); + } + + @Override + public void onPlayStateChanged() { + updatePlayPauseDrawableState(true); + } + + @Override + public void onRepeatModeChanged() { + updateRepeatState(); + } + + @Override + public void onShuffleModeChanged() { + updateShuffleState(); + } + + public void setDark(boolean dark) { + if (dark) { + lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(getActivity(), true); + lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(getActivity(), true); + } else { + lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(getActivity(), false); + lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(getActivity(), false); + } + + updateRepeatState(); + updateShuffleState(); + updatePrevNextColor(); + updatePlayPauseColor(); + updateProgressTextColor(); + } + + private void setUpPlayPauseButton() { + playPauseDrawable = new PlayPauseDrawable(getActivity()); + playPauseButton.setImageDrawable(playPauseDrawable); + updatePlayPauseColor(); + playPauseButton.setOnClickListener(new PlayPauseButtonOnClickHandler()); + playPauseButton.post(new Runnable() { + @Override + public void run() { + if (playPauseButton != null) { + playPauseButton.setPivotX(playPauseButton.getWidth() / 2); + playPauseButton.setPivotY(playPauseButton.getHeight() / 2); + } + } + }); + } + + protected void updatePlayPauseDrawableState(boolean animate) { + if (MusicPlayerRemote.isPlaying()) { + playPauseDrawable.setPause(animate); + } else { + playPauseDrawable.setPlay(animate); + } + } + + private void setUpMusicControllers() { + setUpPlayPauseButton(); + setUpPrevNext(); + setUpRepeatButton(); + setUpShuffleButton(); + setUpProgressSlider(); + } + + private void setUpPrevNext() { + updatePrevNextColor(); + nextButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + MusicPlayerRemote.playNextSong(); + } + }); + prevButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + MusicPlayerRemote.back(); + } + }); + } + + private void updateProgressTextColor() { + int color = MaterialValueHelper.getPrimaryTextColor(getContext(), false); + songTotalTime.setTextColor(color); + songCurrentProgress.setTextColor(color); + } + + private void updatePrevNextColor() { + nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN); + prevButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN); + } + + private void updatePlayPauseColor() { + playPauseButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN); + } + + private void setUpShuffleButton() { + shuffleButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + MusicPlayerRemote.toggleShuffleMode(); + } + }); + } + + private void updateShuffleState() { + switch (MusicPlayerRemote.getShuffleMode()) { + case MusicService.SHUFFLE_MODE_SHUFFLE: + shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN); + break; + default: + shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN); + break; + } + } + + private void setUpRepeatButton() { + repeatButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + MusicPlayerRemote.cycleRepeatMode(); + } + }); + } + + private void updateRepeatState() { + switch (MusicPlayerRemote.getRepeatMode()) { + case MusicService.REPEAT_MODE_NONE: + repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp); + repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN); + break; + case MusicService.REPEAT_MODE_ALL: + repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp); + repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN); + break; + case MusicService.REPEAT_MODE_THIS: + repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp); + repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN); + break; + } + } + + public void show() { + if (musicControllerAnimationSet == null) { + TimeInterpolator interpolator = new FastOutSlowInInterpolator(); + final int duration = 300; + + LinkedList animators = new LinkedList<>(); + + addAnimation(animators, playPauseButton, interpolator, duration, 0); + addAnimation(animators, nextButton, interpolator, duration, 100); + addAnimation(animators, prevButton, interpolator, duration, 100); + addAnimation(animators, shuffleButton, interpolator, duration, 200); + addAnimation(animators, repeatButton, interpolator, duration, 200); + + + musicControllerAnimationSet = new AnimatorSet(); + musicControllerAnimationSet.playTogether(animators); + } else { + musicControllerAnimationSet.cancel(); + } + musicControllerAnimationSet.start(); + } + + public void hide() { + if (musicControllerAnimationSet != null) { + musicControllerAnimationSet.cancel(); + } + prepareForAnimation(playPauseButton); + prepareForAnimation(nextButton); + prepareForAnimation(prevButton); + prepareForAnimation(shuffleButton); + prepareForAnimation(repeatButton); + } + + private static void addAnimation(Collection animators, View view, TimeInterpolator interpolator, int duration, int delay) { + Animator scaleX = ObjectAnimator.ofFloat(view, View.SCALE_X, 0f, 1f); + scaleX.setInterpolator(interpolator); + scaleX.setDuration(duration); + scaleX.setStartDelay(delay); + animators.add(scaleX); + + Animator scaleY = ObjectAnimator.ofFloat(view, View.SCALE_Y, 0f, 1f); + scaleY.setInterpolator(interpolator); + scaleY.setDuration(duration); + scaleY.setStartDelay(delay); + animators.add(scaleY); + } + + private static void prepareForAnimation(View view) { + if (view != null) { + view.setScaleX(0f); + view.setScaleY(0f); + } + } + + private void setUpProgressSlider() { + int color = MaterialValueHelper.getPrimaryTextColor(getContext(), false); + progressSlider.getThumb().mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN); + progressSlider.getProgressDrawable().mutate().setColorFilter(Color.TRANSPARENT, PorterDuff.Mode.SRC_IN); + + progressSlider.setOnSeekBarChangeListener(new SimpleOnSeekbarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (fromUser) { + MusicPlayerRemote.seekTo(progress); + onUpdateProgressViews(MusicPlayerRemote.getSongProgressMillis(), MusicPlayerRemote.getSongDurationMillis()); + } + } + }); + } + + @Override + public void onUpdateProgressViews(int progress, int total) { + progressSlider.setMax(total); + progressSlider.setProgress(progress); + songTotalTime.setText(MusicUtil.getReadableDurationString(total)); + songCurrentProgress.setText(MusicUtil.getReadableDurationString(progress)); + } +} diff --git a/app/src/main/res/drawable/shadow_down.xml b/app/src/main/res/drawable/shadow_down.xml index c8cc6b77..cbf83d4b 100644 --- a/app/src/main/res/drawable/shadow_down.xml +++ b/app/src/main/res/drawable/shadow_down.xml @@ -4,5 +4,6 @@ \ No newline at end of file diff --git a/app/src/main/res/drawable/shadow_down_strong.xml b/app/src/main/res/drawable/shadow_down_strong.xml index c56b0959..90e9cc9b 100644 --- a/app/src/main/res/drawable/shadow_down_strong.xml +++ b/app/src/main/res/drawable/shadow_down_strong.xml @@ -4,5 +4,6 @@ \ No newline at end of file diff --git a/app/src/main/res/drawable/shadow_up.xml b/app/src/main/res/drawable/shadow_up.xml index 64f90aaa..b0f55dc9 100644 --- a/app/src/main/res/drawable/shadow_up.xml +++ b/app/src/main/res/drawable/shadow_up.xml @@ -4,5 +4,6 @@ \ No newline at end of file diff --git a/app/src/main/res/drawable/shadow_up_strong.xml b/app/src/main/res/drawable/shadow_up_strong.xml index bbe3ed2c..988524af 100644 --- a/app/src/main/res/drawable/shadow_up_strong.xml +++ b/app/src/main/res/drawable/shadow_up_strong.xml @@ -4,5 +4,6 @@ \ No newline at end of file diff --git a/app/src/main/res/layout-land/fragment_player.xml b/app/src/main/res/layout-land/fragment_card_player.xml similarity index 99% rename from app/src/main/res/layout-land/fragment_player.xml rename to app/src/main/res/layout-land/fragment_card_player.xml index ed87db9d..b1d8b169 100644 --- a/app/src/main/res/layout-land/fragment_player.xml +++ b/app/src/main/res/layout-land/fragment_card_player.xml @@ -65,7 +65,7 @@ diff --git a/app/src/main/res/layout/activity_album_detail.xml b/app/src/main/res/layout/activity_album_detail.xml index 34bea92f..3b313d79 100644 --- a/app/src/main/res/layout/activity_album_detail.xml +++ b/app/src/main/res/layout/activity_album_detail.xml @@ -55,7 +55,7 @@ - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_flat_player_playback_controls.xml b/app/src/main/res/layout/fragment_flat_player_playback_controls.xml new file mode 100644 index 00000000..ae4809d0 --- /dev/null +++ b/app/src/main/res/layout/fragment_flat_player_playback_controls.xml @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/shadow_statusbar_actionbar.xml b/app/src/main/res/layout/shadow_statusbar_toolbar.xml similarity index 100% rename from app/src/main/res/layout/shadow_statusbar_actionbar.xml rename to app/src/main/res/layout/shadow_statusbar_toolbar.xml diff --git a/app/src/main/res/layout/shadow_toolbar.xml b/app/src/main/res/layout/shadow_toolbar.xml new file mode 100644 index 00000000..80eed90f --- /dev/null +++ b/app/src/main/res/layout/shadow_toolbar.xml @@ -0,0 +1,5 @@ + + diff --git a/app/src/main/res/layout/sliding_music_panel_layout.xml b/app/src/main/res/layout/sliding_music_panel_layout.xml index 4fc08fe4..0f310e04 100644 --- a/app/src/main/res/layout/sliding_music_panel_layout.xml +++ b/app/src/main/res/layout/sliding_music_panel_layout.xml @@ -20,7 +20,7 @@ android:background="?android:colorBackground"> diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 304c8dc8..63fc626a 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -10,7 +10,8 @@ 360dp 20dp - 120dp + 120dp + 104dp 0dp