Added progress bar to the mini player.
This commit is contained in:
parent
4d84e4d600
commit
51f2a3bd3b
18 changed files with 1260 additions and 1039 deletions
|
|
@ -0,0 +1,65 @@
|
||||||
|
package com.kabouzeid.gramophone.helper;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karim Abou Zeid (kabouzeid)
|
||||||
|
*/
|
||||||
|
public class MusicProgressViewUpdateHelper extends Handler {
|
||||||
|
private static final int CMD_REFRESH_PROGRESS_VIEWS = 1;
|
||||||
|
|
||||||
|
private Callback callback;
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
queueNextRefresh(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
removeMessages(CMD_REFRESH_PROGRESS_VIEWS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MusicProgressViewUpdateHelper(Callback callback) {
|
||||||
|
this.callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(@NonNull Message msg) {
|
||||||
|
super.handleMessage(msg);
|
||||||
|
if (msg.what == CMD_REFRESH_PROGRESS_VIEWS) {
|
||||||
|
queueNextRefresh(refreshProgressViews());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private long refreshProgressViews() {
|
||||||
|
final int progressMillis = MusicPlayerRemote.getSongProgressMillis();
|
||||||
|
final int totalMillis = MusicPlayerRemote.getSongDurationMillis();
|
||||||
|
|
||||||
|
callback.onUpdateProgressViews(progressMillis, totalMillis);
|
||||||
|
|
||||||
|
if (!MusicPlayerRemote.isPlaying()) {
|
||||||
|
return 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate the number of milliseconds until the next full second,
|
||||||
|
// so
|
||||||
|
// the counter can be updated at just the right time
|
||||||
|
final long remainingMillis = 1000 - progressMillis % 1000;
|
||||||
|
if (remainingMillis < 20) {
|
||||||
|
return 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
return remainingMillis;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void queueNextRefresh(final long delay) {
|
||||||
|
final Message message = obtainMessage(CMD_REFRESH_PROGRESS_VIEWS);
|
||||||
|
removeMessages(CMD_REFRESH_PROGRESS_VIEWS);
|
||||||
|
sendMessageDelayed(message, delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Callback {
|
||||||
|
void onUpdateProgressViews(int progress, int total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.kabouzeid.gramophone.helper;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karim Abou Zeid (kabouzeid)
|
||||||
|
*/
|
||||||
|
public class PlayPauseButtonOnClickHandler implements View.OnClickListener {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (MusicPlayerRemote.isPlaying()) {
|
||||||
|
MusicPlayerRemote.pauseSong();
|
||||||
|
} else {
|
||||||
|
MusicPlayerRemote.resumePlaying();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
package com.kabouzeid.gramophone.interfaces;
|
package com.kabouzeid.gramophone.interfaces;
|
||||||
|
|
||||||
|
import android.support.annotation.ColorInt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Aidan Follestad (afollestad)
|
* @author Aidan Follestad (afollestad)
|
||||||
*/
|
*/
|
||||||
public interface PaletteColorHolder {
|
public interface PaletteColorHolder {
|
||||||
|
|
||||||
|
@ColorInt
|
||||||
int getPaletteColor();
|
int getPaletteColor();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected View createContentView() {
|
protected View createContentView() {
|
||||||
return wrapSlidingMusicPanelAndFab(R.layout.activity_album_detail);
|
return wrapSlidingMusicPanel(R.layout.activity_album_detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final SimpleObservableScrollViewCallbacks observableScrollViewCallbacks = new SimpleObservableScrollViewCallbacks() {
|
private final SimpleObservableScrollViewCallbacks observableScrollViewCallbacks = new SimpleObservableScrollViewCallbacks() {
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected View createContentView() {
|
protected View createContentView() {
|
||||||
return wrapSlidingMusicPanelAndFab(R.layout.activity_artist_detail);
|
return wrapSlidingMusicPanel(R.layout.activity_artist_detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final SimpleObservableScrollViewCallbacks observableScrollViewCallbacks = new SimpleObservableScrollViewCallbacks() {
|
private final SimpleObservableScrollViewCallbacks observableScrollViewCallbacks = new SimpleObservableScrollViewCallbacks() {
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,6 @@ import com.kabouzeid.gramophone.util.Util;
|
||||||
import com.kabouzeid.gramophone.util.ViewUtil;
|
import com.kabouzeid.gramophone.util.ViewUtil;
|
||||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
import com.sothree.slidinguppanel.SlidingUpPanelLayout;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -121,7 +120,7 @@ public class MainActivity extends AbsSlidingMusicPanelActivity
|
||||||
@SuppressLint("InflateParams")
|
@SuppressLint("InflateParams")
|
||||||
View contentView = getLayoutInflater().inflate(R.layout.activity_main_drawer_layout, null);
|
View contentView = getLayoutInflater().inflate(R.layout.activity_main_drawer_layout, null);
|
||||||
ViewGroup drawerContent = ButterKnife.findById(contentView, R.id.drawer_content_container);
|
ViewGroup drawerContent = ButterKnife.findById(contentView, R.id.drawer_content_container);
|
||||||
drawerContent.addView(wrapSlidingMusicPanelAndFab(R.layout.activity_main_content));
|
drawerContent.addView(wrapSlidingMusicPanel(R.layout.activity_main_content));
|
||||||
return contentView;
|
return contentView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -261,8 +260,8 @@ public class MainActivity extends AbsSlidingMusicPanelActivity
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
drawerLayout.closeDrawers();
|
drawerLayout.closeDrawers();
|
||||||
if (getSlidingUpPanelLayout().getPanelState() != SlidingUpPanelLayout.PanelState.EXPANDED) {
|
if (isPanelCollapsed()) {
|
||||||
getSlidingUpPanelLayout().setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED);
|
toggleSlidingPanel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -564,46 +563,10 @@ public class MainActivity extends AbsSlidingMusicPanelActivity
|
||||||
return pagerAdapter.getFragment(pager.getCurrentItem());
|
return pagerAdapter.getFragment(pager.getCurrentItem());
|
||||||
}
|
}
|
||||||
|
|
||||||
// private boolean isArtistPage() {
|
|
||||||
// return pager.getCurrentItem() == PagerAdapter.MusicFragments.ARTIST.ordinal();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public ArtistsFragment getArtistFragment() {
|
|
||||||
// return (ArtistsFragment) pagerAdapter.getFragment(PagerAdapter.MusicFragments.ARTIST.ordinal());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private boolean isAlbumPage() {
|
|
||||||
// return pager.getCurrentItem() == PagerAdapter.MusicFragments.ALBUM.ordinal();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public AlbumsFragment getAlbumFragment() {
|
|
||||||
// return (AlbumsFragment) pagerAdapter.getFragment(PagerAdapter.MusicFragments.ALBUM.ordinal());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private boolean isSongPage() {
|
|
||||||
// return pager.getCurrentItem() == PagerAdapter.MusicFragments.SONG.ordinal();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public SongsFragment getSongFragment() {
|
|
||||||
// return (SongsFragment) pagerAdapter.getFragment(PagerAdapter.MusicFragments.SONG.ordinal());
|
|
||||||
// }
|
|
||||||
|
|
||||||
private boolean isPlaylistPage() {
|
private boolean isPlaylistPage() {
|
||||||
return pager.getCurrentItem() == PagerAdapter.MusicFragments.PLAYLIST.ordinal();
|
return pager.getCurrentItem() == PagerAdapter.MusicFragments.PLAYLIST.ordinal();
|
||||||
}
|
}
|
||||||
|
|
||||||
// public PlaylistsFragment getPlaylistFragment() {
|
|
||||||
// return (PlaylistsFragment) pagerAdapter.getFragment(PagerAdapter.MusicFragments.PLAYLIST.ordinal());
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void showOverflowMenu() {
|
|
||||||
super.showOverflowMenu();
|
|
||||||
if (toolbar != null && getSlidingUpPanelLayout().getPanelState() != SlidingUpPanelLayout.PanelState.EXPANDED)
|
|
||||||
toolbar.showOverflowMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MaterialCab openCab(final int menu, final MaterialCab.Callback callback) {
|
public MaterialCab openCab(final int menu, final MaterialCab.Callback callback) {
|
||||||
if (cab != null && cab.isActive()) cab.finish();
|
if (cab != null && cab.isActive()) cab.finish();
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity impleme
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected View createContentView() {
|
protected View createContentView() {
|
||||||
return wrapSlidingMusicPanelAndFab(R.layout.activity_playlist_detail);
|
return wrapSlidingMusicPanel(R.layout.activity_playlist_detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUpRecyclerView() {
|
private void setUpRecyclerView() {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,199 @@
|
||||||
|
package com.kabouzeid.gramophone.ui.fragments;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.view.GestureDetector;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
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.MusicProgressViewUpdateHelper;
|
||||||
|
import com.kabouzeid.gramophone.helper.PlayPauseButtonOnClickHandler;
|
||||||
|
import com.kabouzeid.gramophone.interfaces.MusicServiceEventListener;
|
||||||
|
import com.kabouzeid.gramophone.ui.activities.base.AbsMusicServiceActivity;
|
||||||
|
import com.kabouzeid.gramophone.util.ColorUtil;
|
||||||
|
import com.kabouzeid.gramophone.util.Util;
|
||||||
|
import com.kabouzeid.gramophone.views.PlayPauseDrawable;
|
||||||
|
|
||||||
|
import butterknife.Bind;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karim Abou Zeid (kabouzeid)
|
||||||
|
*/
|
||||||
|
public class MiniPlayerFragment extends Fragment implements MusicServiceEventListener, MusicProgressViewUpdateHelper.Callback {
|
||||||
|
@Bind(R.id.mini_player_title)
|
||||||
|
TextView miniPlayerTitle;
|
||||||
|
@Bind(R.id.mini_player_image)
|
||||||
|
ImageView miniPlayerImage;
|
||||||
|
@Bind(R.id.mini_player_play_pause_button)
|
||||||
|
ImageView miniPlayerPlayPauseButton;
|
||||||
|
@Bind(R.id.progress_bar)
|
||||||
|
MaterialProgressBar progressBar;
|
||||||
|
|
||||||
|
private PlayPauseDrawable miniPlayerPlayPauseDrawable;
|
||||||
|
|
||||||
|
private MusicProgressViewUpdateHelper progressViewUpdateHelper;
|
||||||
|
|
||||||
|
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 void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
progressViewUpdateHelper = new MusicProgressViewUpdateHelper(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
return inflater.inflate(R.layout.fragment_mini_player, container, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
ButterKnife.bind(this, view);
|
||||||
|
|
||||||
|
view.setOnTouchListener(new FlingPlayBackController(activity));
|
||||||
|
setUpMiniPlayer();
|
||||||
|
|
||||||
|
activity.addMusicServiceEventListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
activity.removeMusicServiceEventListener(this);
|
||||||
|
ButterKnife.unbind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpMiniPlayer() {
|
||||||
|
setMiniPlayerColor(ColorUtil.resolveColor(activity, R.attr.cardBackgroundColor));
|
||||||
|
miniPlayerImage.setImageDrawable(Util.getTintedDrawable(activity, R.drawable.ic_keyboard_arrow_up_white_24dp,
|
||||||
|
ColorUtil.resolveColor(activity, android.R.attr.textColorSecondary)));
|
||||||
|
setUpPlayPauseButton();
|
||||||
|
|
||||||
|
progressBar.setProgressTintList(ThemeSingleton.get().positiveColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMiniPlayerColor(int color) {
|
||||||
|
if (getView() == null) return;
|
||||||
|
getView().setBackgroundColor(color);
|
||||||
|
miniPlayerTitle.setTextColor(ColorUtil.getPrimaryTextColorForBackground(activity, color));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpPlayPauseButton() {
|
||||||
|
updatePlayPauseDrawableState(false);
|
||||||
|
miniPlayerPlayPauseButton.setImageDrawable(miniPlayerPlayPauseDrawable);
|
||||||
|
miniPlayerPlayPauseButton.setColorFilter(ColorUtil.resolveColor(activity, android.R.attr.textColorSecondary), PorterDuff.Mode.SRC_IN);
|
||||||
|
miniPlayerPlayPauseButton.setOnClickListener(new PlayPauseButtonOnClickHandler());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlayingMetaChanged() {
|
||||||
|
miniPlayerTitle.setText(MusicPlayerRemote.getCurrentSong().title);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlayStateChanged() {
|
||||||
|
updatePlayPauseDrawableState(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRepeatModeChanged() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onShuffleModeChanged() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMediaStoreChanged() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpdateProgressViews(int progress, int total) {
|
||||||
|
progressBar.setMax(total);
|
||||||
|
progressBar.setProgress(progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
progressViewUpdateHelper.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
progressViewUpdateHelper.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class FlingPlayBackController implements View.OnTouchListener {
|
||||||
|
|
||||||
|
GestureDetector flingPlayBackController;
|
||||||
|
|
||||||
|
public FlingPlayBackController(Context context) {
|
||||||
|
flingPlayBackController = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
|
||||||
|
if (Math.abs(velocityX) > Math.abs(velocityY)) {
|
||||||
|
if (velocityX < 0) {
|
||||||
|
MusicPlayerRemote.playNextSong();
|
||||||
|
return true;
|
||||||
|
} else if (velocityX > 0) {
|
||||||
|
MusicPlayerRemote.playPreviousSong();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouch(View v, MotionEvent event) {
|
||||||
|
return flingPlayBackController.onTouchEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updatePlayPauseDrawableState(boolean animate) {
|
||||||
|
if (miniPlayerPlayPauseDrawable == null) {
|
||||||
|
miniPlayerPlayPauseDrawable = new PlayPauseDrawable(activity);
|
||||||
|
}
|
||||||
|
if (MusicPlayerRemote.isPlaying()) {
|
||||||
|
miniPlayerPlayPauseDrawable.setPause(animate);
|
||||||
|
} else {
|
||||||
|
miniPlayerPlayPauseDrawable.setPlay(animate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,845 @@
|
||||||
|
package com.kabouzeid.gramophone.ui.fragments;
|
||||||
|
|
||||||
|
import android.animation.Animator;
|
||||||
|
import android.animation.AnimatorSet;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
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.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
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.v7.widget.CardView;
|
||||||
|
import android.support.v7.widget.Toolbar;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewAnimationUtils;
|
||||||
|
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.dialogs.AddToPlaylistDialog;
|
||||||
|
import com.kabouzeid.gramophone.dialogs.PlayingQueueDialog;
|
||||||
|
import com.kabouzeid.gramophone.dialogs.SleepTimerDialog;
|
||||||
|
import com.kabouzeid.gramophone.dialogs.SongDetailDialog;
|
||||||
|
import com.kabouzeid.gramophone.dialogs.SongShareDialog;
|
||||||
|
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
||||||
|
import com.kabouzeid.gramophone.helper.MusicProgressViewUpdateHelper;
|
||||||
|
import com.kabouzeid.gramophone.helper.PlayPauseButtonOnClickHandler;
|
||||||
|
import com.kabouzeid.gramophone.interfaces.MusicServiceEventListener;
|
||||||
|
import com.kabouzeid.gramophone.interfaces.PaletteColorHolder;
|
||||||
|
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.service.MusicService;
|
||||||
|
import com.kabouzeid.gramophone.ui.activities.base.AbsMusicServiceActivity;
|
||||||
|
import com.kabouzeid.gramophone.ui.activities.tageditor.AbsTagEditorActivity;
|
||||||
|
import com.kabouzeid.gramophone.ui.activities.tageditor.SongTagEditorActivity;
|
||||||
|
import com.kabouzeid.gramophone.util.ColorUtil;
|
||||||
|
import com.kabouzeid.gramophone.util.MusicUtil;
|
||||||
|
import com.kabouzeid.gramophone.util.NavigationUtil;
|
||||||
|
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 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;
|
||||||
|
|
||||||
|
public class PlayerFragment extends Fragment implements SharedPreferences.OnSharedPreferenceChangeListener, MusicServiceEventListener, Toolbar.OnMenuItemClickListener, PaletteColorHolder, MusicProgressViewUpdateHelper.Callback {
|
||||||
|
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)
|
||||||
|
View statusbar;
|
||||||
|
@Bind(R.id.player_toolbar)
|
||||||
|
Toolbar toolbar;
|
||||||
|
@Bind(R.id.player_favorite_icon)
|
||||||
|
ImageView favoriteIcon;
|
||||||
|
@Bind(R.id.player_album_art_frame)
|
||||||
|
FrameLayout albumArtFrame;
|
||||||
|
|
||||||
|
TextView songCurrentProgress;
|
||||||
|
TextView songTotalTime;
|
||||||
|
SeekBar progressSlider;
|
||||||
|
|
||||||
|
private int lastFooterColor;
|
||||||
|
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 PlayPauseDrawable playerFabPlayPauseDrawable;
|
||||||
|
|
||||||
|
private AnimatorSet colorTransitionAnimator;
|
||||||
|
|
||||||
|
private AbsMusicServiceActivity activity;
|
||||||
|
private Callbacks callbacks;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(Context context) {
|
||||||
|
super.onAttach(context);
|
||||||
|
try {
|
||||||
|
activity = (AbsMusicServiceActivity) context;
|
||||||
|
callbacks = (Callbacks) context;
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
throw new RuntimeException(context.getClass().getSimpleName() + " must be an instance of " + AbsMusicServiceActivity.class.getSimpleName() + " and implement " + Callbacks.class.getSimpleName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDetach() {
|
||||||
|
super.onDetach();
|
||||||
|
activity = null;
|
||||||
|
callbacks = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
initAppearanceVarsFromSharedPrefs();
|
||||||
|
PreferenceUtil.getInstance(getContext()).registerOnSharedPreferenceChangedListener(this);
|
||||||
|
progressViewUpdateHelper = new MusicProgressViewUpdateHelper(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
return inflater.inflate(R.layout.fragment_player, container, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
ButterKnife.bind(this, view);
|
||||||
|
|
||||||
|
resetShowControlsAnimation();
|
||||||
|
setUpPlayPauseFab();
|
||||||
|
adjustTitleBoxSize();
|
||||||
|
setUpPlaybackControllerCard();
|
||||||
|
setUpMusicControllers();
|
||||||
|
setUpAlbumArtViews();
|
||||||
|
setUpPlayerToolbar();
|
||||||
|
setUpPlayerStatusBarElevation();
|
||||||
|
|
||||||
|
activity.addMusicServiceEventListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
activity.removeMusicServiceEventListener(this);
|
||||||
|
ButterKnife.unbind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
activity.removeMusicServiceEventListener(this);
|
||||||
|
PreferenceUtil.getInstance(activity).unregisterOnSharedPreferenceChangedListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
progressViewUpdateHelper.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
progressViewUpdateHelper.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlayingMetaChanged() {
|
||||||
|
updateCurrentSong();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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.OPAQUE_STATUSBAR_NOW_PLAYING:
|
||||||
|
opaqueStatusBar = PreferenceUtil.getInstance(activity).opaqueStatusbarNowPlaying();
|
||||||
|
// do not break here
|
||||||
|
case PreferenceUtil.OPAQUE_TOOLBAR_NOW_PLAYING:
|
||||||
|
opaqueToolBar = opaqueStatusBar && PreferenceUtil.getInstance(activity).opaqueToolbarNowPlaying();
|
||||||
|
setUpPlayerStatusBarElevation();
|
||||||
|
animateColorChange(lastFooterColor);
|
||||||
|
if (opaqueStatusBar) {
|
||||||
|
if (opaqueToolBar) {
|
||||||
|
alignAlbumArtToToolbar();
|
||||||
|
} else {
|
||||||
|
alignAlbumArtToStatusBar();
|
||||||
|
}
|
||||||
|
} 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() {
|
||||||
|
updatePlayPauseDrawableState(false);
|
||||||
|
playPauseFab.setImageDrawable(playerFabPlayPauseDrawable);
|
||||||
|
setUpPlayerPlayPauseFabTint();
|
||||||
|
playPauseFab.setOnClickListener(new PlayPauseButtonOnClickHandler());
|
||||||
|
playPauseFab.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
playPauseFab.setPivotX(playPauseFab.getWidth() / 2);
|
||||||
|
playPauseFab.setPivotY(playPauseFab.getHeight() / 2);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpPlayerPlayPauseFabTint() {
|
||||||
|
int fabColor = colorPlaybackControls ? 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlayStateChanged() {
|
||||||
|
updatePlayPauseDrawableState(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initAppearanceVarsFromSharedPrefs() {
|
||||||
|
opaqueStatusBar = PreferenceUtil.getInstance(activity).opaqueStatusbarNowPlaying();
|
||||||
|
opaqueToolBar = opaqueStatusBar && PreferenceUtil.getInstance(activity).opaqueToolbarNowPlaying();
|
||||||
|
forceSquareAlbumArt = PreferenceUtil.getInstance(activity).forceAlbumArtSquared();
|
||||||
|
largerTitleBox = PreferenceUtil.getInstance(activity).largerTitleBoxNowPlaying();
|
||||||
|
alternativeProgressSlider = PreferenceUtil.getInstance(activity).alternativeProgressSliderNowPlaying();
|
||||||
|
showPlaybackControllerCard = PreferenceUtil.getInstance(activity).playbackControllerCardNowPlaying();
|
||||||
|
colorPlaybackControls = PreferenceUtil.getInstance(activity).colorPlaybackControlsNowPlaying();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initProgressSliderDependentViews() {
|
||||||
|
if (getView() == null) return;
|
||||||
|
if (alternativeProgressSlider) {
|
||||||
|
getView().findViewById(R.id.player_default_progress_container).setVisibility(View.GONE);
|
||||||
|
getView().findViewById(R.id.player_default_progress_slider).setVisibility(View.GONE);
|
||||||
|
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);
|
||||||
|
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 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() {
|
||||||
|
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) {
|
||||||
|
activity.onBackPressed();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
toolbar.setOnMenuItemClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpPlayerStatusBarElevation() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
if (opaqueToolBar) {
|
||||||
|
statusbar.setElevation(getResources().getDimensionPixelSize(R.dimen.toolbar_elevation));
|
||||||
|
} else {
|
||||||
|
statusbar.setElevation(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePlayerMenu() {
|
||||||
|
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)));
|
||||||
|
toolbar.getMenu().findItem(R.id.action_toggle_favorite)
|
||||||
|
.setIcon(favoriteIcon)
|
||||||
|
.setTitle(isFavorite ? getString(R.string.action_remove_from_favorites) : getString(R.string.action_add_to_favorites));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateCurrentSong() {
|
||||||
|
getCurrentSong();
|
||||||
|
updateMetaTexts();
|
||||||
|
setUpAlbumArtAndApplyPalette();
|
||||||
|
updatePlayerMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getCurrentSong() {
|
||||||
|
song = MusicPlayerRemote.getCurrentSong();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateMetaTexts() {
|
||||||
|
songTitle.setText(song.title);
|
||||||
|
songText.setText(song.artistName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@ColorInt
|
||||||
|
public int getPaletteColor() {
|
||||||
|
return lastFooterColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpdateProgressViews(int progress, int total) {
|
||||||
|
progressSlider.setMax(total);
|
||||||
|
progressSlider.setProgress(progress);
|
||||||
|
songTotalTime.setText(MusicUtil.getReadableDurationString(total));
|
||||||
|
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) {
|
||||||
|
if (colorTransitionAnimator != null && colorTransitionAnimator.isStarted()) {
|
||||||
|
colorTransitionAnimator.cancel();
|
||||||
|
}
|
||||||
|
colorTransitionAnimator = new AnimatorSet();
|
||||||
|
AnimatorSet.Builder animatorSetBuilder = colorTransitionAnimator.play(ViewUtil.createBackgroundColorTransition(footer, lastFooterColor, newColor));
|
||||||
|
|
||||||
|
if (opaqueToolBar) {
|
||||||
|
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
|
||||||
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case R.id.action_sleep_timer:
|
||||||
|
new SleepTimerDialog().show(getFragmentManager(), "SET_SLEEP_TIMER");
|
||||||
|
return true;
|
||||||
|
case R.id.action_toggle_favorite:
|
||||||
|
MusicUtil.toggleFavorite(activity, song);
|
||||||
|
if (MusicUtil.isFavorite(activity, song)) {
|
||||||
|
animateSetFavorite();
|
||||||
|
}
|
||||||
|
updatePlayerMenu();
|
||||||
|
return true;
|
||||||
|
case R.id.action_share:
|
||||||
|
SongShareDialog.create(song).show(getFragmentManager(), "SHARE_SONG");
|
||||||
|
return true;
|
||||||
|
case R.id.action_equalizer:
|
||||||
|
NavigationUtil.openEqualizer(activity);
|
||||||
|
return true;
|
||||||
|
case R.id.action_shuffle_all:
|
||||||
|
MusicPlayerRemote.openAndShuffleQueue(SongLoader.getAllSongs(activity), true);
|
||||||
|
return true;
|
||||||
|
case R.id.action_add_to_playlist:
|
||||||
|
AddToPlaylistDialog.create(song).show(getFragmentManager(), "ADD_PLAYLIST");
|
||||||
|
return true;
|
||||||
|
case R.id.action_playing_queue:
|
||||||
|
PlayingQueueDialog.create().show(getFragmentManager(), "PLAY_QUEUE");
|
||||||
|
return true;
|
||||||
|
case R.id.action_tag_editor:
|
||||||
|
Intent intent = new Intent(activity, SongTagEditorActivity.class);
|
||||||
|
intent.putExtra(AbsTagEditorActivity.EXTRA_ID, song.id);
|
||||||
|
startActivity(intent);
|
||||||
|
return true;
|
||||||
|
case R.id.action_details:
|
||||||
|
SongDetailDialog.create(song).show(getFragmentManager(), "SONG_DETAIL");
|
||||||
|
return true;
|
||||||
|
case R.id.action_go_to_album:
|
||||||
|
NavigationUtil.goToAlbum(activity, song.albumId);
|
||||||
|
return true;
|
||||||
|
case R.id.action_go_to_artist:
|
||||||
|
NavigationUtil.goToArtist(activity, song.artistId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
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() {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Callbacks {
|
||||||
|
void onPaletteColorChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,11 +8,9 @@ import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.ActivityOptionsCompat;
|
import android.support.v4.app.ActivityOptionsCompat;
|
||||||
import android.support.v4.util.Pair;
|
import android.support.v4.util.Pair;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
import com.kabouzeid.gramophone.dialogs.PlayingQueueDialog;
|
|
||||||
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
||||||
import com.kabouzeid.gramophone.interfaces.KabViewsDisableAble;
|
import com.kabouzeid.gramophone.interfaces.KabViewsDisableAble;
|
||||||
import com.kabouzeid.gramophone.model.Playlist;
|
import com.kabouzeid.gramophone.model.Playlist;
|
||||||
|
|
@ -67,10 +65,6 @@ public class NavigationUtil {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void openPlayingQueueDialog(@NonNull final AppCompatActivity activity) {
|
|
||||||
PlayingQueueDialog.create().show(activity.getSupportFragmentManager(), "PLAY_QUEUE");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void openEqualizer(@NonNull final Activity activity) {
|
public static void openEqualizer(@NonNull final Activity activity) {
|
||||||
final int sessionId = MusicPlayerRemote.getAudioSessionId();
|
final int sessionId = MusicPlayerRemote.getAudioSessionId();
|
||||||
if (sessionId == AudioEffect.ERROR_BAD_VALUE) {
|
if (sessionId == AudioEffect.ERROR_BAD_VALUE) {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ import android.view.View;
|
||||||
import android.view.ViewPropertyAnimator;
|
import android.view.ViewPropertyAnimator;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
import com.afollestad.materialdialogs.internal.ThemeSingleton;
|
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
import com.kabouzeid.gramophone.util.ColorUtil;
|
import com.kabouzeid.gramophone.util.ColorUtil;
|
||||||
import com.kabouzeid.gramophone.util.Util;
|
import com.kabouzeid.gramophone.util.Util;
|
||||||
|
|
@ -58,7 +57,7 @@ public class FastScroller extends FrameLayout {
|
||||||
handle = findViewById(R.id.scroll_handle);
|
handle = findViewById(R.id.scroll_handle);
|
||||||
bar = findViewById(R.id.scroll_bar);
|
bar = findViewById(R.id.scroll_bar);
|
||||||
handle.setEnabled(true);
|
handle.setEnabled(true);
|
||||||
setPressedHandleColor(ThemeSingleton.get().positiveColor.getDefaultColor());
|
setPressedHandleColor(ColorUtil.resolveColor(getContext(), R.attr.colorControlActivated));
|
||||||
setUpBarBackground();
|
setUpBarBackground();
|
||||||
postDelayed(handleHider, HANDLE_HIDE_DELAY);
|
postDelayed(handleHider, HANDLE_HIDE_DELAY);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
60
app/src/main/res/layout/fragment_mini_player.xml
Normal file
60
app/src/main/res/layout/fragment_mini_player.xml
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/mini_player_height"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="false">
|
||||||
|
|
||||||
|
<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="match_parent"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/mini_player_image"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/mini_player_title"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:fontFamily="sans-serif-condensed"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/mini_player_play_pause_button"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:scaleType="center"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
|
||||||
|
android:id="@+id/progress_bar"
|
||||||
|
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="3dp"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
app:mpb_progressStyle="horizontal"
|
||||||
|
app:mpb_useIntrinsicPadding="false" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout android:id="@+id/mini_player"
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="@dimen/mini_player_height"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="false"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/mini_player_image"
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:layout_margin="16dp"
|
|
||||||
android:scaleType="centerCrop"
|
|
||||||
tools:ignore="ContentDescription" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/mini_player_title"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/mini_player_play_pause_button"
|
|
||||||
android:layout_width="40dp"
|
|
||||||
android:layout_height="40dp"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:scaleType="center"
|
|
||||||
tools:ignore="ContentDescription" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
<com.sothree.slidinguppanel.SlidingUpPanelLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<com.sothree.slidinguppanel.SlidingUpPanelLayout
|
||||||
xmlns:sothree="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:id="@+id/sliding_layout"
|
android:id="@+id/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_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="bottom"
|
android:gravity="bottom"
|
||||||
sothree:umanoDragView="@+id/player_container"
|
sothree:umanoDragView="@+id/sliding_panel"
|
||||||
sothree:umanoPanelHeight="@dimen/mini_player_height"
|
sothree:umanoPanelHeight="@dimen/mini_player_height"
|
||||||
sothree:umanoShadowHeight="@dimen/card_elevation">
|
sothree:umanoShadowHeight="@dimen/card_elevation">
|
||||||
|
|
||||||
|
|
@ -14,16 +15,24 @@
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/player_container"
|
android:id="@+id/sliding_panel"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="?android:colorBackground"
|
android:background="?android:colorBackground"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="false">
|
android:focusable="false">
|
||||||
|
|
||||||
<include layout="@layout/player" />
|
<fragment
|
||||||
|
android:id="@+id/player_fragment"
|
||||||
|
class="com.kabouzeid.gramophone.ui.fragments.PlayerFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
<include layout="@layout/mini_player" />
|
<fragment
|
||||||
|
android:id="@+id/mini_player_fragment"
|
||||||
|
class="com.kabouzeid.gramophone.ui.fragments.MiniPlayerFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/mini_player_height" />
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,6 @@ http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout
|
||||||
<!-- For use with 24dp drawables in the item_list layouts-->
|
<!-- For use with 24dp drawables in the item_list layouts-->
|
||||||
<dimen name="list_item_image_icon_padding">8dp</dimen>
|
<dimen name="list_item_image_icon_padding">8dp</dimen>
|
||||||
|
|
||||||
<dimen name="mini_player_height">48dp</dimen>
|
<dimen name="mini_player_height">56dp</dimen>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -205,4 +205,7 @@
|
||||||
<string name="aleksandar_tesic_summary">For helping me with the design.</string>
|
<string name="aleksandar_tesic_summary">For helping me with the design.</string>
|
||||||
<string name="website">Website</string>
|
<string name="website">Website</string>
|
||||||
<string name="loading_products">Loading products…</string>
|
<string name="loading_products">Loading products…</string>
|
||||||
|
|
||||||
|
<!-- TODO: Remove or change this placeholder text -->
|
||||||
|
<string name="hello_blank_fragment">Hello blank fragment</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue