diff --git a/app/src/main/java/com/kabouzeid/gramophone/helper/MusicProgressViewUpdateHelper.java b/app/src/main/java/com/kabouzeid/gramophone/helper/MusicProgressViewUpdateHelper.java new file mode 100644 index 00000000..a1c8e2ae --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/helper/MusicProgressViewUpdateHelper.java @@ -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); + } +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/helper/PlayPauseButtonOnClickHandler.java b/app/src/main/java/com/kabouzeid/gramophone/helper/PlayPauseButtonOnClickHandler.java new file mode 100644 index 00000000..bc2b7fd4 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/helper/PlayPauseButtonOnClickHandler.java @@ -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(); + } + } +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/interfaces/PaletteColorHolder.java b/app/src/main/java/com/kabouzeid/gramophone/interfaces/PaletteColorHolder.java index 9decb410..b6df7c74 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/interfaces/PaletteColorHolder.java +++ b/app/src/main/java/com/kabouzeid/gramophone/interfaces/PaletteColorHolder.java @@ -1,9 +1,12 @@ package com.kabouzeid.gramophone.interfaces; +import android.support.annotation.ColorInt; + /** * @author Aidan Follestad (afollestad) */ public interface PaletteColorHolder { + @ColorInt int getPaletteColor(); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java index 43463206..69f8d3d5 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java @@ -100,7 +100,7 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements @Override protected View createContentView() { - return wrapSlidingMusicPanelAndFab(R.layout.activity_album_detail); + return wrapSlidingMusicPanel(R.layout.activity_album_detail); } private final SimpleObservableScrollViewCallbacks observableScrollViewCallbacks = new SimpleObservableScrollViewCallbacks() { diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java index eab944ce..0d82793b 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java @@ -116,7 +116,7 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement @Override protected View createContentView() { - return wrapSlidingMusicPanelAndFab(R.layout.activity_artist_detail); + return wrapSlidingMusicPanel(R.layout.activity_artist_detail); } private final SimpleObservableScrollViewCallbacks observableScrollViewCallbacks = new SimpleObservableScrollViewCallbacks() { diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java index ed7325d6..0bf6a00f 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java @@ -62,7 +62,6 @@ import com.kabouzeid.gramophone.util.Util; import com.kabouzeid.gramophone.util.ViewUtil; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; -import com.sothree.slidinguppanel.SlidingUpPanelLayout; import java.io.File; import java.util.ArrayList; @@ -121,7 +120,7 @@ public class MainActivity extends AbsSlidingMusicPanelActivity @SuppressLint("InflateParams") View contentView = getLayoutInflater().inflate(R.layout.activity_main_drawer_layout, null); 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; } @@ -261,8 +260,8 @@ public class MainActivity extends AbsSlidingMusicPanelActivity @Override public void onClick(View v) { drawerLayout.closeDrawers(); - if (getSlidingUpPanelLayout().getPanelState() != SlidingUpPanelLayout.PanelState.EXPANDED) { - getSlidingUpPanelLayout().setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED); + if (isPanelCollapsed()) { + toggleSlidingPanel(); } } }); @@ -564,46 +563,10 @@ public class MainActivity extends AbsSlidingMusicPanelActivity 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() { 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 public MaterialCab openCab(final int menu, final MaterialCab.Callback callback) { if (cab != null && cab.isActive()) cab.finish(); diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/PlaylistDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/PlaylistDetailActivity.java index 808a543e..51bb3938 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/PlaylistDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/PlaylistDetailActivity.java @@ -75,7 +75,7 @@ public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity impleme @Override protected View createContentView() { - return wrapSlidingMusicPanelAndFab(R.layout.activity_playlist_detail); + return wrapSlidingMusicPanel(R.layout.activity_playlist_detail); } private void setUpRecyclerView() { diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java index c3965fc9..7e35c538 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java @@ -1,82 +1,21 @@ package com.kabouzeid.gramophone.ui.activities.base; -import android.animation.Animator; -import android.animation.AnimatorSet; import android.annotation.SuppressLint; import android.content.ComponentName; -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.os.Handler; import android.os.IBinder; -import android.os.Message; import android.support.annotation.ColorInt; import android.support.annotation.FloatRange; import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.FloatingActionButton; -import android.support.v7.widget.CardView; -import android.support.v7.widget.Toolbar; -import android.util.TypedValue; -import android.view.GestureDetector; -import android.view.MenuItem; -import android.view.MotionEvent; 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.SleepTimerDialog; -import com.kabouzeid.gramophone.dialogs.SongDetailDialog; -import com.kabouzeid.gramophone.dialogs.SongShareDialog; import com.kabouzeid.gramophone.helper.MusicPlayerRemote; -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.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 com.kabouzeid.gramophone.ui.fragments.MiniPlayerFragment; +import com.kabouzeid.gramophone.ui.fragments.PlayerFragment; import com.sothree.slidinguppanel.SlidingUpPanelLayout; -import java.lang.ref.WeakReference; - import butterknife.Bind; import butterknife.ButterKnife; @@ -84,89 +23,19 @@ import butterknife.ButterKnife; * @author Karim Abou Zeid (kabouzeid) *

* Do not use {@link #setContentView(int)} but wrap your layout with - * {@link #wrapSlidingMusicPanelAndFab(int)} first and then return it in {@link #createContentView()} + * {@link #wrapSlidingMusicPanel(int)} first and then return it in {@link #createContentView()} */ -public abstract class AbsSlidingMusicPanelActivity extends AbsMusicServiceActivity implements SlidingUpPanelLayout.PanelSlideListener, SharedPreferences.OnSharedPreferenceChangeListener, Toolbar.OnMenuItemClickListener { +public abstract class AbsSlidingMusicPanelActivity extends AbsMusicServiceActivity implements SlidingUpPanelLayout.PanelSlideListener, PlayerFragment.Callbacks { public static final String TAG = AbsSlidingMusicPanelActivity.class.getSimpleName(); - private static final int CMD_REFRESH_PROGRESS_VIEWS = 1; - - private static final int FAB_CIRCULAR_REVEAL_ANIMATION_TIME = 1000; - @Bind(R.id.sliding_layout) SlidingUpPanelLayout slidingUpPanelLayout; - @Bind(R.id.mini_player) - LinearLayout miniPlayer; - @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.player_play_pause_fab) - FloatingActionButton playerPlayPauseFab; - - @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 playerStatusbar; - @Bind(R.id.player_toolbar) - Toolbar playerToolbar; - @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 int navigationBarColor; private int taskColor; - private Handler progressViewsUpdateHandler; - - 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 miniPlayerPlayPauseDrawable; - private PlayPauseDrawable playerFabPlayPauseDrawable; - - private AnimatorSet colorTransitionAnimator; + private PlayerFragment playerFragment; + private MiniPlayerFragment miniPlayerFragment; @Override protected void onCreate(Bundle savedInstanceState) { @@ -174,27 +43,24 @@ public abstract class AbsSlidingMusicPanelActivity extends AbsMusicServiceActivi setContentView(createContentView()); ButterKnife.bind(this); - initAppearanceVarsFromSharedPrefs(); - PreferenceUtil.getInstance(this).registerOnSharedPreferenceChangedListener(this); + playerFragment = (PlayerFragment) getSupportFragmentManager().findFragmentById(R.id.player_fragment); + miniPlayerFragment = (MiniPlayerFragment) getSupportFragmentManager().findFragmentById(R.id.mini_player_fragment); + + if (miniPlayerFragment.getView() != null) { + miniPlayerFragment.getView().setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + toggleSlidingPanel(); + } + }); + } - setUpPlayPauseButtons(); - setUpMiniPlayer(); setUpSlidingPanel(); - adjustTitleBoxSize(); - setUpPlaybackControllerCard(); - setUpMusicControllers(); - setUpAlbumArtViews(); - setUpPlayerToolbar(); - setUpPlayerStatusBarElevation(); - - progressViewsUpdateHandler = new MusicProgressViewsUpdateHandler(this); - slidingUpPanelLayout.post(new Runnable() { @Override public void run() { - if (slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { - mediaControllerContainer.setVisibility(View.VISIBLE); + if (!isPanelCollapsed()) { onPanelSlide(slidingUpPanelLayout, 1); onPanelExpanded(slidingUpPanelLayout); } @@ -204,186 +70,13 @@ public abstract class AbsSlidingMusicPanelActivity extends AbsMusicServiceActivi protected abstract View createContentView(); - @Override - protected void onDestroy() { - super.onDestroy(); - PreferenceUtil.getInstance(this).unregisterOnSharedPreferenceChangedListener(this); - } - - @Override - protected void onResume() { - super.onResume(); - startUpdatingProgressViews(); - } - - @Override - protected void onPause() { - super.onPause(); - stopUpdatingProgressViews(); - } - - @Override - public void onPlayingMetaChanged() { - super.onPlayingMetaChanged(); - updateCurrentSong(); - } - @Override public void onServiceConnected(ComponentName name, IBinder service) { hideBottomBar(MusicPlayerRemote.getPlayingQueue().isEmpty()); super.onServiceConnected(name, service); } - @Override - public void onRepeatModeChanged() { - super.onRepeatModeChanged(); - updateRepeatState(); - } - - @Override - public void onShuffleModeChanged() { - super.onShuffleModeChanged(); - updateShuffleState(); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - switch (key) { - case PreferenceUtil.OPAQUE_STATUSBAR_NOW_PLAYING: - opaqueStatusBar = PreferenceUtil.getInstance(this).opaqueStatusbarNowPlaying(); - // do not break here - case PreferenceUtil.OPAQUE_TOOLBAR_NOW_PLAYING: - opaqueToolBar = opaqueStatusBar && PreferenceUtil.getInstance(this).opaqueToolbarNowPlaying(); - setUpPlayerStatusBarElevation(); - animateColorChange(lastFooterColor); - if (opaqueStatusBar) { - if (opaqueToolBar) { - alignAlbumArtToToolbar(); - } else { - alignAlbumArtToStatusBar(); - } - } else { - alignAlbumArtToTop(); - } - break; - case PreferenceUtil.FORCE_SQUARE_ALBUM_ART: - forceSquareAlbumArt = PreferenceUtil.getInstance(this).forceAlbumArtSquared(); - albumArt.forceSquare(forceSquareAlbumArt); - break; - case PreferenceUtil.LARGER_TITLE_BOX_NOW_PLAYING: - largerTitleBox = PreferenceUtil.getInstance(this).largerTitleBoxNowPlaying(); - adjustTitleBoxSize(); - break; - case PreferenceUtil.ALTERNATIVE_PROGRESS_SLIDER_NOW_PLAYING: - alternativeProgressSlider = PreferenceUtil.getInstance(this).alternativeProgressSliderNowPlaying(); - setUpProgressSlider(); - break; - case PreferenceUtil.PLAYBACK_CONTROLLER_CARD_NOW_PLAYING: - showPlaybackControllerCard = PreferenceUtil.getInstance(this).playbackControllerCardNowPlaying(); - setUpPlaybackControllerCard(); - break; - case PreferenceUtil.COLOR_PLAYBACK_CONTROLS_NOW_PLAYING: - colorPlaybackControls = PreferenceUtil.getInstance(this).colorPlaybackControlsNowPlaying(); - updateRepeatState(); - updateShuffleState(); - setUpProgressSliderTint(); - setUpPlayerPlayPauseFabTint(); - break; - } - } - - private View.OnClickListener playPauseButtonOnClickListener = new View.OnClickListener() { - @Override - public void onClick(View v) { - if (MusicPlayerRemote.isPlaying()) { - MusicPlayerRemote.pauseSong(); - } else { - MusicPlayerRemote.resumePlaying(); - } - } - }; - - private void setUpPlayPauseButtons() { - updatePlayPauseDrawablesStates(false); - - miniPlayerPlayPauseButton.setImageDrawable(miniPlayerPlayPauseDrawable); - playerPlayPauseFab.setImageDrawable(playerFabPlayPauseDrawable); - - setUpPlayerPlayPauseFabTint(); - miniPlayerPlayPauseButton.setColorFilter(ColorUtil.resolveColor(this, android.R.attr.textColorSecondary), PorterDuff.Mode.SRC_IN); - - miniPlayerPlayPauseButton.setOnClickListener(playPauseButtonOnClickListener); - playerPlayPauseFab.setOnClickListener(playPauseButtonOnClickListener); - } - - private void setUpPlayerPlayPauseFabTint() { - int fabColor = colorPlaybackControls ? lastPlaybackControlsColor : getThemeColorAccent(); - FloatingActionButtonProperties.COLOR.set(playerPlayPauseFab, fabColor); - } - - 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); - } - } - - private void setUpMiniPlayer() { - miniPlayer.setOnTouchListener(new FlingPlayBackController(this)); - - miniPlayer.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - toggleSlidingPanel(); - } - }); - - setMiniPlayerColor(ColorUtil.resolveColor(this, R.attr.cardBackgroundColor)); - - miniPlayerImage.setImageDrawable(Util.getTintedDrawable(this, R.drawable.ic_keyboard_arrow_up_white_24dp, - ColorUtil.resolveColor(this, android.R.attr.textColorSecondary))); - } - - public void setMiniPlayerColor(int color) { - miniPlayer.setBackgroundColor(color); - miniPlayerTitle.setTextColor(ColorUtil.getPrimaryTextColorForBackground(this, color)); - } - private void setUpSlidingPanel() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - mediaControllerContainer.setVisibility(View.INVISIBLE); - } - playerPlayPauseFab.post(new Runnable() { - @Override - public void run() { - playerPlayPauseFab.setPivotX(playerPlayPauseFab.getWidth() / 2); - playerPlayPauseFab.setPivotY(playerPlayPauseFab.getHeight() / 2); - } - }); - playerPlayPauseFab.setScaleX(0f); - playerPlayPauseFab.setScaleY(0f); - playerPlayPauseFab.setRotation(0f); slidingUpPanelLayout.setPanelSlideListener(this); } @@ -398,41 +91,17 @@ public abstract class AbsSlidingMusicPanelActivity extends AbsMusicServiceActivi if (shouldColorNavigationBar()) { super.setNavigationBarColor(navigationBarColor); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - mediaControllerContainer.setVisibility(View.INVISIBLE); - } - playerPlayPauseFab.setScaleX(0f); - playerPlayPauseFab.setScaleY(0f); - playerPlayPauseFab.setRotation(0f); + playerFragment.resetShowControlsAnimation(); } @Override public void onPanelExpanded(View view) { - super.notifyTaskColorChange(lastFooterColor); + int playerFragmentColor = playerFragment.getPaletteColor(); + super.notifyTaskColorChange(playerFragmentColor); if (shouldColorNavigationBar()) { - super.setNavigationBarColor(lastFooterColor); - } - - playerPlayPauseFab.animate() - .scaleX(1) - .scaleY(1) - .rotation(360f) - .setInterpolator(new DecelerateInterpolator()) - .start(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - if (mediaControllerContainer.getVisibility() == View.INVISIBLE) { - int cx = (playerPlayPauseFab.getLeft() + playerPlayPauseFab.getRight()) / 2; - int cy = (playerPlayPauseFab.getTop() + playerPlayPauseFab.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); - } + super.setNavigationBarColor(playerFragmentColor); } + playerFragment.showControls(); } @Override @@ -446,22 +115,23 @@ public abstract class AbsSlidingMusicPanelActivity extends AbsMusicServiceActivi } private void setMiniPlayerAlphaProgress(@FloatRange(from = 0, to = 1) float progress) { + if (miniPlayerFragment.getView() == null) return; float alpha = 1 - progress; - miniPlayer.setAlpha(alpha); + miniPlayerFragment.getView().setAlpha(alpha); // necessary to make the views below clickable - miniPlayer.setVisibility(alpha == 0 ? View.GONE : View.VISIBLE); + miniPlayerFragment.getView().setVisibility(alpha == 0 ? View.GONE : View.VISIBLE); } - private void toggleSlidingPanel() { - if (slidingUpPanelLayout.getPanelState() != SlidingUpPanelLayout.PanelState.EXPANDED) { + public void toggleSlidingPanel() { + if (isPanelCollapsed()) { slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED); } else { slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); } } - public SlidingUpPanelLayout getSlidingUpPanelLayout() { - return slidingUpPanelLayout; + public boolean isPanelCollapsed() { + return slidingUpPanelLayout == null || slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED; } public void hideBottomBar(boolean hide) { @@ -482,29 +152,7 @@ public abstract class AbsSlidingMusicPanelActivity extends AbsMusicServiceActivi } } - protected void updatePlayPauseDrawablesStates(boolean animate) { - if (miniPlayerPlayPauseDrawable == null) { - miniPlayerPlayPauseDrawable = new PlayPauseDrawable(this); - } - if (playerFabPlayPauseDrawable == null) { - playerFabPlayPauseDrawable = new PlayPauseDrawable(this); - } - if (MusicPlayerRemote.isPlaying()) { - miniPlayerPlayPauseDrawable.setPause(animate); - playerFabPlayPauseDrawable.setPause(animate); - } else { - miniPlayerPlayPauseDrawable.setPlay(animate); - playerFabPlayPauseDrawable.setPlay(animate); - } - } - - @Override - public void onPlayStateChanged() { - super.onPlayStateChanged(); - updatePlayPauseDrawablesStates(true); - } - - protected View wrapSlidingMusicPanelAndFab(@LayoutRes int resId) { + protected View wrapSlidingMusicPanel(@LayoutRes int resId) { @SuppressLint("InflateParams") View slidingMusicPanelLayout = getLayoutInflater().inflate(R.layout.sliding_music_panel_layout, null); ViewGroup contentContainer = ButterKnife.findById(slidingMusicPanelLayout, R.id.content_container); @@ -514,569 +162,17 @@ public abstract class AbsSlidingMusicPanelActivity extends AbsMusicServiceActivi @Override public void onBackPressed() { - if (slidingUpPanelLayout.getPanelState() != SlidingUpPanelLayout.PanelState.COLLAPSED) { + if (!isPanelCollapsed()) { slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); return; } super.onBackPressed(); } - private void initAppearanceVarsFromSharedPrefs() { - opaqueStatusBar = PreferenceUtil.getInstance(this).opaqueStatusbarNowPlaying(); - opaqueToolBar = opaqueStatusBar && PreferenceUtil.getInstance(this).opaqueToolbarNowPlaying(); - forceSquareAlbumArt = PreferenceUtil.getInstance(this).forceAlbumArtSquared(); - largerTitleBox = PreferenceUtil.getInstance(this).largerTitleBoxNowPlaying(); - alternativeProgressSlider = PreferenceUtil.getInstance(this).alternativeProgressSliderNowPlaying(); - showPlaybackControllerCard = PreferenceUtil.getInstance(this).playbackControllerCardNowPlaying(); - colorPlaybackControls = PreferenceUtil.getInstance(this).colorPlaybackControlsNowPlaying(); - } - - private void initProgressSliderDependentViews() { - if (alternativeProgressSlider) { - findViewById(R.id.player_default_progress_container).setVisibility(View.GONE); - findViewById(R.id.player_default_progress_slider).setVisibility(View.GONE); - findViewById(R.id.player_alternative_progress_container).setVisibility(View.VISIBLE); - - songCurrentProgress = (TextView) findViewById(R.id.player_alternative_song_current_progress); - songTotalTime = (TextView) findViewById(R.id.player_alternative_song_total_time); - progressSlider = (SeekBar) findViewById(R.id.player_alternative_progress_slider); - } else { - findViewById(R.id.player_default_progress_container).setVisibility(View.VISIBLE); - findViewById(R.id.player_default_progress_slider).setVisibility(View.VISIBLE); - findViewById(R.id.player_alternative_progress_container).setVisibility(View.GONE); - - songCurrentProgress = (TextView) findViewById(R.id.player_default_song_current_progress); - songTotalTime = (TextView) findViewById(R.id.player_default_song_total_time); - progressSlider = (SeekBar) 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 = shiftColorDown(lastPlaybackControlsColor); - } else { - thumbColor = shiftColorUp(lastPlaybackControlsColor); - } - } else { - thumbColor = getThemeColorAccent(); - } - progressColor = thumbColor; - } - setSeekBarTint(progressSlider, thumbColor, progressColor); - } - - @ColorInt - private static int shiftColorUp(@ColorInt int color) { - return ColorUtil.shiftColor(color, 1.2f); - } - - @ColorInt - private static int shiftColorDown(@ColorInt int color) { - return ColorUtil.shiftColor(color, 0.8f); - } - - 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); - refreshProgressViews(); - } - } - }); - } - - private void setUpPrevNext() { - int themedDrawableColor = ColorUtil.resolveColor(this, android.R.attr.textColorSecondary); - nextButton.setImageDrawable(Util.getTintedDrawable(this, - R.drawable.ic_skip_next_white_36dp, themedDrawableColor)); - prevButton.setImageDrawable(Util.getTintedDrawable(this, - 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(this, R.drawable.ic_shuffle_white_36dp, - getActivatedIconColor())); - break; - default: - shuffleButton.setImageDrawable(Util.getTintedDrawable(this, 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(this, R.drawable.ic_repeat_white_36dp, - getActivatedIconColor())); - break; - case MusicService.REPEAT_MODE_THIS: - repeatButton.setImageDrawable(Util.getTintedDrawable(this, R.drawable.ic_repeat_one_white_36dp, - getActivatedIconColor())); - break; - default: - repeatButton.setImageDrawable(Util.getTintedDrawable(this, 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(this, 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() { - playerToolbar.inflateMenu(R.menu.menu_player); - playerToolbar.setNavigationIcon(R.drawable.ic_close_white_24dp); - playerToolbar.setNavigationOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); - } - }); - playerToolbar.setOnMenuItemClickListener(this); - } - - private void setUpPlayerStatusBarElevation() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - if (opaqueToolBar) { - playerStatusbar.setElevation(getResources().getDimensionPixelSize(R.dimen.toolbar_elevation)); - } else { - playerStatusbar.setElevation(0); - } - } - } - - private void updatePlayerMenu() { - boolean isFavorite = MusicUtil.isFavorite(this, song); - Drawable favoriteIcon = Util.getTintedDrawable(this, isFavorite ? R.drawable.ic_favorite_white_24dp : R.drawable.ic_favorite_outline_white_24dp, ViewUtil.getToolbarIconColor(this, opaqueToolBar && ColorUtil.useDarkTextColorOnBackground(lastFooterColor))); - playerToolbar.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() { - hideBottomBar(MusicPlayerRemote.getPlayingQueue().isEmpty()); - getCurrentSong(); - updateMiniPlayerAndHeaderText(); - setUpAlbumArtAndApplyPalette(); - updatePlayerMenu(); - } - - private void getCurrentSong() { - song = MusicPlayerRemote.getCurrentSong(); - } - - private void updateMiniPlayerAndHeaderText() { - songTitle.setText(song.title); - songText.setText(song.artistName); - - miniPlayerTitle.setText(song.title); - } - - 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(AbsSlidingMusicPanelActivity.this, 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(AbsSlidingMusicPanelActivity.this, 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); - - if (slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { - super.notifyTaskColorChange(color); - if (shouldColorNavigationBar()) { - super.setNavigationBarColor(color); - } - } - } - - 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(playerToolbar, lastFooterColor, newColor)); - ViewUtil.setToolbarContentColorForBackground(this, playerToolbar, newColor); - } else { - playerToolbar.setBackgroundColor(Color.TRANSPARENT); - ViewUtil.setToolbarContentDark(this, playerToolbar, 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(playerStatusbar, oldStatusbarColor, newStatusbarColor)); - } else { - playerStatusbar.setBackgroundColor(Color.TRANSPARENT); - } - - int titleTextColor = ColorUtil.getPrimaryTextColorForBackground(this, newColor); - int captionTextColor = ColorUtil.getSecondaryTextColorForBackground(this, 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(AbsSlidingMusicPanelActivity.this, 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; - } - - private void startUpdatingProgressViews() { - queueNextRefresh(1); - } - - private void stopUpdatingProgressViews() { - progressViewsUpdateHandler.removeMessages(CMD_REFRESH_PROGRESS_VIEWS); - } - - private void queueNextRefresh(final long delay) { - final Message message = progressViewsUpdateHandler.obtainMessage(CMD_REFRESH_PROGRESS_VIEWS); - progressViewsUpdateHandler.removeMessages(CMD_REFRESH_PROGRESS_VIEWS); - progressViewsUpdateHandler.sendMessageDelayed(message, delay); - } - - private long refreshProgressViews() { - final int totalMillis = MusicPlayerRemote.getSongDurationMillis(); - final int progressMillis = MusicPlayerRemote.getSongProgressMillis(); - - progressSlider.setMax(totalMillis); - progressSlider.setProgress(progressMillis); - songCurrentProgress.setText(MusicUtil.getReadableDurationString(progressMillis)); - songTotalTime.setText(MusicUtil.getReadableDurationString(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 static class MusicProgressViewsUpdateHandler extends Handler { - private WeakReference activityReference; - - public MusicProgressViewsUpdateHandler(final AbsSlidingMusicPanelActivity activity) { - super(); - activityReference = new WeakReference<>(activity); - } - - @Override - public void handleMessage(@NonNull Message msg) { - super.handleMessage(msg); - if (msg.what == CMD_REFRESH_PROGRESS_VIEWS) { - AbsSlidingMusicPanelActivity activity = activityReference.get(); - if (activity != null) { - long nextDelay = activityReference.get().refreshProgressViews(); - activityReference.get().queueNextRefresh(nextDelay); - } - } - } - } - - @Override - public boolean onMenuItemClick(MenuItem item) { - switch (item.getItemId()) { - case R.id.action_sleep_timer: - new SleepTimerDialog().show(getSupportFragmentManager(), "SET_SLEEP_TIMER"); - return true; - case R.id.action_toggle_favorite: - MusicUtil.toggleFavorite(this, song); - if (MusicUtil.isFavorite(this, song)) { - animateSetFavorite(); - } - updatePlayerMenu(); - return true; - case R.id.action_share: - SongShareDialog.create(song).show(getSupportFragmentManager(), "SHARE_SONG"); - return true; - case R.id.action_equalizer: - NavigationUtil.openEqualizer(this); - return true; - case R.id.action_shuffle_all: - MusicPlayerRemote.openAndShuffleQueue(SongLoader.getAllSongs(this), true); - return true; - case R.id.action_add_to_playlist: - AddToPlaylistDialog.create(song).show(getSupportFragmentManager(), "ADD_PLAYLIST"); - return true; - case R.id.action_playing_queue: - NavigationUtil.openPlayingQueueDialog(this); - return true; - case R.id.action_tag_editor: - Intent intent = new Intent(this, SongTagEditorActivity.class); - intent.putExtra(AbsTagEditorActivity.EXTRA_ID, song.id); - startActivity(intent); - return true; - case R.id.action_details: - SongDetailDialog.create(song).show(getSupportFragmentManager(), "SONG_DETAIL"); - return true; - case R.id.action_go_to_album: - NavigationUtil.goToAlbum(this, song.albumId); - return true; - case R.id.action_go_to_artist: - NavigationUtil.goToArtist(this, 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(); - } - @Override protected void setNavigationBarColor(@ColorInt int color) { this.navigationBarColor = color; - if (slidingUpPanelLayout == null || slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) { + if (isPanelCollapsed()) { super.setNavigationBarColor(color); } } @@ -1084,8 +180,19 @@ public abstract class AbsSlidingMusicPanelActivity extends AbsMusicServiceActivi @Override protected void notifyTaskColorChange(@ColorInt int color) { this.taskColor = color; - if (slidingUpPanelLayout == null || slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) { + if (isPanelCollapsed()) { super.notifyTaskColorChange(color); } } + + @Override + public void onPaletteColorChanged() { + if (!isPanelCollapsed()) { + int playerFragmentColor = playerFragment.getPaletteColor(); + super.notifyTaskColorChange(playerFragmentColor); + if (shouldColorNavigationBar()) { + super.setNavigationBarColor(playerFragmentColor); + } + } + } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/MiniPlayerFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/MiniPlayerFragment.java new file mode 100644 index 00000000..4ca804e7 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/MiniPlayerFragment.java @@ -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); + } + } +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/PlayerFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/PlayerFragment.java new file mode 100644 index 00000000..79854512 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/PlayerFragment.java @@ -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(); + } +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/util/NavigationUtil.java b/app/src/main/java/com/kabouzeid/gramophone/util/NavigationUtil.java index 9e8c55b9..6cc4ef96 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/util/NavigationUtil.java +++ b/app/src/main/java/com/kabouzeid/gramophone/util/NavigationUtil.java @@ -8,11 +8,9 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.ActivityOptionsCompat; import android.support.v4.util.Pair; -import android.support.v7.app.AppCompatActivity; import android.widget.Toast; import com.kabouzeid.gramophone.R; -import com.kabouzeid.gramophone.dialogs.PlayingQueueDialog; import com.kabouzeid.gramophone.helper.MusicPlayerRemote; import com.kabouzeid.gramophone.interfaces.KabViewsDisableAble; import com.kabouzeid.gramophone.model.Playlist; @@ -67,10 +65,6 @@ public class NavigationUtil { 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) { final int sessionId = MusicPlayerRemote.getAudioSessionId(); if (sessionId == AudioEffect.ERROR_BAD_VALUE) { diff --git a/app/src/main/java/com/kabouzeid/gramophone/views/FastScroller.java b/app/src/main/java/com/kabouzeid/gramophone/views/FastScroller.java index 495b609c..f3427691 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/views/FastScroller.java +++ b/app/src/main/java/com/kabouzeid/gramophone/views/FastScroller.java @@ -16,7 +16,6 @@ import android.view.View; import android.view.ViewPropertyAnimator; import android.widget.FrameLayout; -import com.afollestad.materialdialogs.internal.ThemeSingleton; import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.util.ColorUtil; import com.kabouzeid.gramophone.util.Util; @@ -58,7 +57,7 @@ public class FastScroller extends FrameLayout { handle = findViewById(R.id.scroll_handle); bar = findViewById(R.id.scroll_bar); handle.setEnabled(true); - setPressedHandleColor(ThemeSingleton.get().positiveColor.getDefaultColor()); + setPressedHandleColor(ColorUtil.resolveColor(getContext(), R.attr.colorControlActivated)); setUpBarBackground(); postDelayed(handleHider, HANDLE_HIDE_DELAY); } diff --git a/app/src/main/res/layout/fragment_mini_player.xml b/app/src/main/res/layout/fragment_mini_player.xml new file mode 100644 index 00000000..125919cc --- /dev/null +++ b/app/src/main/res/layout/fragment_mini_player.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/player.xml b/app/src/main/res/layout/fragment_player.xml similarity index 100% rename from app/src/main/res/layout/player.xml rename to app/src/main/res/layout/fragment_player.xml diff --git a/app/src/main/res/layout/mini_player.xml b/app/src/main/res/layout/mini_player.xml deleted file mode 100644 index ad7f473e..00000000 --- a/app/src/main/res/layout/mini_player.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/sliding_music_panel_layout.xml b/app/src/main/res/layout/sliding_music_panel_layout.xml index 6ee18333..e025d048 100644 --- a/app/src/main/res/layout/sliding_music_panel_layout.xml +++ b/app/src/main/res/layout/sliding_music_panel_layout.xml @@ -1,10 +1,11 @@ - @@ -14,16 +15,24 @@ android:layout_height="match_parent" /> - + - + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 130f5935..ba38643a 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -61,6 +61,6 @@ http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout 8dp - 48dp + 56dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2d5ad1a9..a9844830 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -205,4 +205,7 @@ For helping me with the design. Website Loading products… + + + Hello blank fragment