Added a new now playing screen.
This commit is contained in:
parent
b3a9c96fe6
commit
e7a896e3f4
21 changed files with 1171 additions and 37 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ public class PlayerAlbumCoverFragment extends AbsMusicServiceFragment implements
|
|||
callbacks = listener;
|
||||
}
|
||||
|
||||
interface Callbacks {
|
||||
public interface Callbacks {
|
||||
void onColorChanged(int color);
|
||||
|
||||
void onFavoriteToggled();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -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
|
||||
|
|
@ -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<Song, Void, Boolean>() {
|
||||
@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<Void, Void, String>() {
|
||||
@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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Animator> 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<Animator> 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));
|
||||
}
|
||||
}
|
||||
|
|
@ -4,5 +4,6 @@
|
|||
<gradient
|
||||
android:angle="90"
|
||||
android:endColor="#34000000"
|
||||
android:centerColor="#11000000"
|
||||
android:startColor="#00000000" />
|
||||
</shape>
|
||||
|
|
@ -4,5 +4,6 @@
|
|||
<gradient
|
||||
android:angle="90"
|
||||
android:endColor="#88000000"
|
||||
android:centerColor="#30000000"
|
||||
android:startColor="#00000000" />
|
||||
</shape>
|
||||
|
|
@ -4,5 +4,6 @@
|
|||
<gradient
|
||||
android:angle="270"
|
||||
android:endColor="#34000000"
|
||||
android:centerColor="#11000000"
|
||||
android:startColor="#00000000" />
|
||||
</shape>
|
||||
|
|
@ -4,5 +4,6 @@
|
|||
<gradient
|
||||
android:angle="270"
|
||||
android:endColor="#88000000"
|
||||
android:centerColor="#30000000"
|
||||
android:startColor="#00000000" />
|
||||
</shape>
|
||||
|
|
@ -65,7 +65,7 @@
|
|||
|
||||
<fragment
|
||||
android:id="@+id/playback_controls_fragment"
|
||||
class="com.kabouzeid.gramophone.ui.fragments.player.PlaybackControlsFragment"
|
||||
class="com.kabouzeid.gramophone.ui.fragments.player.card.CardPlayerPlaybackControlsFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
|
|
@ -55,7 +55,7 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<include layout="@layout/shadow_statusbar_actionbar" />
|
||||
<include layout="@layout/shadow_statusbar_toolbar" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<include layout="@layout/shadow_statusbar_actionbar" />
|
||||
<include layout="@layout/shadow_statusbar_toolbar" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
|
|
@ -51,14 +51,14 @@
|
|||
|
||||
<fragment
|
||||
android:id="@+id/playback_controls_fragment"
|
||||
class="com.kabouzeid.gramophone.ui.fragments.player.PlaybackControlsFragment"
|
||||
class="com.kabouzeid.gramophone.ui.fragments.player.card.CardPlayerPlaybackControlsFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/album_cover_container" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<include layout="@layout/shadow_statusbar_actionbar" />
|
||||
<include layout="@layout/shadow_statusbar_toolbar" />
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/player_toolbar"
|
||||
|
|
@ -53,7 +53,7 @@
|
|||
<RelativeLayout
|
||||
android:id="@+id/player_media_controller_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/media_controller_container_height"
|
||||
android:layout_height="@dimen/fab_media_controller_container_height"
|
||||
tools:ignore="ContentDescription,UnusedAttribute">
|
||||
|
||||
<ImageButton
|
||||
122
app/src/main/res/layout/fragment_flat_player.xml
Normal file
122
app/src/main/res/layout/fragment_flat_player.xml
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<View
|
||||
android:id="@+id/player_status_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/status_bar_padding" />
|
||||
|
||||
<com.sothree.slidinguppanel.SlidingUpPanelLayout android:id="@+id/player_sliding_layout"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:sothree="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clickable="false"
|
||||
android:focusable="true"
|
||||
android:gravity="bottom"
|
||||
sothree:umanoPanelHeight="0dp"
|
||||
sothree:umanoScrollableView="@+id/player_recycler_view"
|
||||
sothree:umanoShadowHeight="0dp">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/player_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.kabouzeid.gramophone.views.WidthFitSquareLayout
|
||||
android:id="@+id/album_cover_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/player_album_cover_fragment"
|
||||
class="com.kabouzeid.gramophone.ui.fragments.player.PlayerAlbumCoverFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</com.kabouzeid.gramophone.views.WidthFitSquareLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<include layout="@layout/shadow_toolbar" />
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/player_toolbar"
|
||||
style="@style/Toolbar"
|
||||
android:background="@android:color/transparent" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/player_panel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/playback_controls_fragment"
|
||||
class="com.kabouzeid.gramophone.ui.fragments.player.flat.FlatPlayerPlaybackControlsFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<!--This is necessary for the drag sorting to work at the top-->
|
||||
<View
|
||||
android:id="@+id/draggable_area"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBottom="@+id/player_panel_content"
|
||||
android:layout_alignTop="@+id/player_panel_content"
|
||||
android:layout_marginTop="128dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/player_panel_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:background="@drawable/shadow_down" />
|
||||
|
||||
<include
|
||||
android:id="@+id/current_song"
|
||||
layout="@layout/item_list" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/player_queue_sub_header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:text="@string/up_next"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
|
||||
android:textColor="?android:textColorSecondary" />
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/player_recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:requiresFadingEdge="vertical" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.sothree.slidinguppanel.SlidingUpPanelLayout>
|
||||
</LinearLayout>
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
tools:background="@color/md_amber_500">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/progress_container_height"
|
||||
android:background="#33000000">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/player_song_current_progress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:gravity="center_vertical|left|end"
|
||||
android:paddingLeft="8dp"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Title"
|
||||
android:textColor="@color/ate_primary_text_dark"
|
||||
android:textSize="12sp"
|
||||
tools:ignore="RtlHardcoded,RtlSymmetry"
|
||||
tools:text="0:00" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/player_song_total_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentRight="true"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:gravity="center_vertical|right|end"
|
||||
android:paddingRight="8dp"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Title"
|
||||
android:textColor="@color/ate_primary_text_dark"
|
||||
android:textSize="12sp"
|
||||
tools:ignore="RtlHardcoded,RtlSymmetry"
|
||||
tools:text="3:14" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/player_progress_slider"
|
||||
style="@style/MusicProgressSlider"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toLeftOf="@id/player_song_total_time"
|
||||
android:layout_toRightOf="@id/player_song_current_progress"
|
||||
tools:ignore="RtlHardcoded,UnusedAttribute" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/player_media_controller_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/media_controller_container_height"
|
||||
tools:ignore="ContentDescription,UnusedAttribute">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/player_prev_button"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="-8dp"
|
||||
android:layout_marginRight="-8dp"
|
||||
android:layout_toLeftOf="@+id/player_play_pause__button"
|
||||
android:layout_toStartOf="@+id/player_play_pause__button"
|
||||
android:background="?attr/roundSelector"
|
||||
android:padding="22dp"
|
||||
android:scaleType="fitCenter"
|
||||
app:srcCompat="@drawable/ic_skip_previous_white_24dp"
|
||||
tools:ignore="MissingPrefix" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/player_next_button"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="-8dp"
|
||||
android:layout_marginStart="-8dp"
|
||||
android:layout_toEndOf="@+id/player_play_pause__button"
|
||||
android:layout_toRightOf="@+id/player_play_pause__button"
|
||||
android:background="?attr/roundSelector"
|
||||
android:padding="22dp"
|
||||
android:scaleType="fitCenter"
|
||||
app:srcCompat="@drawable/ic_skip_next_white_24dp"
|
||||
tools:ignore="MissingPrefix" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/player_repeat_button"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:background="?attr/roundSelector"
|
||||
android:padding="22dp"
|
||||
android:scaleType="fitCenter"
|
||||
app:srcCompat="@drawable/ic_repeat_white_24dp"
|
||||
tools:ignore="MissingPrefix" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/player_shuffle_button"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:background="?attr/roundSelector"
|
||||
android:padding="22dp"
|
||||
android:scaleType="fitCenter"
|
||||
app:srcCompat="@drawable/ic_shuffle_white_24dp"
|
||||
tools:ignore="MissingPrefix" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/player_play_pause__button"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:background="?attr/roundSelector"
|
||||
android:padding="22dp"
|
||||
android:scaleType="fitCenter"
|
||||
tools:ignore="MissingPrefix"
|
||||
tools:src="@drawable/ic_pause_white_24dp" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
5
app/src/main/res/layout/shadow_toolbar.xml
Normal file
5
app/src/main/res/layout/shadow_toolbar.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<View xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?actionBarSize"
|
||||
android:background="@drawable/shadow_down" />
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
android:background="?android:colorBackground">
|
||||
|
||||
<fragment android:id="@+id/player_fragment"
|
||||
class="com.kabouzeid.gramophone.ui.fragments.player.PlayerFragment"
|
||||
class="com.kabouzeid.gramophone.ui.fragments.player.flat.FlatPlayerFragment"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@
|
|||
|
||||
<dimen name="header_image_height">360dp</dimen>
|
||||
<dimen name="progress_container_height">20dp</dimen>
|
||||
<dimen name="media_controller_container_height">120dp</dimen>
|
||||
<dimen name="fab_media_controller_container_height">120dp</dimen>
|
||||
<dimen name="media_controller_container_height">104dp</dimen>
|
||||
|
||||
<dimen name="status_bar_padding">0dp</dimen>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue