Added a new now playing screen.

This commit is contained in:
Karim Abou Zeid 2016-04-09 19:03:43 +02:00
commit e4848e1dab
21 changed files with 1171 additions and 37 deletions

View file

@ -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)

View file

@ -168,7 +168,7 @@ public class PlayerAlbumCoverFragment extends AbsMusicServiceFragment implements
callbacks = listener;
}
interface Callbacks {
public interface Callbacks {
void onColorChanged(int color);
void onFavoriteToggled();

View file

@ -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);

View file

@ -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

View file

@ -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();
}
}
}

View file

@ -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));
}
}

View file

@ -4,5 +4,6 @@
<gradient
android:angle="90"
android:endColor="#34000000"
android:centerColor="#11000000"
android:startColor="#00000000" />
</shape>

View file

@ -4,5 +4,6 @@
<gradient
android:angle="90"
android:endColor="#88000000"
android:centerColor="#30000000"
android:startColor="#00000000" />
</shape>

View file

@ -4,5 +4,6 @@
<gradient
android:angle="270"
android:endColor="#34000000"
android:centerColor="#11000000"
android:startColor="#00000000" />
</shape>

View file

@ -4,5 +4,6 @@
<gradient
android:angle="270"
android:endColor="#88000000"
android:centerColor="#30000000"
android:startColor="#00000000" />
</shape>

View file

@ -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" />

View file

@ -55,7 +55,7 @@
</LinearLayout>
<include layout="@layout/shadow_statusbar_actionbar" />
<include layout="@layout/shadow_statusbar_toolbar" />
<LinearLayout
android:layout_width="match_parent"

View file

@ -54,7 +54,7 @@
</LinearLayout>
<include layout="@layout/shadow_statusbar_actionbar" />
<include layout="@layout/shadow_statusbar_toolbar" />
<LinearLayout
android:layout_width="match_parent"

View file

@ -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"

View file

@ -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

View 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>

View file

@ -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>

View 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" />

View file

@ -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" />

View file

@ -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>