Divided the player fragment into sub fragments. WIP!

This commit is contained in:
Karim Abou Zeid 2015-10-28 15:22:39 +01:00
commit 79c50ce42e
8 changed files with 1056 additions and 872 deletions

View file

@ -55,7 +55,8 @@ public abstract class AbsSlidingMusicPanelActivity extends AbsMusicServiceActivi
}); });
} }
setUpSlidingPanel(); slidingUpPanelLayout.setPanelSlideListener(this);
playerFragment.resetShowControlsAnimation();
slidingUpPanelLayout.post(new Runnable() { slidingUpPanelLayout.post(new Runnable() {
@Override @Override
@ -76,10 +77,6 @@ public abstract class AbsSlidingMusicPanelActivity extends AbsMusicServiceActivi
super.onServiceConnected(name, service); super.onServiceConnected(name, service);
} }
private void setUpSlidingPanel() {
slidingUpPanelLayout.setPanelSlideListener(this);
}
@Override @Override
public void onPanelSlide(View view, @FloatRange(from = 0, to = 1) float slideOffset) { public void onPanelSlide(View view, @FloatRange(from = 0, to = 1) float slideOffset) {
setMiniPlayerAlphaProgress(slideOffset); setMiniPlayerAlphaProgress(slideOffset);

View file

@ -0,0 +1,390 @@
package com.kabouzeid.gramophone.ui.fragments;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.support.v7.widget.CardView;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.afollestad.materialdialogs.internal.ThemeSingleton;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.kabouzeid.gramophone.helper.PlayPauseButtonOnClickHandler;
import com.kabouzeid.gramophone.interfaces.MusicServiceEventListener;
import com.kabouzeid.gramophone.misc.FloatingActionButtonProperties;
import com.kabouzeid.gramophone.misc.SimpleAnimatorListener;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.service.MusicService;
import com.kabouzeid.gramophone.ui.activities.base.AbsMusicServiceActivity;
import com.kabouzeid.gramophone.util.ColorUtil;
import com.kabouzeid.gramophone.util.PreferenceUtil;
import com.kabouzeid.gramophone.util.Util;
import com.kabouzeid.gramophone.util.ViewUtil;
import com.kabouzeid.gramophone.views.PlayPauseDrawable;
import butterknife.Bind;
import butterknife.ButterKnife;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class PlaybackControlsFragment extends Fragment implements MusicServiceEventListener, SharedPreferences.OnSharedPreferenceChangeListener {
private static final int FAB_CIRCULAR_REVEAL_ANIMATION_TIME = 1000;
@Bind(R.id.player_play_pause_fab)
FloatingActionButton playPauseFab;
@Bind(R.id.player_title)
TextView songTitle;
@Bind(R.id.player_text)
TextView songText;
@Bind(R.id.player_footer)
LinearLayout footer;
@Bind(R.id.player_playback_controller_card)
CardView playbackControllerCard;
@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_media_controller_container)
RelativeLayout mediaControllerContainer;
@Bind(R.id.player_media_controller_container_background)
View mediaControllerContainerBackground;
private int lastFooterColor;
private int lastPlaybackControlsColor;
private int lastTitleTextColor;
private int lastCaptionTextColor;
private PlayPauseDrawable playerFabPlayPauseDrawable;
private AnimatorSet colorTransitionAnimator;
private AbsMusicServiceActivity activity;
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
activity = (AbsMusicServiceActivity) context;
} catch (ClassCastException e) {
throw new RuntimeException(context.getClass().getSimpleName() + " must be an instance of " + AbsMusicServiceActivity.class.getSimpleName());
}
}
@Override
public void onDetach() {
super.onDetach();
activity = null;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_playback_controls, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
PreferenceUtil.getInstance(getContext()).registerOnSharedPreferenceChangedListener(this);
activity.addMusicServiceEventListener(this);
setUpMusicControllers();
}
@Override
public void onDestroyView() {
super.onDestroyView();
activity.removeMusicServiceEventListener(this);
PreferenceUtil.getInstance(activity).unregisterOnSharedPreferenceChangedListener(this);
ButterKnife.unbind(this);
}
@Override
public void onPlayingMetaChanged() {
updateMetaTexts();
}
@Override
public void onPlayStateChanged() {
updatePlayPauseDrawableState(true);
}
@Override
public void onRepeatModeChanged() {
updateRepeatState();
}
@Override
public void onShuffleModeChanged() {
updateShuffleState();
}
@Override
public void onMediaStoreChanged() {
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
switch (key) {
case PreferenceUtil.PLAYBACK_CONTROLLER_CARD_NOW_PLAYING:
updatePlaybackControllerCardVisibility();
break;
case PreferenceUtil.COLOR_PLAYBACK_CONTROLS_NOW_PLAYING:
updateRepeatState();
updateShuffleState();
updatePlayPauseFabTint();
break;
case PreferenceUtil.LARGER_TITLE_BOX_NOW_PLAYING:
updateTitleBoxSize();
break;
}
}
public void setColor(int color) {
animateColorChange(color);
}
private void setUpPlayPauseFab() {
updatePlayPauseDrawableState(false);
playPauseFab.setImageDrawable(playerFabPlayPauseDrawable);
updatePlayPauseFabTint();
playPauseFab.setOnClickListener(new PlayPauseButtonOnClickHandler());
playPauseFab.post(new Runnable() {
@Override
public void run() {
playPauseFab.setPivotX(playPauseFab.getWidth() / 2);
playPauseFab.setPivotY(playPauseFab.getHeight() / 2);
}
});
}
private void updatePlayPauseFabTint() {
int fabColor = PreferenceUtil.getInstance(activity).colorPlaybackControlsNowPlaying() ? lastPlaybackControlsColor : activity.getThemeColorAccent();
FloatingActionButtonProperties.COLOR.set(playPauseFab, fabColor);
}
protected void updatePlayPauseDrawableState(boolean animate) {
if (playerFabPlayPauseDrawable == null) {
playerFabPlayPauseDrawable = new PlayPauseDrawable(activity);
}
if (MusicPlayerRemote.isPlaying()) {
playerFabPlayPauseDrawable.setPause(animate);
} else {
playerFabPlayPauseDrawable.setPlay(animate);
}
}
private void updateTitleBoxSize() {
boolean largerTitleBox = PreferenceUtil.getInstance(activity).largerTitleBoxNowPlaying();
int paddingTopBottom = largerTitleBox ? getResources().getDimensionPixelSize(R.dimen.title_box_padding_large) : getResources().getDimensionPixelSize(R.dimen.title_box_padding_small);
footer.setPadding(footer.getPaddingLeft(), paddingTopBottom, footer.getPaddingRight(), paddingTopBottom);
songTitle.setPadding(songTitle.getPaddingLeft(), songTitle.getPaddingTop(), songTitle.getPaddingRight(), largerTitleBox ? getResources().getDimensionPixelSize(R.dimen.title_box_text_spacing_large) : getResources().getDimensionPixelSize(R.dimen.title_box_text_spacing_small));
songText.setPadding(songText.getPaddingLeft(), largerTitleBox ? getResources().getDimensionPixelSize(R.dimen.title_box_text_spacing_large) : getResources().getDimensionPixelSize(R.dimen.title_box_text_spacing_small), songText.getPaddingRight(), songText.getPaddingBottom());
songTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, largerTitleBox ? getResources().getDimensionPixelSize(R.dimen.title_box_title_text_size_large) : getResources().getDimensionPixelSize(R.dimen.title_box_title_text_size_small));
songText.setTextSize(TypedValue.COMPLEX_UNIT_PX, largerTitleBox ? getResources().getDimensionPixelSize(R.dimen.title_box_caption_text_size_large) : getResources().getDimensionPixelSize(R.dimen.title_box_caption_text_size_small));
}
private void updatePlaybackControllerCardVisibility() {
boolean showPlaybackControllerCard = PreferenceUtil.getInstance(activity).playbackControllerCardNowPlaying();
playbackControllerCard.setVisibility(showPlaybackControllerCard ? View.VISIBLE : View.GONE);
mediaControllerContainerBackground.setVisibility(showPlaybackControllerCard ? View.GONE : View.VISIBLE);
}
private void setUpMusicControllers() {
setUpPlayPauseFab();
setUpPrevNext();
setUpRepeatButton();
setUpShuffleButton();
}
private void setUpPrevNext() {
int themedDrawableColor = ColorUtil.resolveColor(activity, android.R.attr.textColorSecondary);
nextButton.setImageDrawable(Util.getTintedDrawable(activity,
R.drawable.ic_skip_next_white_36dp, themedDrawableColor));
prevButton.setImageDrawable(Util.getTintedDrawable(activity,
R.drawable.ic_skip_previous_white_36dp, themedDrawableColor));
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 setUpShuffleButton() {
updateShuffleState();
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.setImageDrawable(Util.getTintedDrawable(activity, R.drawable.ic_shuffle_white_36dp,
getActivatedIconColor()));
break;
default:
shuffleButton.setImageDrawable(Util.getTintedDrawable(activity, R.drawable.ic_shuffle_white_36dp,
getDeactivatedIconColor()));
break;
}
}
private void setUpRepeatButton() {
updateRepeatState();
repeatButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MusicPlayerRemote.cycleRepeatMode();
}
});
}
private void updateRepeatState() {
switch (MusicPlayerRemote.getRepeatMode()) {
case MusicService.REPEAT_MODE_ALL:
repeatButton.setImageDrawable(Util.getTintedDrawable(activity, R.drawable.ic_repeat_white_36dp,
getActivatedIconColor()));
break;
case MusicService.REPEAT_MODE_THIS:
repeatButton.setImageDrawable(Util.getTintedDrawable(activity, R.drawable.ic_repeat_one_white_36dp,
getActivatedIconColor()));
break;
default:
repeatButton.setImageDrawable(Util.getTintedDrawable(activity, R.drawable.ic_repeat_white_36dp,
getDeactivatedIconColor()));
break;
}
}
private int getActivatedIconColor() {
if (PreferenceUtil.getInstance(activity).colorPlaybackControlsNowPlaying()) {
return ensureActivatedColorVisibleIfNecessary(lastPlaybackControlsColor);
} else {
return ThemeSingleton.get().positiveColor.getDefaultColor();
}
}
private int getDeactivatedIconColor() {
return ColorUtil.resolveColor(activity, android.R.attr.textColorSecondary);
}
/**
* @return If the activated color wont have enough difference to the deactivated color Color.WHITE / Color.BLACK (depending on the theme),
* else the unmodified accentColor.
*/
private int ensureActivatedColorVisibleIfNecessary(int activatedColor) {
// Not optimal, but much easier then computing the opaque deactivated color on the background color every time.
int preBlendedDeactivatedIconColor = ThemeSingleton.get().darkTheme ? Color.argb(255, 188, 188, 188) : Color.argb(255, 115, 115, 115);
if (ColorUtil.getColorDifference(activatedColor, preBlendedDeactivatedIconColor) <= 30d) {
return ThemeSingleton.get().darkTheme ? Color.WHITE : Color.BLACK;
}
return activatedColor;
}
private void updateMetaTexts() {
final Song song = MusicPlayerRemote.getCurrentSong();
songTitle.setText(song.title);
songText.setText(song.artistName);
}
private void animateColorChange(final int newColor) {
if (colorTransitionAnimator != null && colorTransitionAnimator.isStarted()) {
colorTransitionAnimator.cancel();
}
colorTransitionAnimator = new AnimatorSet();
AnimatorSet.Builder animatorSetBuilder = colorTransitionAnimator.play(ViewUtil.createBackgroundColorTransition(footer, lastFooterColor, newColor));
int titleTextColor = ColorUtil.getPrimaryTextColorForBackground(activity, newColor);
int captionTextColor = ColorUtil.getSecondaryTextColorForBackground(activity, newColor);
animatorSetBuilder.with(ViewUtil.createTextColorTransition(songTitle, lastTitleTextColor, titleTextColor));
animatorSetBuilder.with(ViewUtil.createTextColorTransition(songText, lastCaptionTextColor, captionTextColor));
colorTransitionAnimator.addListener(new SimpleAnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
if (newColor == ColorUtil.resolveColor(activity, R.attr.default_bar_color) && ThemeSingleton.get().darkTheme) {
lastPlaybackControlsColor = Color.WHITE;
} else {
lastPlaybackControlsColor = newColor;
}
updateRepeatState();
updateShuffleState();
updatePlayPauseFabTint();
}
});
colorTransitionAnimator.start();
lastFooterColor = newColor;
lastTitleTextColor = titleTextColor;
lastCaptionTextColor = captionTextColor;
}
public void showControls() {
playPauseFab.animate()
.scaleX(1f)
.scaleY(1f)
.rotation(360f)
.setInterpolator(new DecelerateInterpolator())
.start();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (mediaControllerContainer.getVisibility() == View.INVISIBLE) {
int cx = (playPauseFab.getLeft() + playPauseFab.getRight()) / 2;
int cy = (playPauseFab.getTop() + playPauseFab.getBottom()) / 2;
int finalRadius = Math.max(mediaControllerContainer.getWidth(), mediaControllerContainer.getHeight());
final Animator animator = ViewAnimationUtils.createCircularReveal(mediaControllerContainer, cx, cy, 0, finalRadius);
animator.setInterpolator(new DecelerateInterpolator());
animator.setDuration(FAB_CIRCULAR_REVEAL_ANIMATION_TIME);
animator.start();
mediaControllerContainer.setVisibility(View.VISIBLE);
}
}
}
public void resetShowControlsAnimation() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mediaControllerContainer.setVisibility(View.INVISIBLE);
}
playPauseFab.setScaleX(0f);
playPauseFab.setScaleY(0f);
playPauseFab.setRotation(0f);
}
}

View file

@ -0,0 +1,225 @@
package com.kabouzeid.gramophone.ui.fragments;
import android.animation.Animator;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.annotation.ColorInt;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.OvershootInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.kabouzeid.gramophone.interfaces.MusicServiceEventListener;
import com.kabouzeid.gramophone.misc.SimpleAnimatorListener;
import com.kabouzeid.gramophone.ui.activities.base.AbsMusicServiceActivity;
import com.kabouzeid.gramophone.util.ColorUtil;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.PreferenceUtil;
import com.kabouzeid.gramophone.util.ViewUtil;
import com.kabouzeid.gramophone.views.SquareIfPlaceImageView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.assist.LoadedFrom;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.imageaware.ImageAware;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import com.nostra13.universalimageloader.core.process.BitmapProcessor;
import butterknife.Bind;
import butterknife.ButterKnife;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class PlayerAlbumCoverFragment extends Fragment implements MusicServiceEventListener, SharedPreferences.OnSharedPreferenceChangeListener {
@Bind(R.id.player_image)
SquareIfPlaceImageView albumArt;
@Bind(R.id.player_favorite_icon)
ImageView favoriteIcon;
@Bind(R.id.player_album_art_frame)
FrameLayout albumArtFrame;
private boolean forceSquareAlbumArt;
private AbsMusicServiceActivity activity;
private OnColorChangedListener onColorChangedListener;
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
activity = (AbsMusicServiceActivity) context;
} catch (ClassCastException e) {
throw new RuntimeException(context.getClass().getSimpleName() + " must be an instance of " + AbsMusicServiceActivity.class.getSimpleName());
}
}
@Override
public void onDetach() {
super.onDetach();
activity = null;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_player_album_cover, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
albumArt.forceSquare(forceSquareAlbumArt);
PreferenceUtil.getInstance(getContext()).registerOnSharedPreferenceChangedListener(this);
activity.addMusicServiceEventListener(this);
}
@Override
public void onDestroyView() {
super.onDestroyView();
activity.removeMusicServiceEventListener(this);
PreferenceUtil.getInstance(activity).unregisterOnSharedPreferenceChangedListener(this);
ButterKnife.unbind(this);
}
@Override
public void onPlayingMetaChanged() {
loadAlbumCover();
}
@Override
public void onPlayStateChanged() {
}
@Override
public void onRepeatModeChanged() {
}
@Override
public void onShuffleModeChanged() {
}
@Override
public void onMediaStoreChanged() {
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
switch (key) {
case PreferenceUtil.FORCE_SQUARE_ALBUM_ART:
forceSquareAlbumArt = PreferenceUtil.getInstance(activity).forceAlbumArtSquared();
albumArt.forceSquare(forceSquareAlbumArt);
break;
}
}
private static class ColorHolder {
@ColorInt
public int color;
}
private void loadAlbumCover() {
final ColorHolder colorHolder = new ColorHolder();
ImageLoader.getInstance().displayImage(
MusicUtil.getSongImageLoaderString(MusicPlayerRemote.getCurrentSong()),
albumArt,
new DisplayImageOptions.Builder()
.cacheInMemory(true)
.showImageOnFail(R.drawable.default_album_art)
.postProcessor(new BitmapProcessor() {
@Override
public Bitmap process(Bitmap bitmap) {
colorHolder.color = ColorUtil.generateColor(activity, bitmap);
return bitmap;
}
})
.displayer(new FadeInBitmapDisplayer(ViewUtil.DEFAULT_COLOR_ANIMATION_DURATION) {
@Override
public void display(Bitmap bitmap, ImageAware imageAware, LoadedFrom loadedFrom) {
super.display(bitmap, imageAware, loadedFrom);
setColor(colorHolder.color);
}
})
.build(),
new SimpleImageLoadingListener() {
@Override
public void onLoadingFailed(String imageUri, View view, @Nullable FailReason failReason) {
FadeInBitmapDisplayer.animate(view, ViewUtil.DEFAULT_COLOR_ANIMATION_DURATION);
setColor(ColorUtil.resolveColor(activity, R.attr.default_bar_color));
}
@Override
public void onLoadingComplete(String imageUri, View view, @Nullable Bitmap loadedImage) {
if (loadedImage == null) {
onLoadingFailed(imageUri, view, null);
}
}
}
);
}
public void showHeart() {
favoriteIcon.clearAnimation();
favoriteIcon.setAlpha(0f);
favoriteIcon.setScaleX(0f);
favoriteIcon.setScaleY(0f);
favoriteIcon.setVisibility(View.VISIBLE);
favoriteIcon.setPivotX(favoriteIcon.getWidth() / 2);
favoriteIcon.setPivotY(favoriteIcon.getHeight() / 2);
favoriteIcon.animate()
.setDuration(600)
.setInterpolator(new OvershootInterpolator())
.scaleX(1f)
.scaleY(1f)
.alpha(1f)
.setListener(new SimpleAnimatorListener() {
@Override
public void onAnimationCancel(Animator animation) {
favoriteIcon.setVisibility(View.INVISIBLE);
}
})
.withEndAction(new Runnable() {
@Override
public void run() {
favoriteIcon.animate()
.setDuration(300)
.setInterpolator(new DecelerateInterpolator())
.alpha(0f)
.start();
}
})
.start();
}
private void setColor(int color) {
if (onColorChangedListener != null) onColorChangedListener.onColorChanged(color);
}
public void setOnColorChangedListener(OnColorChangedListener listener) {
onColorChangedListener = listener;
}
interface OnColorChangedListener {
void onColorChanged(int color);
}
}

View file

@ -1,40 +1,19 @@
package com.kabouzeid.gramophone.ui.fragments; package com.kabouzeid.gramophone.ui.fragments;
import android.animation.Animator;
import android.animation.AnimatorSet; import android.animation.AnimatorSet;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.ColorInt; import android.support.annotation.ColorInt;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v7.widget.CardView;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.util.TypedValue;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.OvershootInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import com.afollestad.materialdialogs.internal.ThemeSingleton;
import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.dialogs.AddToPlaylistDialog; import com.kabouzeid.gramophone.dialogs.AddToPlaylistDialog;
import com.kabouzeid.gramophone.dialogs.PlayingQueueDialog; import com.kabouzeid.gramophone.dialogs.PlayingQueueDialog;
@ -43,15 +22,10 @@ import com.kabouzeid.gramophone.dialogs.SongDetailDialog;
import com.kabouzeid.gramophone.dialogs.SongShareDialog; import com.kabouzeid.gramophone.dialogs.SongShareDialog;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote; import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.kabouzeid.gramophone.helper.MusicProgressViewUpdateHelper; import com.kabouzeid.gramophone.helper.MusicProgressViewUpdateHelper;
import com.kabouzeid.gramophone.helper.PlayPauseButtonOnClickHandler;
import com.kabouzeid.gramophone.interfaces.MusicServiceEventListener; import com.kabouzeid.gramophone.interfaces.MusicServiceEventListener;
import com.kabouzeid.gramophone.interfaces.PaletteColorHolder; import com.kabouzeid.gramophone.interfaces.PaletteColorHolder;
import com.kabouzeid.gramophone.loader.SongLoader; import com.kabouzeid.gramophone.loader.SongLoader;
import com.kabouzeid.gramophone.misc.FloatingActionButtonProperties;
import com.kabouzeid.gramophone.misc.SimpleAnimatorListener;
import com.kabouzeid.gramophone.misc.SimpleOnSeekbarChangeListener;
import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.service.MusicService;
import com.kabouzeid.gramophone.ui.activities.base.AbsMusicServiceActivity; import com.kabouzeid.gramophone.ui.activities.base.AbsMusicServiceActivity;
import com.kabouzeid.gramophone.ui.activities.tageditor.AbsTagEditorActivity; import com.kabouzeid.gramophone.ui.activities.tageditor.AbsTagEditorActivity;
import com.kabouzeid.gramophone.ui.activities.tageditor.SongTagEditorActivity; import com.kabouzeid.gramophone.ui.activities.tageditor.SongTagEditorActivity;
@ -61,87 +35,32 @@ import com.kabouzeid.gramophone.util.NavigationUtil;
import com.kabouzeid.gramophone.util.PreferenceUtil; import com.kabouzeid.gramophone.util.PreferenceUtil;
import com.kabouzeid.gramophone.util.Util; import com.kabouzeid.gramophone.util.Util;
import com.kabouzeid.gramophone.util.ViewUtil; import com.kabouzeid.gramophone.util.ViewUtil;
import com.kabouzeid.gramophone.views.PlayPauseDrawable;
import com.kabouzeid.gramophone.views.SquareIfPlaceImageView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.assist.LoadedFrom;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.imageaware.ImageAware;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import com.nostra13.universalimageloader.core.process.BitmapProcessor;
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
public class PlayerFragment extends Fragment implements SharedPreferences.OnSharedPreferenceChangeListener, MusicServiceEventListener, Toolbar.OnMenuItemClickListener, PaletteColorHolder, MusicProgressViewUpdateHelper.Callback { public class PlayerFragment extends Fragment implements SharedPreferences.OnSharedPreferenceChangeListener, MusicServiceEventListener, Toolbar.OnMenuItemClickListener, PaletteColorHolder, MusicProgressViewUpdateHelper.Callback, PlayerAlbumCoverFragment.OnColorChangedListener {
public static final String TAG = PlayerFragment.class.getSimpleName(); public static final String TAG = PlayerFragment.class.getSimpleName();
private static final int FAB_CIRCULAR_REVEAL_ANIMATION_TIME = 1000;
@Bind(R.id.player_play_pause_fab)
FloatingActionButton playPauseFab;
@Bind(R.id.player_title)
TextView songTitle;
@Bind(R.id.player_text)
TextView songText;
@Bind(R.id.player_footer)
LinearLayout footer;
@Bind(R.id.player_playback_controller_card)
CardView playbackControllerCard;
@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_media_controller_container)
RelativeLayout mediaControllerContainer;
@Bind(R.id.player_media_controller_container_background)
View mediaControllerContainerBackground;
@Bind(R.id.player_image)
SquareIfPlaceImageView albumArt;
@Bind(R.id.player_status_bar) @Bind(R.id.player_status_bar)
View statusbar; View statusbar;
@Bind(R.id.player_toolbar) @Bind(R.id.player_toolbar)
Toolbar toolbar; Toolbar toolbar;
@Bind(R.id.player_favorite_icon)
ImageView favoriteIcon;
@Bind(R.id.player_album_art_frame)
FrameLayout albumArtFrame;
TextView songCurrentProgress; private AnimatorSet colorTransitionAnimator;
TextView songTotalTime; private int lastColor;
SeekBar progressSlider;
private int lastFooterColor;
private int lastPlaybackControlsColor; private int lastPlaybackControlsColor;
private int lastTitleTextColor;
private int lastCaptionTextColor;
private MusicProgressViewUpdateHelper progressViewUpdateHelper;
private boolean opaqueStatusBar;
private boolean opaqueToolBar;
private boolean forceSquareAlbumArt;
private boolean largerTitleBox;
private boolean alternativeProgressSlider;
private boolean showPlaybackControllerCard;
private boolean colorPlaybackControls;
private Song song; private Song song;
private PlayPauseDrawable playerFabPlayPauseDrawable; private MusicProgressViewUpdateHelper progressViewUpdateHelper;
private AnimatorSet colorTransitionAnimator;
private AbsMusicServiceActivity activity; private AbsMusicServiceActivity activity;
private Callbacks callbacks; private Callbacks callbacks;
private PlaybackControlsFragment playbackControlsFragment;
private PlayerAlbumCoverFragment playerAlbumCoverFragment;
@Override @Override
public void onAttach(Context context) { public void onAttach(Context context) {
super.onAttach(context); super.onAttach(context);
@ -163,7 +82,6 @@ public class PlayerFragment extends Fragment implements SharedPreferences.OnShar
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
initAppearanceVarsFromSharedPrefs();
progressViewUpdateHelper = new MusicProgressViewUpdateHelper(this); progressViewUpdateHelper = new MusicProgressViewUpdateHelper(this);
} }
@ -178,14 +96,13 @@ public class PlayerFragment extends Fragment implements SharedPreferences.OnShar
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view); ButterKnife.bind(this, view);
resetShowControlsAnimation(); playbackControlsFragment = (PlaybackControlsFragment) getChildFragmentManager().findFragmentById(R.id.playback_controls_fragment);
setUpPlayPauseFab(); playerAlbumCoverFragment = (PlayerAlbumCoverFragment) getChildFragmentManager().findFragmentById(R.id.player_album_cover_fragment);
adjustTitleBoxSize(); playerAlbumCoverFragment.setOnColorChangedListener(this);
setUpPlaybackControllerCard();
setUpMusicControllers(); // alignAlbumArt();
setUpAlbumArtViews();
setUpPlayerToolbar(); setUpPlayerToolbar();
setUpPlayerStatusBarElevation(); // setUpPlayerStatusBarElevation();
PreferenceUtil.getInstance(getContext()).registerOnSharedPreferenceChangedListener(this); PreferenceUtil.getInstance(getContext()).registerOnSharedPreferenceChangedListener(this);
activity.addMusicServiceEventListener(this); activity.addMusicServiceEventListener(this);
@ -216,14 +133,19 @@ public class PlayerFragment extends Fragment implements SharedPreferences.OnShar
updateCurrentSong(); updateCurrentSong();
} }
@Override
public void onPlayStateChanged() {
}
@Override @Override
public void onRepeatModeChanged() { public void onRepeatModeChanged() {
updateRepeatState();
} }
@Override @Override
public void onShuffleModeChanged() { public void onShuffleModeChanged() {
updateShuffleState();
} }
@Override @Override
@ -234,326 +156,135 @@ public class PlayerFragment extends Fragment implements SharedPreferences.OnShar
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
switch (key) { switch (key) {
case PreferenceUtil.OPAQUE_STATUSBAR_NOW_PLAYING: // case PreferenceUtil.OPAQUE_STATUSBAR_NOW_PLAYING:
opaqueStatusBar = PreferenceUtil.getInstance(activity).opaqueStatusbarNowPlaying(); // opaqueStatusBar = PreferenceUtil.getInstance(activity).opaqueStatusbarNowPlaying();
// do not break here // // do not break here
case PreferenceUtil.OPAQUE_TOOLBAR_NOW_PLAYING: // case PreferenceUtil.OPAQUE_TOOLBAR_NOW_PLAYING:
opaqueToolBar = opaqueStatusBar && PreferenceUtil.getInstance(activity).opaqueToolbarNowPlaying(); // opaqueToolBar = opaqueStatusBar && PreferenceUtil.getInstance(activity).opaqueToolbarNowPlaying();
setUpPlayerStatusBarElevation(); // setUpPlayerStatusBarElevation();
animateColorChange(lastFooterColor); // animateColorChange(lastColor);
if (opaqueStatusBar) { // alignAlbumArt();
if (opaqueToolBar) { // break;
alignAlbumArtToToolbar(); // case PreferenceUtil.ALTERNATIVE_PROGRESS_SLIDER_NOW_PLAYING:
} else { // alternativeProgressSlider = PreferenceUtil.getInstance(activity).alternativeProgressSliderNowPlaying();
alignAlbumArtToStatusBar(); // setUpProgressSlider();
} // break;
} else {
alignAlbumArtToTop();
}
break;
case PreferenceUtil.FORCE_SQUARE_ALBUM_ART:
forceSquareAlbumArt = PreferenceUtil.getInstance(activity).forceAlbumArtSquared();
albumArt.forceSquare(forceSquareAlbumArt);
break;
case PreferenceUtil.LARGER_TITLE_BOX_NOW_PLAYING:
largerTitleBox = PreferenceUtil.getInstance(activity).largerTitleBoxNowPlaying();
adjustTitleBoxSize();
break;
case PreferenceUtil.ALTERNATIVE_PROGRESS_SLIDER_NOW_PLAYING:
alternativeProgressSlider = PreferenceUtil.getInstance(activity).alternativeProgressSliderNowPlaying();
setUpProgressSlider();
break;
case PreferenceUtil.PLAYBACK_CONTROLLER_CARD_NOW_PLAYING:
showPlaybackControllerCard = PreferenceUtil.getInstance(activity).playbackControllerCardNowPlaying();
setUpPlaybackControllerCard();
break;
case PreferenceUtil.COLOR_PLAYBACK_CONTROLS_NOW_PLAYING:
colorPlaybackControls = PreferenceUtil.getInstance(activity).colorPlaybackControlsNowPlaying();
updateRepeatState();
updateShuffleState();
setUpProgressSliderTint();
setUpPlayerPlayPauseFabTint();
break;
} }
} }
private void setUpPlayPauseFab() { // private void initProgressSliderDependentViews() {
updatePlayPauseDrawableState(false); // if (getView() == null) return;
playPauseFab.setImageDrawable(playerFabPlayPauseDrawable); // if (alternativeProgressSlider) {
setUpPlayerPlayPauseFabTint(); // getView().findViewById(R.id.player_default_progress_container).setVisibility(View.GONE);
playPauseFab.setOnClickListener(new PlayPauseButtonOnClickHandler()); // getView().findViewById(R.id.player_default_progress_slider).setVisibility(View.GONE);
playPauseFab.post(new Runnable() { // getView().findViewById(R.id.player_alternative_progress_container).setVisibility(View.VISIBLE);
@Override //
public void run() { // songCurrentProgress = (TextView) getView().findViewById(R.id.player_alternative_song_current_progress);
playPauseFab.setPivotX(playPauseFab.getWidth() / 2); // songTotalTime = (TextView) getView().findViewById(R.id.player_alternative_song_total_time);
playPauseFab.setPivotY(playPauseFab.getHeight() / 2); // progressSlider = (SeekBar) getView().findViewById(R.id.player_alternative_progress_slider);
} // } else {
}); // getView().findViewById(R.id.player_default_progress_container).setVisibility(View.VISIBLE);
} // getView().findViewById(R.id.player_default_progress_slider).setVisibility(View.VISIBLE);
// getView().findViewById(R.id.player_alternative_progress_container).setVisibility(View.GONE);
//
// songCurrentProgress = (TextView) getView().findViewById(R.id.player_default_song_current_progress);
// songTotalTime = (TextView) getView().findViewById(R.id.player_default_song_total_time);
// progressSlider = (SeekBar) getView().findViewById(R.id.player_default_progress_slider);
// }
// }
//
// private void moveProgressSliderIntoPlace() {
// if (!alternativeProgressSlider) {
// RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) progressSlider.getLayoutParams();
// progressSlider.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
// final int seekBarMarginLeftRight = getResources().getDimensionPixelSize(R.dimen.seek_bar_margin_left_right);
// lp.setMargins(seekBarMarginLeftRight, 0, seekBarMarginLeftRight, -(progressSlider.getMeasuredHeight() / 2));
// progressSlider.setLayoutParams(lp);
// }
// }
private void setUpPlayerPlayPauseFabTint() { // private void updateProgressSliderTint() {
int fabColor = colorPlaybackControls ? lastPlaybackControlsColor : activity.getThemeColorAccent(); // int thumbColor;
FloatingActionButtonProperties.COLOR.set(playPauseFab, fabColor); // int progressColor;
} // if (alternativeProgressSlider) {
// if (colorPlaybackControls) {
// thumbColor = lastPlaybackControlsColor;
// } else {
// thumbColor = ThemeSingleton.get().positiveColor.getDefaultColor();
// }
// progressColor = Color.TRANSPARENT;
// } else {
// if (colorPlaybackControls) {
// if (ColorUtil.useDarkTextColorOnBackground(lastPlaybackControlsColor)) {
// thumbColor = ColorUtil.shiftColor(lastPlaybackControlsColor, 1.2f);
// } else {
// thumbColor = ColorUtil.shiftColor(lastPlaybackControlsColor, 0.8f);
// }
// } else {
// thumbColor = activity.getThemeColorAccent();
// }
// progressColor = thumbColor;
// }
// setSeekBarTint(progressSlider, thumbColor, progressColor);
// }
//
// private static void setSeekBarTint(SeekBar seekBar, @ColorInt int thumbColor, @ColorInt int progressColor) {
// seekBar.getThumb().mutate().setColorFilter(thumbColor, PorterDuff.Mode.SRC_IN);
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// // this will only tint the left part of the progress bar
// seekBar.setProgressTintList(ColorStateList.valueOf(progressColor));
// } else {
// seekBar.getProgressDrawable().mutate().setColorFilter(progressColor, PorterDuff.Mode.SRC_IN);
// }
// }
protected void updatePlayPauseDrawableState(boolean animate) { // private void setUpProgressSlider() {
if (playerFabPlayPauseDrawable == null) { // initProgressSliderDependentViews();
playerFabPlayPauseDrawable = new PlayPauseDrawable(activity); // moveProgressSliderIntoPlace();
} // updateProgressSliderTint();
if (MusicPlayerRemote.isPlaying()) { // progressSlider.setOnSeekBarChangeListener(new SimpleOnSeekbarChangeListener() {
playerFabPlayPauseDrawable.setPause(animate); // @Override
} else { // public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
playerFabPlayPauseDrawable.setPlay(animate); // if (fromUser) {
} // MusicPlayerRemote.seekTo(progress);
} // onUpdateProgressViews(MusicPlayerRemote.getSongProgressMillis(), MusicPlayerRemote.getSongDurationMillis());
// }
// }
// });
// }
@Override // private void alignAlbumArt() {
public void onPlayStateChanged() { // if (opaqueStatusBar) {
updatePlayPauseDrawableState(true); // if (opaqueToolBar) {
} // alignAlbumArtToToolbar();
// } else {
private void initAppearanceVarsFromSharedPrefs() { // alignAlbumArtToStatusBar();
opaqueStatusBar = PreferenceUtil.getInstance(activity).opaqueStatusbarNowPlaying(); // }
opaqueToolBar = opaqueStatusBar && PreferenceUtil.getInstance(activity).opaqueToolbarNowPlaying(); // } else {
forceSquareAlbumArt = PreferenceUtil.getInstance(activity).forceAlbumArtSquared(); // alignAlbumArtToTop();
largerTitleBox = PreferenceUtil.getInstance(activity).largerTitleBoxNowPlaying(); // }
alternativeProgressSlider = PreferenceUtil.getInstance(activity).alternativeProgressSliderNowPlaying(); // }
showPlaybackControllerCard = PreferenceUtil.getInstance(activity).playbackControllerCardNowPlaying(); //
colorPlaybackControls = PreferenceUtil.getInstance(activity).colorPlaybackControlsNowPlaying(); // private void alignAlbumArtToTop() {
} // RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) albumArtFrame.getLayoutParams();
// if (Build.VERSION.SDK_INT > 16) {
private void initProgressSliderDependentViews() { // params.removeRule(RelativeLayout.BELOW);
if (getView() == null) return; // } else {
if (alternativeProgressSlider) { // params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
getView().findViewById(R.id.player_default_progress_container).setVisibility(View.GONE); // ViewGroup.LayoutParams.MATCH_PARENT);
getView().findViewById(R.id.player_default_progress_slider).setVisibility(View.GONE); // params.addRule(RelativeLayout.ABOVE, R.id.player_footer_frame);
getView().findViewById(R.id.player_alternative_progress_container).setVisibility(View.VISIBLE); // }
// }
songCurrentProgress = (TextView) getView().findViewById(R.id.player_alternative_song_current_progress); //
songTotalTime = (TextView) getView().findViewById(R.id.player_alternative_song_total_time); // private void alignAlbumArtToToolbar() {
progressSlider = (SeekBar) getView().findViewById(R.id.player_alternative_progress_slider); // RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) albumArtFrame.getLayoutParams();
} else { // params.addRule(RelativeLayout.BELOW, R.id.player_toolbar);
getView().findViewById(R.id.player_default_progress_container).setVisibility(View.VISIBLE); // }
getView().findViewById(R.id.player_default_progress_slider).setVisibility(View.VISIBLE); //
getView().findViewById(R.id.player_alternative_progress_container).setVisibility(View.GONE); // private void alignAlbumArtToStatusBar() {
// RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) albumArtFrame.getLayoutParams();
songCurrentProgress = (TextView) getView().findViewById(R.id.player_default_song_current_progress); // params.addRule(RelativeLayout.BELOW, R.id.player_status_bar);
songTotalTime = (TextView) getView().findViewById(R.id.player_default_song_total_time); // }
progressSlider = (SeekBar) getView().findViewById(R.id.player_default_progress_slider);
}
}
private void moveProgressSliderIntoPlace() {
if (!alternativeProgressSlider) {
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) progressSlider.getLayoutParams();
progressSlider.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
final int seekBarMarginLeftRight = getResources().getDimensionPixelSize(R.dimen.seek_bar_margin_left_right);
lp.setMargins(seekBarMarginLeftRight, 0, seekBarMarginLeftRight, -(progressSlider.getMeasuredHeight() / 2));
progressSlider.setLayoutParams(lp);
}
}
private void adjustTitleBoxSize() {
int paddingTopBottom = largerTitleBox ? getResources().getDimensionPixelSize(R.dimen.title_box_padding_large) : getResources().getDimensionPixelSize(R.dimen.title_box_padding_small);
footer.setPadding(footer.getPaddingLeft(), paddingTopBottom, footer.getPaddingRight(), paddingTopBottom);
songTitle.setPadding(songTitle.getPaddingLeft(), songTitle.getPaddingTop(), songTitle.getPaddingRight(), largerTitleBox ? getResources().getDimensionPixelSize(R.dimen.title_box_text_spacing_large) : getResources().getDimensionPixelSize(R.dimen.title_box_text_spacing_small));
songText.setPadding(songText.getPaddingLeft(), largerTitleBox ? getResources().getDimensionPixelSize(R.dimen.title_box_text_spacing_large) : getResources().getDimensionPixelSize(R.dimen.title_box_text_spacing_small), songText.getPaddingRight(), songText.getPaddingBottom());
songTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, largerTitleBox ? getResources().getDimensionPixelSize(R.dimen.title_box_title_text_size_large) : getResources().getDimensionPixelSize(R.dimen.title_box_title_text_size_small));
songText.setTextSize(TypedValue.COMPLEX_UNIT_PX, largerTitleBox ? getResources().getDimensionPixelSize(R.dimen.title_box_caption_text_size_large) : getResources().getDimensionPixelSize(R.dimen.title_box_caption_text_size_small));
}
private void setUpPlaybackControllerCard() {
playbackControllerCard.setVisibility(showPlaybackControllerCard ? View.VISIBLE : View.GONE);
mediaControllerContainerBackground.setVisibility(showPlaybackControllerCard ? View.GONE : View.VISIBLE);
}
private void setUpMusicControllers() {
setUpPrevNext();
setUpRepeatButton();
setUpShuffleButton();
setUpProgressSlider();
}
private void setUpProgressSliderTint() {
int thumbColor;
int progressColor;
if (alternativeProgressSlider) {
if (colorPlaybackControls) {
thumbColor = lastPlaybackControlsColor;
} else {
thumbColor = ThemeSingleton.get().positiveColor.getDefaultColor();
}
progressColor = Color.TRANSPARENT;
} else {
if (colorPlaybackControls) {
if (ColorUtil.useDarkTextColorOnBackground(lastPlaybackControlsColor)) {
thumbColor = ColorUtil.shiftColor(lastPlaybackControlsColor, 1.2f);
} else {
thumbColor = ColorUtil.shiftColor(lastPlaybackControlsColor, 0.8f);
}
} else {
thumbColor = activity.getThemeColorAccent();
}
progressColor = thumbColor;
}
setSeekBarTint(progressSlider, thumbColor, progressColor);
}
private static void setSeekBarTint(SeekBar seekBar, @ColorInt int thumbColor, @ColorInt int progressColor) {
seekBar.getThumb().mutate().setColorFilter(thumbColor, PorterDuff.Mode.SRC_IN);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// this will only tint the left part of the progress bar
seekBar.setProgressTintList(ColorStateList.valueOf(progressColor));
} else {
seekBar.getProgressDrawable().mutate().setColorFilter(progressColor, PorterDuff.Mode.SRC_IN);
}
}
private void setUpProgressSlider() {
initProgressSliderDependentViews();
moveProgressSliderIntoPlace();
setUpProgressSliderTint();
progressSlider.setOnSeekBarChangeListener(new SimpleOnSeekbarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
MusicPlayerRemote.seekTo(progress);
onUpdateProgressViews(MusicPlayerRemote.getSongProgressMillis(), MusicPlayerRemote.getSongDurationMillis());
}
}
});
}
private void setUpPrevNext() {
int themedDrawableColor = ColorUtil.resolveColor(activity, android.R.attr.textColorSecondary);
nextButton.setImageDrawable(Util.getTintedDrawable(activity,
R.drawable.ic_skip_next_white_36dp, themedDrawableColor));
prevButton.setImageDrawable(Util.getTintedDrawable(activity,
R.drawable.ic_skip_previous_white_36dp, themedDrawableColor));
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 setUpShuffleButton() {
updateShuffleState();
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.setImageDrawable(Util.getTintedDrawable(activity, R.drawable.ic_shuffle_white_36dp,
getActivatedIconColor()));
break;
default:
shuffleButton.setImageDrawable(Util.getTintedDrawable(activity, R.drawable.ic_shuffle_white_36dp,
getDeactivatedIconColor()));
break;
}
}
private void setUpRepeatButton() {
updateRepeatState();
repeatButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MusicPlayerRemote.cycleRepeatMode();
}
});
}
private void updateRepeatState() {
switch (MusicPlayerRemote.getRepeatMode()) {
case MusicService.REPEAT_MODE_ALL:
repeatButton.setImageDrawable(Util.getTintedDrawable(activity, R.drawable.ic_repeat_white_36dp,
getActivatedIconColor()));
break;
case MusicService.REPEAT_MODE_THIS:
repeatButton.setImageDrawable(Util.getTintedDrawable(activity, R.drawable.ic_repeat_one_white_36dp,
getActivatedIconColor()));
break;
default:
repeatButton.setImageDrawable(Util.getTintedDrawable(activity, R.drawable.ic_repeat_white_36dp,
getDeactivatedIconColor()));
break;
}
}
private int getActivatedIconColor() {
if (colorPlaybackControls) {
return ensureActivatedColorVisibleIfNecessary(lastPlaybackControlsColor);
} else {
return ThemeSingleton.get().positiveColor.getDefaultColor();
}
}
private int getDeactivatedIconColor() {
return ColorUtil.resolveColor(activity, android.R.attr.textColorSecondary);
}
/**
* @return If the activated color wont have enough difference to the deactivated color Color.WHITE / Color.BLACK (depending on the theme),
* else the unmodified accentColor.
*/
private int ensureActivatedColorVisibleIfNecessary(int activatedColor) {
// Not optimal, but much easier then computing the opaque deactivated color on the background color every time.
int preBlendedDeactivatedIconColor = ThemeSingleton.get().darkTheme ? Color.argb(255, 188, 188, 188) : Color.argb(255, 115, 115, 115);
if (ColorUtil.getColorDifference(activatedColor, preBlendedDeactivatedIconColor) <= 30d) {
return ThemeSingleton.get().darkTheme ? Color.WHITE : Color.BLACK;
}
return activatedColor;
}
private void setUpAlbumArtViews() {
albumArt.forceSquare(forceSquareAlbumArt);
if (opaqueStatusBar) {
if (opaqueToolBar) {
alignAlbumArtToToolbar();
} else {
alignAlbumArtToStatusBar();
}
} else {
alignAlbumArtToTop();
}
}
private void alignAlbumArtToTop() {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) albumArtFrame.getLayoutParams();
if (Build.VERSION.SDK_INT > 16) {
params.removeRule(RelativeLayout.BELOW);
} else {
params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
params.addRule(RelativeLayout.ABOVE, R.id.player_footer_frame);
}
}
private void alignAlbumArtToToolbar() {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) albumArtFrame.getLayoutParams();
params.addRule(RelativeLayout.BELOW, R.id.player_toolbar);
}
private void alignAlbumArtToStatusBar() {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) albumArtFrame.getLayoutParams();
params.addRule(RelativeLayout.BELOW, R.id.player_status_bar);
}
private void setUpPlayerToolbar() { private void setUpPlayerToolbar() {
toolbar.inflateMenu(R.menu.menu_player); toolbar.inflateMenu(R.menu.menu_player);
@ -567,19 +298,19 @@ public class PlayerFragment extends Fragment implements SharedPreferences.OnShar
toolbar.setOnMenuItemClickListener(this); toolbar.setOnMenuItemClickListener(this);
} }
private void setUpPlayerStatusBarElevation() { // private void setUpPlayerStatusBarElevation() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (opaqueToolBar) { // if (opaqueToolBar) {
statusbar.setElevation(getResources().getDimensionPixelSize(R.dimen.toolbar_elevation)); // statusbar.setElevation(getResources().getDimensionPixelSize(R.dimen.toolbar_elevation));
} else { // } else {
statusbar.setElevation(0); // statusbar.setElevation(0);
} // }
} // }
} // }
private void updatePlayerMenu() { private void updatePlayerMenu() {
boolean isFavorite = MusicUtil.isFavorite(activity, song); boolean isFavorite = MusicUtil.isFavorite(activity, song);
Drawable favoriteIcon = Util.getTintedDrawable(activity, isFavorite ? R.drawable.ic_favorite_white_24dp : R.drawable.ic_favorite_outline_white_24dp, ViewUtil.getToolbarIconColor(activity, opaqueToolBar && ColorUtil.useDarkTextColorOnBackground(lastFooterColor))); Drawable favoriteIcon = Util.getTintedDrawable(activity, isFavorite ? R.drawable.ic_favorite_white_24dp : R.drawable.ic_favorite_outline_white_24dp, ViewUtil.getToolbarIconColor(activity, PreferenceUtil.getInstance(activity).opaqueToolbarNowPlaying() && ColorUtil.useDarkTextColorOnBackground(lastColor)));
toolbar.getMenu().findItem(R.id.action_toggle_favorite) toolbar.getMenu().findItem(R.id.action_toggle_favorite)
.setIcon(favoriteIcon) .setIcon(favoriteIcon)
.setTitle(isFavorite ? getString(R.string.action_remove_from_favorites) : getString(R.string.action_add_to_favorites)); .setTitle(isFavorite ? getString(R.string.action_remove_from_favorites) : getString(R.string.action_add_to_favorites));
@ -587,8 +318,6 @@ public class PlayerFragment extends Fragment implements SharedPreferences.OnShar
private void updateCurrentSong() { private void updateCurrentSong() {
getCurrentSong(); getCurrentSong();
updateMetaTexts();
setUpAlbumArtAndApplyPalette();
updatePlayerMenu(); updatePlayerMenu();
} }
@ -596,128 +325,62 @@ public class PlayerFragment extends Fragment implements SharedPreferences.OnShar
song = MusicPlayerRemote.getCurrentSong(); song = MusicPlayerRemote.getCurrentSong();
} }
private void updateMetaTexts() {
songTitle.setText(song.title);
songText.setText(song.artistName);
}
@Override @Override
@ColorInt @ColorInt
public int getPaletteColor() { public int getPaletteColor() {
return lastFooterColor; return lastColor;
} }
@Override @Override
public void onUpdateProgressViews(int progress, int total) { public void onUpdateProgressViews(int progress, int total) {
progressSlider.setMax(total); // progressSlider.setMax(total);
progressSlider.setProgress(progress); // progressSlider.setProgress(progress);
songTotalTime.setText(MusicUtil.getReadableDurationString(total)); // songTotalTime.setText(MusicUtil.getReadableDurationString(total));
songCurrentProgress.setText(MusicUtil.getReadableDurationString(progress)); // songCurrentProgress.setText(MusicUtil.getReadableDurationString(progress));
}
private static class ColorHolder {
@ColorInt
public int color;
}
private void setUpAlbumArtAndApplyPalette() {
final ColorHolder colorHolder = new ColorHolder();
ImageLoader.getInstance().displayImage(
MusicUtil.getSongImageLoaderString(song),
albumArt,
new DisplayImageOptions.Builder()
.cacheInMemory(true)
.showImageOnFail(R.drawable.default_album_art)
.postProcessor(new BitmapProcessor() {
@Override
public Bitmap process(Bitmap bitmap) {
colorHolder.color = ColorUtil.generateColor(activity, bitmap);
return bitmap;
}
})
.displayer(new FadeInBitmapDisplayer(ViewUtil.DEFAULT_COLOR_ANIMATION_DURATION) {
@Override
public void display(Bitmap bitmap, ImageAware imageAware, LoadedFrom loadedFrom) {
super.display(bitmap, imageAware, loadedFrom);
setColors(colorHolder.color);
}
})
.build(),
new SimpleImageLoadingListener() {
@Override
public void onLoadingFailed(String imageUri, View view, @Nullable FailReason failReason) {
FadeInBitmapDisplayer.animate(view, ViewUtil.DEFAULT_COLOR_ANIMATION_DURATION);
setColors(ColorUtil.resolveColor(activity, R.attr.default_bar_color));
}
@Override
public void onLoadingComplete(String imageUri, View view, @Nullable Bitmap loadedImage) {
if (loadedImage == null) {
onLoadingFailed(imageUri, view, null);
}
}
}
);
}
private void setColors(int color) {
animateColorChange(color);
callbacks.onPaletteColorChanged();
} }
private void animateColorChange(final int newColor) { private void animateColorChange(final int newColor) {
if (colorTransitionAnimator != null && colorTransitionAnimator.isStarted()) { // if (colorTransitionAnimator != null && colorTransitionAnimator.isStarted()) {
colorTransitionAnimator.cancel(); // colorTransitionAnimator.cancel();
} // }
colorTransitionAnimator = new AnimatorSet(); // colorTransitionAnimator = new AnimatorSet();
AnimatorSet.Builder animatorSetBuilder = colorTransitionAnimator.play(ViewUtil.createBackgroundColorTransition(footer, lastFooterColor, newColor)); // AnimatorSet.Builder animatorSetBuilder = colorTransitionAnimator.play(ViewUtil.createBackgroundColorTransition(footer, lastColor, newColor));
//
// if (opaqueToolBar) {
// animatorSetBuilder.with(ViewUtil.createBackgroundColorTransition(toolbar, lastColor, newColor));
// ViewUtil.setToolbarContentColorForBackground(activity, toolbar, newColor);
// } else {
// toolbar.setBackgroundColor(Color.TRANSPARENT);
// ViewUtil.setToolbarContentDark(activity, toolbar, false);
// }
//
// if (opaqueStatusBar) {
// int newStatusbarColor = newColor;
// int oldStatusbarColor = lastColor;
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// newStatusbarColor = ColorUtil.shiftColorDown(newStatusbarColor);
// oldStatusbarColor = ColorUtil.shiftColorDown(oldStatusbarColor);
// }
// animatorSetBuilder.with(ViewUtil.createBackgroundColorTransition(statusbar, oldStatusbarColor, newStatusbarColor));
// } else {
// statusbar.setBackgroundColor(Color.TRANSPARENT);
// }
//
// colorTransitionAnimator.addListener(new SimpleAnimatorListener() {
// @Override
// public void onAnimationStart(Animator animation) {
// if (newColor == ColorUtil.resolveColor(activity, R.attr.default_bar_color) && ThemeSingleton.get().darkTheme) {
// lastPlaybackControlsColor = Color.WHITE;
// } else {
// lastPlaybackControlsColor = newColor;
// }
// updateProgressSliderTint();
// }
// });
//
// colorTransitionAnimator.start();
if (opaqueToolBar) { lastColor = newColor;
animatorSetBuilder.with(ViewUtil.createBackgroundColorTransition(toolbar, lastFooterColor, newColor));
ViewUtil.setToolbarContentColorForBackground(activity, toolbar, newColor);
} else {
toolbar.setBackgroundColor(Color.TRANSPARENT);
ViewUtil.setToolbarContentDark(activity, toolbar, false);
}
if (opaqueStatusBar) {
int newStatusbarColor = newColor;
int oldStatusbarColor = lastFooterColor;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
newStatusbarColor = ColorUtil.shiftColorDown(newStatusbarColor);
oldStatusbarColor = ColorUtil.shiftColorDown(oldStatusbarColor);
}
animatorSetBuilder.with(ViewUtil.createBackgroundColorTransition(statusbar, oldStatusbarColor, newStatusbarColor));
} else {
statusbar.setBackgroundColor(Color.TRANSPARENT);
}
int titleTextColor = ColorUtil.getPrimaryTextColorForBackground(activity, newColor);
int captionTextColor = ColorUtil.getSecondaryTextColorForBackground(activity, newColor);
animatorSetBuilder.with(ViewUtil.createTextColorTransition(songTitle, lastTitleTextColor, titleTextColor));
animatorSetBuilder.with(ViewUtil.createTextColorTransition(songText, lastCaptionTextColor, captionTextColor));
colorTransitionAnimator.addListener(new SimpleAnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
if (newColor == ColorUtil.resolveColor(activity, R.attr.default_bar_color) && ThemeSingleton.get().darkTheme) {
lastPlaybackControlsColor = Color.WHITE;
} else {
lastPlaybackControlsColor = newColor;
}
updateRepeatState();
updateShuffleState();
setUpProgressSliderTint();
setUpPlayerPlayPauseFabTint();
}
});
colorTransitionAnimator.start();
lastFooterColor = newColor;
lastTitleTextColor = titleTextColor;
lastCaptionTextColor = captionTextColor;
} }
@Override @Override
@ -729,7 +392,7 @@ public class PlayerFragment extends Fragment implements SharedPreferences.OnShar
case R.id.action_toggle_favorite: case R.id.action_toggle_favorite:
MusicUtil.toggleFavorite(activity, song); MusicUtil.toggleFavorite(activity, song);
if (MusicUtil.isFavorite(activity, song)) { if (MusicUtil.isFavorite(activity, song)) {
animateSetFavorite(); playerAlbumCoverFragment.showHeart();
} }
updatePlayerMenu(); updatePlayerMenu();
return true; return true;
@ -766,71 +429,19 @@ public class PlayerFragment extends Fragment implements SharedPreferences.OnShar
return false; return false;
} }
private void animateSetFavorite() {
favoriteIcon.clearAnimation();
favoriteIcon.setAlpha(0f);
favoriteIcon.setScaleX(0f);
favoriteIcon.setScaleY(0f);
favoriteIcon.setVisibility(View.VISIBLE);
favoriteIcon.setPivotX(favoriteIcon.getWidth() / 2);
favoriteIcon.setPivotY(favoriteIcon.getHeight() / 2);
favoriteIcon.animate()
.setDuration(600)
.setInterpolator(new OvershootInterpolator())
.scaleX(1f)
.scaleY(1f)
.alpha(1f)
.setListener(new SimpleAnimatorListener() {
@Override
public void onAnimationCancel(Animator animation) {
favoriteIcon.setVisibility(View.INVISIBLE);
}
})
.withEndAction(new Runnable() {
@Override
public void run() {
favoriteIcon.animate()
.setDuration(300)
.setInterpolator(new DecelerateInterpolator())
.alpha(0f)
.start();
}
})
.start();
}
public void showControls() { public void showControls() {
playPauseFab.animate() playbackControlsFragment.showControls();
.scaleX(1f)
.scaleY(1f)
.rotation(360f)
.setInterpolator(new DecelerateInterpolator())
.start();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (mediaControllerContainer.getVisibility() == View.INVISIBLE) {
int cx = (playPauseFab.getLeft() + playPauseFab.getRight()) / 2;
int cy = (playPauseFab.getTop() + playPauseFab.getBottom()) / 2;
int finalRadius = Math.max(mediaControllerContainer.getWidth(), mediaControllerContainer.getHeight());
final Animator animator = ViewAnimationUtils.createCircularReveal(mediaControllerContainer, cx, cy, 0, finalRadius);
animator.setInterpolator(new DecelerateInterpolator());
animator.setDuration(FAB_CIRCULAR_REVEAL_ANIMATION_TIME);
animator.start();
mediaControllerContainer.setVisibility(View.VISIBLE);
}
}
} }
public void resetShowControlsAnimation() { public void resetShowControlsAnimation() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { playbackControlsFragment.resetShowControlsAnimation();
mediaControllerContainer.setVisibility(View.INVISIBLE); }
}
playPauseFab.setScaleX(0f); @Override
playPauseFab.setScaleY(0f); public void onColorChanged(int color) {
playPauseFab.setRotation(0f); animateColorChange(color);
playbackControlsFragment.setColor(color);
callbacks.onPaletteColorChanged();
} }
public interface Callbacks { public interface Callbacks {

View file

@ -0,0 +1,41 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="false">
<include layout="@layout/shadow_statusbar_actionbar" />
<View
android:id="@+id/player_status_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/status_bar_padding"
android:background="@android:color/transparent"
android:elevation="@dimen/toolbar_elevation"
tools:ignore="UnusedAttribute" />
<android.support.v7.widget.Toolbar
android:id="@+id/player_toolbar"
style="@style/Toolbar"
android:layout_below="@id/player_status_bar"
android:background="@android:color/transparent"
tools:ignore="UnusedAttribute" />
<fragment
android:layout_alignParentLeft="true"
android:id="@+id/player_album_cover_fragment"
class="com.kabouzeid.gramophone.ui.fragments.PlayerAlbumCoverFragment"
android:layout_width="wrap_content"
android:layout_height="match_parent"
tools:layout="@layout/fragment_player_album_cover" />
<fragment
android:layout_toRightOf="@id/player_album_cover_fragment"
android:id="@+id/playback_controls_fragment"
class="com.kabouzeid.gramophone.ui.fragments.PlaybackControlsFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:layout="@layout/fragment_playback_controls" />
</RelativeLayout>

View file

@ -0,0 +1,143 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/player_footer_frame"
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">
<LinearLayout
android:id="@+id/player_footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?default_bar_color"
android:elevation="@dimen/toolbar_elevation"
android:orientation="vertical"
android:paddingBottom="@dimen/title_box_padding_large"
android:paddingLeft="72dp"
android:paddingRight="72dp"
android:paddingTop="@dimen/title_box_padding_large"
tools:ignore="UnusedAttribute">
<TextView
android:id="@+id/player_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Title" />
<TextView
android:id="@+id/player_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Caption" />
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<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">
<View
android:id="@+id/player_media_controller_container_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?music_controller_container_color" />
<android.support.v7.widget.CardView
android:id="@+id/player_playback_controller_card"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
android:visibility="gone"
app:cardBackgroundColor="?music_controller_container_color"
app:elevation="@dimen/card_elevation" />
<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/dummy_fab"
android:layout_toStartOf="@+id/dummy_fab"
android:background="?round_selector"
android:elevation="8dp"
android:padding="22dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_skip_previous_white_36dp" />
<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/dummy_fab"
android:layout_toRightOf="@+id/dummy_fab"
android:background="?round_selector"
android:elevation="8dp"
android:padding="22dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_skip_next_white_36dp" />
<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="24dp"
android:layout_marginStart="24dp"
android:background="?round_selector"
android:elevation="8dp"
android:padding="22dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_repeat_white_36dp" />
<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="24dp"
android:layout_marginRight="24dp"
android:background="?round_selector"
android:elevation="8dp"
android:padding="22dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_shuffle_white_36dp" />
<View
android:id="@+id/dummy_fab"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_centerInParent="true"
android:visibility="invisible" />
</RelativeLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/player_play_pause_fab"
style="@style/PlayPauseFab"
android:layout_gravity="center" />
</FrameLayout>
</LinearLayout>

View file

@ -1,277 +1,25 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout 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" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:clickable="true" android:clickable="true"
android:focusable="false"> android:focusable="false">
<!-- BOTTOM--> <fragment
android:id="@+id/player_album_cover_fragment"
<LinearLayout class="com.kabouzeid.gramophone.ui.fragments.PlayerAlbumCoverFragment"
android:id="@+id/player_footer_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="?android:colorBackground"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/player_alternative_progress_container"
android:layout_width="match_parent"
android:layout_height="@dimen/progress_container_height"
android:background="?music_controller_container_color"
android:elevation="@dimen/toolbar_elevation"
android:visibility="gone"
tools:ignore="UnusedAttribute">
<TextView
android:id="@+id/player_alternative_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="?android:textColorSecondary"
android:textSize="10sp"
tools:ignore="RtlHardcoded,RtlSymmetry,SmallSp" />
<TextView
android:id="@+id/player_alternative_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="?android:textColorSecondary"
android:textSize="10sp"
tools:ignore="RtlHardcoded,RtlSymmetry,SmallSp" />
<SeekBar
android:id="@+id/player_alternative_progress_slider"
style="@style/MusicProgressSlider"
android:layout_height="match_parent"
android:layout_toLeftOf="@id/player_alternative_song_total_time"
android:layout_toRightOf="@id/player_alternative_song_current_progress"
tools:ignore="RtlHardcoded,UnusedAttribute" />
</RelativeLayout>
<LinearLayout
android:id="@+id/player_footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?default_bar_color"
android:elevation="@dimen/toolbar_elevation"
android:orientation="vertical"
android:paddingBottom="@dimen/title_box_padding_large"
android:paddingLeft="72dp"
android:paddingRight="72dp"
android:paddingTop="@dimen/title_box_padding_large"
tools:ignore="UnusedAttribute">
<TextView
android:id="@+id/player_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Title" />
<TextView
android:id="@+id/player_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Caption" />
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<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">
<View
android:id="@+id/player_media_controller_container_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?music_controller_container_color" />
<android.support.v7.widget.CardView
android:id="@+id/player_playback_controller_card"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
android:visibility="gone"
app:cardBackgroundColor="?music_controller_container_color"
app:elevation="@dimen/card_elevation" />
<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/dummy_fab"
android:layout_toStartOf="@+id/dummy_fab"
android:background="?round_selector"
android:elevation="8dp"
android:padding="22dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_skip_previous_white_36dp" />
<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/dummy_fab"
android:layout_toRightOf="@+id/dummy_fab"
android:background="?round_selector"
android:elevation="8dp"
android:padding="22dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_skip_next_white_36dp" />
<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="24dp"
android:layout_marginStart="24dp"
android:background="?round_selector"
android:elevation="8dp"
android:padding="22dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_repeat_white_36dp" />
<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="24dp"
android:layout_marginRight="24dp"
android:background="?round_selector"
android:elevation="8dp"
android:padding="22dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_shuffle_white_36dp" />
<View
android:id="@+id/dummy_fab"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_centerInParent="true"
android:visibility="invisible" />
</RelativeLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/player_play_pause_fab"
style="@style/PlayPauseFab"
android:layout_gravity="center" />
</FrameLayout>
</LinearLayout>
<!-- ALBUMART-->
<FrameLayout
android:id="@+id/player_album_art_frame"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_above="@id/player_footer_frame" android:layout_above="@+id/playback_controls_fragment"
android:background="@android:color/black"> tools:layout="@layout/fragment_player_album_cover" />
<com.kabouzeid.gramophone.views.SquareIfPlaceImageView <fragment
android:id="@+id/player_image" android:layout_alignParentBottom="true"
android:layout_width="match_parent" android:id="@+id/playback_controls_fragment"
android:layout_height="match_parent" class="com.kabouzeid.gramophone.ui.fragments.PlaybackControlsFragment"
android:layout_gravity="center" android:layout_width="match_parent"
android:scaleType="centerCrop" android:layout_height="wrap_content"
android:src="@drawable/default_album_art" tools:layout="@layout/fragment_playback_controls" />
tools:ignore="ContentDescription,UnusedAttribute" />
<ImageView
android:id="@+id/player_favorite_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_favorite_red_a400_96dp"
android:visibility="invisible"
tools:ignore="ContentDescription" />
<RelativeLayout
android:id="@+id/player_default_progress_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="@drawable/shadow_up">
<TextView
android:id="@+id/player_default_song_current_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:fontFamily="sans-serif-medium"
android:gravity="center_vertical|left|end"
android:padding="16dp"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:textColor="@android:color/white"
android:textSize="16sp"
tools:ignore="RtlHardcoded,RtlSymmetry,SmallSp" />
<TextView
android:id="@+id/player_default_song_total_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:fontFamily="sans-serif-medium"
android:gravity="center_vertical|right|end"
android:padding="16dp"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:textColor="@android:color/white"
android:textSize="16sp"
tools:ignore="RelativeOverlap,RtlHardcoded,RtlSymmetry,SmallSp" />
</RelativeLayout>
</FrameLayout>
<!-- PROGRESS SLIDER-->
<SeekBar
android:id="@+id/player_default_progress_slider"
style="@style/TraditionalMusicProgressSlider"
android:layout_above="@id/player_footer_frame"
android:elevation="2dp"
tools:ignore="UnusedAttribute" />
<!-- TOOLBAR-->
<include layout="@layout/shadow_statusbar_actionbar" /> <include layout="@layout/shadow_statusbar_actionbar" />
@ -287,7 +35,7 @@
android:id="@+id/player_toolbar" android:id="@+id/player_toolbar"
style="@style/Toolbar" style="@style/Toolbar"
android:layout_below="@id/player_status_bar" android:layout_below="@id/player_status_bar"
android:background="#00000000" android:background="@android:color/transparent"
tools:ignore="UnusedAttribute" /> tools:ignore="UnusedAttribute" />
</RelativeLayout> </RelativeLayout>

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
android:id="@+id/player_album_art_frame"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/player_footer_frame"
android:background="@android:color/black">
<com.kabouzeid.gramophone.views.SquareIfPlaceImageView
android:id="@+id/player_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:scaleType="centerCrop"
android:src="@drawable/default_album_art"
tools:ignore="ContentDescription,UnusedAttribute" />
<ImageView
android:id="@+id/player_favorite_icon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:src="@drawable/ic_favorite_red_a400_96dp"
android:visibility="invisible"
tools:ignore="ContentDescription" />
</FrameLayout>