Sliding panel (early version, current implementation will probably replaced with a fragment implementation soon), translucent and colored statusbar for KitKat everywhere, use correct text colors for secondary texts, numerous clean ups

This commit is contained in:
Karim Abou Zeid 2015-07-30 22:44:34 +02:00
commit 5f0bfdb14b
65 changed files with 1247 additions and 1177 deletions

View file

@ -4,7 +4,6 @@ import android.os.Build;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.util.Pair;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.MenuItem;
@ -25,7 +24,6 @@ import com.kabouzeid.gramophone.loader.PlaylistSongLoader;
import com.kabouzeid.gramophone.model.Playlist;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.model.smartplaylist.AbsSmartPlaylist;
import com.kabouzeid.gramophone.ui.activities.base.AbsSlidingMusicPanelActivity;
import com.kabouzeid.gramophone.util.ColorUtil;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.NavigationUtil;
@ -216,11 +214,8 @@ public class PlaylistAdapter extends AbsMultiSelectAdapter<PlaylistAdapter.ViewH
if (isInQuickSelectMode()) {
toggleChecked(getAdapterPosition());
} else {
Pair[] sharedViews = null;
if (activity instanceof AbsSlidingMusicPanelActivity)
sharedViews = ((AbsSlidingMusicPanelActivity) activity).getSharedViewsWithPlayPauseFab(null);
Playlist playlist = dataSet.get(getAdapterPosition());
NavigationUtil.goToPlaylist(activity, playlist, sharedViews);
NavigationUtil.goToPlaylist(activity, playlist, null);
}
}

View file

@ -157,12 +157,11 @@ public class AlbumAdapter extends AbsMultiSelectAdapter<AlbumAdapter.ViewHolder,
private void setColors(int color, ViewHolder holder) {
if (holder.paletteColorContainer != null) {
holder.paletteColorContainer.setBackgroundColor(color);
int textColor = ColorUtil.getTextColorForBackground(color);
if (holder.title != null) {
holder.title.setTextColor(textColor);
holder.title.setTextColor(ColorUtil.getPrimaryTextColorForBackground(activity, color));
}
if (holder.text != null) {
holder.text.setTextColor(textColor);
holder.text.setTextColor(ColorUtil.getSecondaryTextColorForBackground(activity, color));
}
}
}
@ -223,7 +222,7 @@ public class AlbumAdapter extends AbsMultiSelectAdapter<AlbumAdapter.ViewHolder,
activity.getResources().getString(R.string.transition_album_art)
)};
if (activity instanceof AbsSlidingMusicPanelActivity)
albumPairs = ((AbsSlidingMusicPanelActivity) activity).getSharedViewsWithPlayPauseFab(albumPairs);
albumPairs = ((AbsSlidingMusicPanelActivity) activity).addPlayPauseFabToSharedViews(albumPairs);
NavigationUtil.goToAlbum(activity, dataSet.get(getAdapterPosition()).id, albumPairs);
}
}

View file

@ -151,12 +151,11 @@ public class ArtistAdapter extends AbsMultiSelectAdapter<ArtistAdapter.ViewHolde
private void setColors(int color, ViewHolder holder) {
if (holder.paletteColorContainer != null) {
holder.paletteColorContainer.setBackgroundColor(color);
int textColor = ColorUtil.getTextColorForBackground(color);
if (holder.title != null) {
holder.title.setTextColor(textColor);
holder.title.setTextColor(ColorUtil.getPrimaryTextColorForBackground(activity, color));
}
if (holder.text != null) {
holder.text.setTextColor(textColor);
holder.text.setTextColor(ColorUtil.getSecondaryTextColorForBackground(activity, color));
}
}
}
@ -212,7 +211,7 @@ public class ArtistAdapter extends AbsMultiSelectAdapter<ArtistAdapter.ViewHolde
activity.getResources().getString(R.string.transition_artist_image)
)};
if (activity instanceof AbsSlidingMusicPanelActivity)
artistPairs = ((AbsSlidingMusicPanelActivity) activity).getSharedViewsWithPlayPauseFab(artistPairs);
artistPairs = ((AbsSlidingMusicPanelActivity) activity).addPlayPauseFabToSharedViews(artistPairs);
NavigationUtil.goToArtist(activity, dataSet.get(getAdapterPosition()).id, artistPairs);
}
}

View file

@ -27,6 +27,7 @@ import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.NavigationUtil;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import java.util.ArrayList;
@ -34,6 +35,7 @@ import java.util.ArrayList;
* @author Karim Abou Zeid (kabouzeid)
*/
public class ArtistSongAdapter extends ArrayAdapter<Song> implements MaterialCab.Callback {
private static final int FADE_IN_TIME = 500;
@Nullable
private final CabHolder cabHolder;
@ -83,6 +85,7 @@ public class ArtistSongAdapter extends ArrayAdapter<Song> implements MaterialCab
.cacheInMemory(true)
.showImageOnFail(R.drawable.default_album_art)
.resetViewBeforeLoading(true)
.displayer(new FadeInBitmapDisplayer(FADE_IN_TIME, true, true, false))
.build()
);
@ -104,7 +107,7 @@ public class ArtistSongAdapter extends ArrayAdapter<Song> implements MaterialCab
Pair.create(albumArt, activity.getResources().getString(R.string.transition_album_art))
};
if (activity instanceof AbsSlidingMusicPanelActivity)
albumPairs = ((AbsSlidingMusicPanelActivity) activity).getSharedViewsWithPlayPauseFab(albumPairs);
albumPairs = ((AbsSlidingMusicPanelActivity) activity).addPlayPauseFabToSharedViews(albumPairs);
NavigationUtil.goToAlbum(activity, song.albumId, albumPairs);
return true;
}

View file

@ -55,7 +55,7 @@ public class SmartPlaylistSongAdapter extends SongAdapter {
Pair.create(image, activity.getString(R.string.transition_album_art))
};
if (activity instanceof AbsSlidingMusicPanelActivity)
albumPairs = ((AbsSlidingMusicPanelActivity) activity).getSharedViewsWithPlayPauseFab(albumPairs);
albumPairs = ((AbsSlidingMusicPanelActivity) activity).addPlayPauseFabToSharedViews(albumPairs);
NavigationUtil.goToAlbum(activity, dataSet.get(getAdapterPosition()).albumId, albumPairs);
return true;
}

View file

@ -124,15 +124,10 @@ public class SongAdapter extends AbsMultiSelectAdapter<SongAdapter.ViewHolder, S
return bitmap;
}
})
.displayer(new FadeInBitmapDisplayer(FADE_IN_TIME) {
.displayer(new FadeInBitmapDisplayer(FADE_IN_TIME, true, true, false) {
@Override
public void display(Bitmap bitmap, ImageAware imageAware, LoadedFrom loadedFrom) {
boolean loadedFromMemoryCache = loadedFrom == LoadedFrom.MEMORY_CACHE;
if (loadedFromMemoryCache) {
imageAware.setImageBitmap(bitmap);
} else {
super.display(bitmap, imageAware, loadedFrom);
}
super.display(bitmap, imageAware, loadedFrom);
if (usePalette)
setColors(holder.paletteColor, holder);
}
@ -153,12 +148,11 @@ public class SongAdapter extends AbsMultiSelectAdapter<SongAdapter.ViewHolder, S
private void setColors(int color, ViewHolder holder) {
if (holder.paletteColorContainer != null) {
holder.paletteColorContainer.setBackgroundColor(color);
int textColor = ColorUtil.getTextColorForBackground(color);
if (holder.title != null) {
holder.title.setTextColor(textColor);
holder.title.setTextColor(ColorUtil.getPrimaryTextColorForBackground(activity, color));
}
if (holder.text != null) {
holder.text.setTextColor(textColor);
holder.text.setTextColor(ColorUtil.getSecondaryTextColorForBackground(activity, color));
}
}
}
@ -244,7 +238,7 @@ public class SongAdapter extends AbsMultiSelectAdapter<SongAdapter.ViewHolder, S
Pair.create(image, activity.getResources().getString(R.string.transition_album_art))
};
if (activity instanceof AbsSlidingMusicPanelActivity)
albumPairs = ((AbsSlidingMusicPanelActivity) activity).getSharedViewsWithPlayPauseFab(albumPairs);
albumPairs = ((AbsSlidingMusicPanelActivity) activity).addPlayPauseFabToSharedViews(albumPairs);
NavigationUtil.goToAlbum(activity, getSong().albumId, albumPairs);
return true;
}

View file

@ -14,6 +14,7 @@ import android.widget.TextView;
import com.afollestad.materialdialogs.MaterialDialog;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.util.MusicUtil;
import org.jaudiotagger.audio.AudioFile;
@ -35,10 +36,10 @@ public class SongDetailDialog extends DialogFragment {
public static final String TAG = SongDetailDialog.class.getSimpleName();
@NonNull
public static SongDetailDialog create(File songFile) {
public static SongDetailDialog create(Song song) {
SongDetailDialog dialog = new SongDetailDialog();
Bundle args = new Bundle();
args.putSerializable("song_file", songFile);
args.putSerializable("song", song);
dialog.setArguments(args);
return dialog;
}
@ -47,7 +48,7 @@ public class SongDetailDialog extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Activity context = getActivity();
final File songFile = (File) getArguments().getSerializable("song_file");
final Song song = (Song) getArguments().getSerializable("song");
MaterialDialog dialog = new MaterialDialog.Builder(context)
.customView(R.layout.dialog_file_details, true)
@ -73,17 +74,20 @@ public class SongDetailDialog extends DialogFragment {
samplingRate.setText(makeTextWithTitle(context, R.string.label_sampling_rate, "-"));
try {
if (songFile != null && songFile.exists()) {
AudioFile audioFile = AudioFileIO.read(songFile);
AudioHeader audioHeader = audioFile.getAudioHeader();
if (song != null) {
final File songFile = new File(song.data);
if (songFile.exists()) {
AudioFile audioFile = AudioFileIO.read(songFile);
AudioHeader audioHeader = audioFile.getAudioHeader();
fileName.setText(makeTextWithTitle(context, R.string.label_file_name, songFile.getName()));
filePath.setText(makeTextWithTitle(context, R.string.label_file_path, songFile.getAbsolutePath()));
fileSize.setText(makeTextWithTitle(context, R.string.label_file_size, getFileSizeString(songFile.length())));
fileFormat.setText(makeTextWithTitle(context, R.string.label_file_format, audioHeader.getFormat()));
trackLength.setText(makeTextWithTitle(context, R.string.label_track_length, MusicUtil.getReadableDurationString(audioHeader.getTrackLength() * 1000)));
bitRate.setText(makeTextWithTitle(context, R.string.label_bit_rate, audioHeader.getBitRate() + " kb/s"));
samplingRate.setText(makeTextWithTitle(context, R.string.label_sampling_rate, audioHeader.getSampleRate() + " Hz"));
fileName.setText(makeTextWithTitle(context, R.string.label_file_name, songFile.getName()));
filePath.setText(makeTextWithTitle(context, R.string.label_file_path, songFile.getAbsolutePath()));
fileSize.setText(makeTextWithTitle(context, R.string.label_file_size, getFileSizeString(songFile.length())));
fileFormat.setText(makeTextWithTitle(context, R.string.label_file_format, audioHeader.getFormat()));
trackLength.setText(makeTextWithTitle(context, R.string.label_track_length, MusicUtil.getReadableDurationString(audioHeader.getTrackLength() * 1000)));
bitRate.setText(makeTextWithTitle(context, R.string.label_bit_rate, audioHeader.getBitRate() + " kb/s"));
samplingRate.setText(makeTextWithTitle(context, R.string.label_sampling_rate, audioHeader.getSampleRate() + " Hz"));
}
}
} catch (@NonNull CannotReadException | IOException | TagException | ReadOnlyFileException | InvalidAudioFrameException e) {
Log.e(TAG, "error while reading the song file", e);

View file

@ -183,10 +183,11 @@ public class MusicPlayerRemote {
return -1;
}
public static void seekTo(int millis) {
public static int seekTo(int millis) {
if (musicService != null) {
musicService.seek(millis);
return musicService.seek(millis);
}
return -1;
}
public static int getRepeatMode() {

View file

@ -21,8 +21,6 @@ import com.kabouzeid.gramophone.ui.activities.tageditor.SongTagEditorActivity;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.NavigationUtil;
import java.io.File;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
@ -57,19 +55,18 @@ public class SongMenuHelper {
activity.startActivity(tagEditorIntent);
return true;
case R.id.action_details:
File songFile = new File(song.data);
SongDetailDialog.create(songFile).show(activity.getSupportFragmentManager(), "SONG_DETAILS");
SongDetailDialog.create(song).show(activity.getSupportFragmentManager(), "SONG_DETAILS");
return true;
case R.id.action_go_to_album:
Pair[] albumPairs = null;
if (activity instanceof AbsSlidingMusicPanelActivity)
albumPairs = ((AbsSlidingMusicPanelActivity) activity).getSharedViewsWithPlayPauseFab(null);
albumPairs = ((AbsSlidingMusicPanelActivity) activity).addPlayPauseFabToSharedViews(null);
NavigationUtil.goToAlbum(activity, song.albumId, albumPairs);
return true;
case R.id.action_go_to_artist:
Pair[] artistPairs = null;
if (activity instanceof AbsSlidingMusicPanelActivity)
artistPairs = ((AbsSlidingMusicPanelActivity) activity).getSharedViewsWithPlayPauseFab(null);
artistPairs = ((AbsSlidingMusicPanelActivity) activity).addPlayPauseFabToSharedViews(null);
NavigationUtil.goToArtist(activity, song.artistId, artistPairs);
return true;
}

View file

@ -6,9 +6,7 @@ package com.kabouzeid.gramophone.interfaces;
public interface MusicStateListener {
void onPlayingMetaChanged();
void onPlayStateChanged();
void onMediaStoreChanged();
}

View file

@ -0,0 +1,28 @@
package com.kabouzeid.gramophone.misc;
import android.animation.Animator;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public abstract class SimpleAnimatorListener implements Animator.AnimatorListener {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
}

View file

@ -6,7 +6,7 @@ import com.github.ksoichiro.android.observablescrollview.ScrollState;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class SmallObservableScrollViewCallbacks implements ObservableScrollViewCallbacks {
public abstract class SimpleObservableScrollViewCallbacks implements ObservableScrollViewCallbacks {
@Override
public void onScrollChanged(int i, boolean b, boolean b2) {

View file

@ -0,0 +1,23 @@
package com.kabouzeid.gramophone.misc;
import android.widget.SeekBar;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public abstract class SimpleOnSeekbarChangeListener implements SeekBar.OnSeekBarChangeListener {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
}

View file

@ -7,7 +7,7 @@ import android.transition.Transition;
* @author Karim Abou Zeid (kabouzeid)
*/
@TargetApi(21)
public class SmallTransitionListener implements Transition.TransitionListener {
public abstract class SimpleTransitionListener implements Transition.TransitionListener {
@Override
public void onTransitionStart(Transition transition) {

View file

@ -1,39 +0,0 @@
package com.kabouzeid.gramophone.misc;
import android.view.GestureDetector;
import android.view.MotionEvent;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class SmallOnGestureListener implements GestureDetector.OnGestureListener {
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
}

View file

@ -24,12 +24,9 @@ public class MultiPlayer implements MediaPlayer.OnErrorListener,
MediaPlayer.OnCompletionListener {
public static final String TAG = MultiPlayer.class.getSimpleName();
@NonNull
private final WeakReference<MusicService> mService;
@Nullable
private MediaPlayer mCurrentMediaPlayer = new MediaPlayer();
@Nullable
private MediaPlayer mNextMediaPlayer;
private Handler mHandler;

View file

@ -741,9 +741,10 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
return player.duration();
}
public void seek(int millis) {
player.seek(millis);
public int seek(int millis) {
int newPosition = player.seek(millis);
savePositionInTrack();
return newPosition;
}
public void cycleRepeatMode() {

View file

@ -33,8 +33,8 @@ import com.kabouzeid.gramophone.interfaces.CabHolder;
import com.kabouzeid.gramophone.interfaces.PaletteColorHolder;
import com.kabouzeid.gramophone.loader.AlbumLoader;
import com.kabouzeid.gramophone.loader.AlbumSongLoader;
import com.kabouzeid.gramophone.misc.SmallObservableScrollViewCallbacks;
import com.kabouzeid.gramophone.misc.SmallTransitionListener;
import com.kabouzeid.gramophone.misc.SimpleObservableScrollViewCallbacks;
import com.kabouzeid.gramophone.misc.SimpleTransitionListener;
import com.kabouzeid.gramophone.model.Album;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.ui.activities.base.AbsSlidingMusicPanelActivity;
@ -57,9 +57,7 @@ import butterknife.Bind;
import butterknife.ButterKnife;
/**
* A lot of hackery is done in this activity. Changing things may will brake the whole activity.
* <p/>
* Should be kinda stable ONLY AS IT IS!!!
* Be careful when changing things in this Activity!
*/
public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements PaletteColorHolder, CabHolder {
@ -97,7 +95,6 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements
protected void onCreate(Bundle savedInstanceState) {
setStatusBarTransparent();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_album_detail);
ButterKnife.bind(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@ -114,9 +111,14 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements
animateFabCircularRevealOnEnterTransitionEnd();
}
@Override
protected View createContentView() {
return wrapSlidingMusicPanelAndFab(R.layout.activity_album_detail);
}
private void animateFabCircularRevealOnEnterTransitionEnd() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().getEnterTransition().addListener(new SmallTransitionListener() {
getWindow().getEnterTransition().addListener(new SimpleTransitionListener() {
@Override
public void onTransitionStart(Transition transition) {
albumArtBackground.setVisibility(View.INVISIBLE);
@ -140,11 +142,10 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements
}
}
private final SmallObservableScrollViewCallbacks observableScrollViewCallbacks = new SmallObservableScrollViewCallbacks() {
private final SimpleObservableScrollViewCallbacks observableScrollViewCallbacks = new SimpleObservableScrollViewCallbacks() {
@Override
public void onScrollChanged(int scrollY, boolean b, boolean b2) {
scrollY += albumArtViewHeight + titleViewHeight;
super.onScrollChanged(scrollY, b, b2);
float flexibleRange = albumArtViewHeight - headerOffset;
// Translate album cover
@ -253,7 +254,7 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements
private void setColors(int vibrantColor) {
toolbarColor = vibrantColor;
albumTitleView.setBackgroundColor(vibrantColor);
albumTitleView.setTextColor(ColorUtil.getTextColorForBackground(vibrantColor));
albumTitleView.setTextColor(ColorUtil.getPrimaryTextColorForBackground(this, vibrantColor));
if (shouldColorNavigationBar())
setNavigationBarColor(vibrantColor);
@ -280,6 +281,7 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements
public void run() {
songsBackgroundView.getLayoutParams().height = contentView.getHeight();
observableScrollViewCallbacks.onScrollChanged(-(albumArtViewHeight + titleViewHeight), false, false);
// necessary to fix a bug
recyclerView.scrollBy(0, 1);
recyclerView.scrollBy(0, -1);
}
@ -350,19 +352,13 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements
case android.R.id.home:
super.onBackPressed();
return true;
case R.id.action_playing_queue:
NavigationUtil.openPlayingQueueDialog(this);
return true;
case R.id.action_now_playing:
NavigationUtil.openCurrentPlayingIfPossible(this, getSharedViewsWithPlayPauseFab(null));
return true;
case R.id.action_tag_editor:
Intent intent = new Intent(this, AlbumTagEditorActivity.class);
intent.putExtra(AbsTagEditorActivity.EXTRA_ID, album.id);
startActivityForResult(intent, TAG_EDITOR_REQUEST);
return true;
case R.id.action_go_to_artist:
Pair[] artistPairs = getSharedViewsWithPlayPauseFab(null);
Pair[] artistPairs = addPlayPauseFabToSharedViews(null);
NavigationUtil.goToArtist(this, album.artistId, artistPairs);
return true;
}

View file

@ -41,8 +41,8 @@ import com.kabouzeid.gramophone.lastfm.rest.model.artistinfo.ArtistInfo;
import com.kabouzeid.gramophone.loader.ArtistAlbumLoader;
import com.kabouzeid.gramophone.loader.ArtistLoader;
import com.kabouzeid.gramophone.loader.ArtistSongLoader;
import com.kabouzeid.gramophone.misc.SmallObservableScrollViewCallbacks;
import com.kabouzeid.gramophone.misc.SmallTransitionListener;
import com.kabouzeid.gramophone.misc.SimpleObservableScrollViewCallbacks;
import com.kabouzeid.gramophone.misc.SimpleTransitionListener;
import com.kabouzeid.gramophone.model.Album;
import com.kabouzeid.gramophone.model.Artist;
import com.kabouzeid.gramophone.model.Song;
@ -68,9 +68,7 @@ import retrofit.RetrofitError;
import retrofit.client.Response;
/**
* A lot of hackery is done in this activity. Changing things may will brake the whole activity.
* <p/>
* Should be kinda stable ONLY AS IT IS!!!
* Be careful when changing things in this Activity!
*/
public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implements PaletteColorHolder, CabHolder {
@ -114,13 +112,8 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement
protected void onCreate(Bundle savedInstanceState) {
setStatusBarTransparent();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_artist_detail);
ButterKnife.bind(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
postponeEnterTransition();
}
if (shouldColorNavigationBar())
setNavigationBarColor(DialogUtils.resolveColor(this, R.attr.default_bar_color));
@ -137,12 +130,7 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
fixLollipopTransitionImageWrongSize();
startPostponedEnterTransition();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().getEnterTransition().addListener(new SmallTransitionListener() {
getWindow().getEnterTransition().addListener(new SimpleTransitionListener() {
@Override
public void onTransitionStart(Transition transition) {
artistImageBackground.setVisibility(View.INVISIBLE);
@ -166,11 +154,15 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement
}
}
private final SmallObservableScrollViewCallbacks observableScrollViewCallbacks = new SmallObservableScrollViewCallbacks() {
@Override
protected View createContentView() {
return wrapSlidingMusicPanelAndFab(R.layout.activity_artist_detail);
}
private final SimpleObservableScrollViewCallbacks observableScrollViewCallbacks = new SimpleObservableScrollViewCallbacks() {
@Override
public void onScrollChanged(int scrollY, boolean b, boolean b2) {
scrollY += artistImageViewHeight + titleViewHeight;
super.onScrollChanged(scrollY, b, b2);
float flexibleRange = artistImageViewHeight - headerOffset;
// Translate album cover
@ -214,12 +206,7 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement
private void setUpViews() {
artistName.setText(artist.name);
ViewUtil.addOnGlobalLayoutListener(artistImage, new Runnable() {
@Override
public void run() {
setUpArtistImageAndApplyPalette(false);
}
});
setUpArtistImageAndApplyPalette(false);
setUpSongListView();
setUpAlbumRecyclerView();
loadBiography();
@ -377,7 +364,7 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement
private void setColors(int vibrantColor) {
toolbarColor = vibrantColor;
artistName.setBackgroundColor(vibrantColor);
artistName.setTextColor(ColorUtil.getTextColorForBackground(vibrantColor));
artistName.setTextColor(ColorUtil.getPrimaryTextColorForBackground(this, vibrantColor));
if (shouldColorNavigationBar())
setNavigationBarColor(vibrantColor);
@ -416,9 +403,6 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement
case android.R.id.home:
super.onBackPressed();
return true;
case R.id.action_playing_queue:
NavigationUtil.openPlayingQueueDialog(this);
return true;
case R.id.action_biography:
if (biography != null) {
getBiographyDialog().show();
@ -430,9 +414,6 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement
Toast.makeText(ArtistDetailActivity.this, getResources().getString(R.string.updating), Toast.LENGTH_SHORT).show();
setUpArtistImageAndApplyPalette(true);
return true;
case R.id.action_now_playing:
NavigationUtil.openCurrentPlayingIfPossible(this, getSharedViewsWithPlayPauseFab(null));
return true;
}
return super.onOptionsItemSelected(item);
}
@ -453,37 +434,6 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement
albumRecyclerView.setEnabled(false);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void fixLollipopTransitionImageWrongSize() {
getWindow().getSharedElementEnterTransition().addListener(new Transition.TransitionListener() {
@Override
public void onTransitionStart(Transition transition) {
}
@Override
public void onTransitionEnd(Transition transition) {
setUpArtistImageAndApplyPalette(false);
}
@Override
public void onTransitionCancel(Transition transition) {
}
@Override
public void onTransitionPause(Transition transition) {
}
@Override
public void onTransitionResume(Transition transition) {
}
});
}
@Override
public MaterialCab openCab(int menuRes, @NonNull final MaterialCab.Callback callback) {
if (cab != null && cab.isActive()) cab.finish();

View file

@ -1,11 +1,13 @@
package com.kabouzeid.gramophone.ui.activities;
import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@ -17,7 +19,6 @@ import android.support.design.widget.AppBarLayout.OnOffsetChangedListener;
import android.support.design.widget.NavigationView;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.util.Pair;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
@ -29,6 +30,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
@ -51,16 +53,14 @@ import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.ui.activities.base.AbsSlidingMusicPanelActivity;
import com.kabouzeid.gramophone.ui.fragments.mainactivityfragments.AbsMainActivityFragment;
import com.kabouzeid.gramophone.ui.fragments.mainactivityfragments.AbsMainActivityRecyclerViewLayoutModeFragment;
import com.kabouzeid.gramophone.ui.fragments.mainactivityfragments.AlbumViewFragment;
import com.kabouzeid.gramophone.ui.fragments.mainactivityfragments.ArtistViewFragment;
import com.kabouzeid.gramophone.ui.fragments.mainactivityfragments.PlaylistViewFragment;
import com.kabouzeid.gramophone.ui.fragments.mainactivityfragments.SongViewFragment;
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.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.sothree.slidinguppanel.SlidingUpPanelLayout;
import java.io.File;
import java.lang.reflect.Field;
@ -97,15 +97,32 @@ public class MainActivity extends AbsSlidingMusicPanelActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
Util.setStatusBarTranslucent(getWindow());
drawerLayout.setFitsSystemWindows(false);
navigationView.setFitsSystemWindows(false);
findViewById(R.id.drawer_content_container).setFitsSystemWindows(false);
}
setUpDrawerLayout();
setUpToolbar();
setUpViewPager();
if (shouldColorNavigationBar())
setNavigationBarThemeColor();
setStatusBarThemeColor();
}
@Override
protected View createContentView() {
@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));
return contentView;
}
private void setUpViewPager() {
@ -258,7 +275,6 @@ public class MainActivity extends AbsSlidingMusicPanelActivity
}
private void setUpDrawerLayout() {
drawerLayout.setStatusBarBackgroundColor(getThemeColorPrimaryDarker());
setUpNavigationView();
}
@ -271,12 +287,10 @@ public class MainActivity extends AbsSlidingMusicPanelActivity
navigationDrawerHeader.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//noinspection ConstantConditions
NavigationUtil.openCurrentPlayingIfPossible(MainActivity.this, getSharedViewsWithPlayPauseFab(new Pair[]{
Pair.create(navigationDrawerHeader.findViewById(R.id.image),
getResources().getString(R.string.transition_album_art)
)
}));
drawerLayout.closeDrawers();
if (getSlidingUpPanelLayout().getPanelState() != SlidingUpPanelLayout.PanelState.EXPANDED) {
getSlidingUpPanelLayout().setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED);
}
}
});
}
@ -391,12 +405,6 @@ public class MainActivity extends AbsSlidingMusicPanelActivity
case R.id.action_search:
startActivity(new Intent(MainActivity.this, SearchActivity.class));
return true;
case R.id.action_now_playing:
NavigationUtil.openCurrentPlayingIfPossible(this, getSharedViewsWithPlayPauseFab(null));
return true;
case R.id.action_playing_queue:
NavigationUtil.openPlayingQueueDialog(this);
return true;
}
return super.onOptionsItemSelected(item);
}
@ -524,38 +532,37 @@ public class MainActivity extends AbsSlidingMusicPanelActivity
return pagerAdapter.getFragment(pager.getCurrentItem());
}
private boolean isArtistPage() {
return pager.getCurrentItem() == PagerAdapter.MusicFragments.ARTIST.ordinal();
}
public ArtistViewFragment getArtistFragment() {
return (ArtistViewFragment) pagerAdapter.getFragment(PagerAdapter.MusicFragments.ARTIST.ordinal());
}
private boolean isAlbumPage() {
return pager.getCurrentItem() == PagerAdapter.MusicFragments.ALBUM.ordinal();
}
@NonNull
public AlbumViewFragment getAlbumFragment() {
return (AlbumViewFragment) pagerAdapter.getFragment(PagerAdapter.MusicFragments.ALBUM.ordinal());
}
private boolean isSongPage() {
return pager.getCurrentItem() == PagerAdapter.MusicFragments.SONG.ordinal();
}
public SongViewFragment getSongFragment() {
return (SongViewFragment) pagerAdapter.getFragment(PagerAdapter.MusicFragments.SONG.ordinal());
}
// private boolean isArtistPage() {
// return pager.getCurrentItem() == PagerAdapter.MusicFragments.ARTIST.ordinal();
// }
//
// public ArtistViewFragment getArtistFragment() {
// return (ArtistViewFragment) pagerAdapter.getFragment(PagerAdapter.MusicFragments.ARTIST.ordinal());
// }
//
// private boolean isAlbumPage() {
// return pager.getCurrentItem() == PagerAdapter.MusicFragments.ALBUM.ordinal();
// }
//
// public AlbumViewFragment getAlbumFragment() {
// return (AlbumViewFragment) pagerAdapter.getFragment(PagerAdapter.MusicFragments.ALBUM.ordinal());
// }
//
// private boolean isSongPage() {
// return pager.getCurrentItem() == PagerAdapter.MusicFragments.SONG.ordinal();
// }
//
// public SongViewFragment getSongFragment() {
// return (SongViewFragment) pagerAdapter.getFragment(PagerAdapter.MusicFragments.SONG.ordinal());
// }
private boolean isPlaylistPage() {
return pager.getCurrentItem() == PagerAdapter.MusicFragments.PLAYLIST.ordinal();
}
public PlaylistViewFragment getPlaylistFragment() {
return (PlaylistViewFragment) pagerAdapter.getFragment(PagerAdapter.MusicFragments.PLAYLIST.ordinal());
}
// public PlaylistViewFragment getPlaylistFragment() {
// return (PlaylistViewFragment) pagerAdapter.getFragment(PagerAdapter.MusicFragments.PLAYLIST.ordinal());
// }
@Override
public boolean dispatchKeyEvent(@NonNull KeyEvent event) {
@ -589,4 +596,16 @@ public class MainActivity extends AbsSlidingMusicPanelActivity
public int getTotalAppBarScrollingRange() {
return appbar.getTotalScrollRange();
}
@Override
public void onPanelExpanded(View view) {
super.onPanelExpanded(view);
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
}
@Override
public void onPanelCollapsed(View view) {
super.onPanelCollapsed(view);
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
}
}

View file

@ -1,706 +0,0 @@
package com.kabouzeid.gramophone.ui.activities;
import android.animation.Animator;
import android.annotation.TargetApi;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.graphics.Palette;
import android.support.v7.widget.CardView;
import android.support.v7.widget.Toolbar;
import android.transition.Transition;
import android.util.TypedValue;
import android.view.Menu;
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.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.ThemeSingleton;
import com.afollestad.materialdialogs.util.DialogUtils;
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.imageloader.BlurProcessor;
import com.kabouzeid.gramophone.loader.SongLoader;
import com.kabouzeid.gramophone.misc.SmallTransitionListener;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.service.MusicService;
import com.kabouzeid.gramophone.ui.activities.base.AbsSlidingMusicPanelActivity;
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.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.listener.SimpleImageLoadingListener;
import java.io.File;
import java.lang.ref.WeakReference;
import butterknife.Bind;
import butterknife.ButterKnife;
import hugo.weaving.DebugLog;
public class MusicControllerActivity extends AbsSlidingMusicPanelActivity {
public static final String TAG = MusicControllerActivity.class.getSimpleName();
private static final int FAB_CIRCULAR_REVEAL_ANIMATION_TIME = 1000;
private static final int PROGRESS_VIEW_UPDATE_INTERVAL = 100;
private static final int CMD_UPDATE_PROGRESS_VIEWS = 1;
@Bind(R.id.title)
TextView songTitle;
@Bind(R.id.text)
TextView songArtist;
@Bind(R.id.footer)
LinearLayout footer;
@Bind(R.id.playback_controller_card)
CardView playbackControllerCard;
@Bind(R.id.prev_button)
ImageButton prevButton;
@Bind(R.id.next_button)
ImageButton nextButton;
@Bind(R.id.repeat_button)
ImageButton repeatButton;
@Bind(R.id.shuffle_button)
ImageButton shuffleButton;
@Bind(R.id.media_controller_container)
RelativeLayout mediaControllerContainer;
@Bind(R.id.album_art_background)
ImageView albumArtBackground;
@Bind(R.id.image)
SquareIfPlaceImageView albumArt;
@Bind(R.id.toolbar)
Toolbar toolbar;
@Bind(R.id.favorite_icon)
ImageView favoriteIcon;
TextView songCurrentProgress;
TextView songTotalTime;
SeekBar progressSlider;
private int lastFooterColor = -1;
private int lastTextColor = -2;
private Handler progressViewsUpdateHandler;
private HandlerThread handlerThread;
private boolean opaqueStatusBar;
private boolean opaqueToolBar;
private boolean forceSquareAlbumArt;
private boolean largerTitleBox;
private boolean alternativeProgressSlider;
private boolean showPlaybackControllerCard;
private Song song;
@Override
protected void onCreate(Bundle savedInstanceState) {
setStatusBarTransparent();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_music_controller);
ButterKnife.bind(this);
initAppearanceVarsFromSharedPrefs();
initProgressSliderDependentViews();
moveSeekBarIntoPlace();
adjustTitleBoxSize();
setUpPlaybackControllerCard();
setUpMusicControllers();
setUpAlbumArtViews();
setUpToolbar();
animateFabCircularRevealOnEnterTransitionEnd();
updateCurrentSong();
}
private void initProgressSliderDependentViews() {
if (alternativeProgressSlider) {
findViewById(R.id.default_progress_container).setVisibility(View.GONE);
findViewById(R.id.default_progress_slider).setVisibility(View.GONE);
findViewById(R.id.alternative_progress_container).setVisibility(View.VISIBLE);
songCurrentProgress = (TextView) findViewById(R.id.alternative_song_current_progress);
songTotalTime = (TextView) findViewById(R.id.alternative_song_total_time);
progressSlider = (SeekBar) findViewById(R.id.alternative_progress_slider);
} else {
songCurrentProgress = (TextView) findViewById(R.id.default_song_current_progress);
songTotalTime = (TextView) findViewById(R.id.default_song_total_time);
progressSlider = (SeekBar) findViewById(R.id.default_progress_slider);
}
}
private void setUpAlbumArtViews() {
albumArtBackground.setAlpha(0.7f);
albumArt.forceSquare(forceSquareAlbumArt);
if (opaqueStatusBar) {
if (opaqueToolBar) {
alignAlbumArtToToolbar();
} else {
alignAlbumArtToStatusBar();
}
} else {
alignAlbumArtToTop();
}
}
private void setUpToolbar() {
setSupportActionBar(toolbar);
//noinspection ConstantConditions
getSupportActionBar().setTitle(null);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
}
private void animateFabCircularRevealOnEnterTransitionEnd() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().getEnterTransition().addListener(new SmallTransitionListener() {
@Override
public void onTransitionStart(Transition transition) {
mediaControllerContainer.setVisibility(View.INVISIBLE);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onTransitionEnd(Transition transition) {
int cx = (getPlayPauseFab().getLeft() + getPlayPauseFab().getRight()) / 2;
int cy = (getPlayPauseFab().getTop() + getPlayPauseFab().getBottom()) / 2;
int finalRadius = Math.max(mediaControllerContainer.getWidth(), mediaControllerContainer.getHeight());
Animator animator = ViewAnimationUtils.createCircularReveal(mediaControllerContainer, cx, cy, getPlayPauseFab().getWidth() / 2, finalRadius);
animator.setInterpolator(new DecelerateInterpolator());
animator.setDuration(FAB_CIRCULAR_REVEAL_ANIMATION_TIME);
animator.start();
mediaControllerContainer.setVisibility(View.VISIBLE);
}
});
}
}
private void startHandler() {
handlerThread = new HandlerThread("MusicProgressViewUpdateHandler",
android.os.Process.THREAD_PRIORITY_BACKGROUND);
handlerThread.start();
progressViewsUpdateHandler = new MusicProgressViewsUpdateHandler(this, handlerThread.getLooper());
}
private void stopHandler() {
progressViewsUpdateHandler.removeCallbacksAndMessages(null);
if (Build.VERSION.SDK_INT >= 18) {
handlerThread.quitSafely();
} else {
handlerThread.quit();
}
}
private void startUpdatingProgressViews() {
startHandler();
progressViewsUpdateHandler.sendEmptyMessage(CMD_UPDATE_PROGRESS_VIEWS);
}
private void stopUpdatingProgressViews() {
progressViewsUpdateHandler.removeMessages(CMD_UPDATE_PROGRESS_VIEWS);
stopHandler();
}
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();
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
getPlayPauseFab().setOnLongClickListener(null);
}
private void moveSeekBarIntoPlace() {
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));
songArtist.setPadding(songArtist.getPaddingLeft(), largerTitleBox ? getResources().getDimensionPixelSize(R.dimen.title_box_text_spacing_large) : getResources().getDimensionPixelSize(R.dimen.title_box_text_spacing_small), songArtist.getPaddingRight(), songArtist.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));
songArtist.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);
mediaControllerContainer.setBackgroundColor(showPlaybackControllerCard ? Color.TRANSPARENT : ColorUtil.resolveColor(this, R.attr.music_controller_container_color));
}
private void setUpMusicControllers() {
setUpPrevNext();
setUpRepeatButton();
setUpShuffleButton();
setUpProgressSlider();
}
private void setTint(@NonNull SeekBar seekBar, int color) {
ColorStateList s1 = ColorStateList.valueOf(color);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
seekBar.setThumbTintList(s1);
if (!alternativeProgressSlider) seekBar.setProgressTintList(s1);
} else {
seekBar.getThumb().setColorFilter(color, PorterDuff.Mode.SRC_IN);
if (!alternativeProgressSlider)
seekBar.getProgressDrawable().setColorFilter(color, PorterDuff.Mode.SRC_IN);
}
}
private void setUpProgressSlider() {
progressSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
MusicPlayerRemote.seekTo(progress);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
private void setUpPrevNext() {
nextButton.setImageDrawable(Util.getTintedDrawable(this,
R.drawable.ic_skip_next_white_36dp, DialogUtils.resolveColor(this, R.attr.themed_drawable_color)));
prevButton.setImageDrawable(Util.getTintedDrawable(this,
R.drawable.ic_skip_previous_white_36dp, DialogUtils.resolveColor(this, R.attr.themed_drawable_color)));
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,
getThemeColorAccent() == Color.WHITE ? Color.BLACK : getThemeColorAccent()));
break;
default:
shuffleButton.setImageDrawable(Util.getTintedDrawable(this, R.drawable.ic_shuffle_white_36dp,
DialogUtils.resolveColor(this, R.attr.themed_drawable_color)));
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_NONE:
repeatButton.setImageDrawable(Util.getTintedDrawable(this, R.drawable.ic_repeat_white_36dp,
DialogUtils.resolveColor(this, R.attr.themed_drawable_color)));
break;
case MusicService.REPEAT_MODE_ALL:
repeatButton.setImageDrawable(Util.getTintedDrawable(this, R.drawable.ic_repeat_white_36dp,
getThemeColorAccent() == Color.WHITE ? Color.BLACK : getThemeColorAccent()));
break;
default:
repeatButton.setImageDrawable(Util.getTintedDrawable(this, R.drawable.ic_repeat_one_white_36dp,
getThemeColorAccent() == Color.WHITE ? Color.BLACK : getThemeColorAccent()));
break;
}
}
@Override
protected void onResume() {
super.onResume();
startUpdatingProgressViews();
}
@Override
protected void onPause() {
super.onPause();
stopUpdatingProgressViews();
}
private void updateCurrentSong() {
getCurrentSong();
setHeadersText();
setUpAlbumArtAndApplyPalette();
songTotalTime.setText(MusicUtil.getReadableDurationString(song.duration));
songCurrentProgress.setText(MusicUtil.getReadableDurationString(0));
invalidateOptionsMenu();
}
private void setHeadersText() {
songTitle.setText(song.title);
songArtist.setText(song.artistName);
}
@Override
protected boolean overridesTaskColor() {
return true;
}
private void setUpAlbumArtAndApplyPalette() {
ImageLoader.getInstance().displayImage(
MusicUtil.getSongImageLoaderString(song),
albumArt,
new DisplayImageOptions.Builder()
.cacheInMemory(true)
.showImageOnFail(R.drawable.default_album_art)
.build(),
new SimpleImageLoadingListener() {
@DebugLog
@Override
public void onLoadingFailed(String imageUri, View view, @Nullable FailReason failReason) {
applyPalette(null);
ImageLoader.getInstance().displayImage(
"drawable://" + R.drawable.default_album_art,
albumArtBackground,
new DisplayImageOptions.Builder().postProcessor(new BlurProcessor(10)).build()
);
}
@DebugLog
@Override
public void onLoadingComplete(String imageUri, View view, @Nullable Bitmap loadedImage) {
if (loadedImage == null) {
onLoadingFailed(imageUri, view, null);
return;
}
applyPalette(loadedImage);
ImageLoader.getInstance().displayImage(
imageUri,
albumArtBackground,
new DisplayImageOptions.Builder().postProcessor(new BlurProcessor(10)).build()
);
}
}
);
}
private void applyPalette(@Nullable Bitmap bitmap) {
final int defaultBarColor = ColorUtil.resolveColor(this, R.attr.default_bar_color);
if (bitmap != null) {
Palette.from(bitmap)
.resizeBitmapSize(100)
.generate(new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(@NonNull Palette palette) {
setColors(palette.getVibrantColor(defaultBarColor));
}
});
} else {
setColors(defaultBarColor);
}
}
private void setColors(int vibrantColor) {
animateColorChange(vibrantColor);
animateTextColorChange(ColorUtil.getTextColorForBackground(vibrantColor));
notifyTaskColorChange(vibrantColor);
}
private void animateColorChange(final int newColor) {
if (lastFooterColor != -1 && lastFooterColor != newColor) {
ViewUtil.animateViewColor(footer, lastFooterColor, newColor);
if (opaqueToolBar)
ViewUtil.animateViewColor(toolbar, lastFooterColor, newColor);
else toolbar.setBackgroundColor(Color.TRANSPARENT);
} else {
footer.setBackgroundColor(newColor);
if (opaqueToolBar) toolbar.setBackgroundColor(newColor);
else toolbar.setBackgroundColor(Color.TRANSPARENT);
}
setTint(progressSlider, !ThemeSingleton.get().darkTheme && getThemeColorAccent() == Color.WHITE ? Color.BLACK : getThemeColorAccent());
if (opaqueStatusBar) setStatusBarColor(newColor);
else setStatusBarColor(Color.TRANSPARENT);
if (shouldColorNavigationBar())
setNavigationBarColor(newColor);
lastFooterColor = newColor;
}
private void animateTextColorChange(final int newColor) {
if (lastTextColor != -2 && lastTextColor != newColor) {
ViewUtil.animateTextColor(songTitle, lastTextColor, newColor);
ViewUtil.animateTextColor(songArtist, lastTextColor, newColor);
} else {
songTitle.setTextColor(newColor);
songArtist.setTextColor(newColor);
}
lastTextColor = newColor;
}
private void getCurrentSong() {
song = MusicPlayerRemote.getCurrentSong();
if (song.id == -1) {
finish();
}
}
private void updateProgressViews() {
final int totalMillis = MusicPlayerRemote.getSongDurationMillis();
final int progressMillis = MusicPlayerRemote.getSongProgressMillis();
runOnUiThread(new Runnable() {
@Override
public void run() {
progressSlider.setMax(totalMillis);
progressSlider.setProgress(progressMillis);
songCurrentProgress.setText(MusicUtil.getReadableDurationString(progressMillis));
songTotalTime.setText(MusicUtil.getReadableDurationString(totalMillis));
}
});
}
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 Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
favoriteIcon.setVisibility(View.INVISIBLE);
}
@Override
public void onAnimationRepeat(Animator animation) {
}
})
.withEndAction(new Runnable() {
@Override
public void run() {
favoriteIcon.animate()
.setDuration(300)
.setInterpolator(new DecelerateInterpolator())
.alpha(0f)
.start();
}
})
.start();
}
@Override
public void onPlayingMetaChanged() {
super.onPlayingMetaChanged();
updateCurrentSong();
}
@Override
public void onRepeatModeChanged() {
super.onRepeatModeChanged();
updateRepeatState();
}
@Override
public void onShuffleModeChanged() {
super.onShuffleModeChanged();
updateShuffleState();
}
@Override
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
getMenuInflater().inflate(R.menu.menu_music_playing, menu);
boolean isFavorite = MusicUtil.isFavorite(this, song);
menu.findItem(R.id.action_toggle_favorite)
.setIcon(isFavorite ? R.drawable.ic_favorite_white_24dp : R.drawable.ic_favorite_outline_white_24dp)
.setTitle(isFavorite ? getString(R.string.action_remove_from_favorites) : getString(R.string.action_add_to_favorites));
return true;
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();
switch (id) {
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();
}
invalidateOptionsMenu();
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 android.R.id.home:
super.onBackPressed();
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:
File songFile = new File(song.data);
SongDetailDialog.create(songFile).show(getSupportFragmentManager(), "SONG_DETAIL");
return true;
case R.id.action_go_to_album:
NavigationUtil.goToAlbum(this, song.albumId, getSharedViewsWithPlayPauseFab(null));
return true;
case R.id.action_go_to_artist:
NavigationUtil.goToArtist(this, song.artistId, getSharedViewsWithPlayPauseFab(null));
return true;
}
return super.onOptionsItemSelected(item);
}
private void alignAlbumArtToTop() {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) findViewById(R.id.album_art_frame).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.footer_frame);
}
}
private void alignAlbumArtToToolbar() {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) findViewById(R.id.album_art_frame).getLayoutParams();
params.addRule(RelativeLayout.BELOW, R.id.toolbar);
}
private void alignAlbumArtToStatusBar() {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) findViewById(R.id.album_art_frame).getLayoutParams();
params.addRule(RelativeLayout.BELOW, R.id.status_bar);
}
private static class MusicProgressViewsUpdateHandler extends Handler {
private WeakReference<MusicControllerActivity> activityReference;
public MusicProgressViewsUpdateHandler(final MusicControllerActivity activity, @NonNull final Looper looper) {
super(looper);
activityReference = new WeakReference<>(activity);
}
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
if (msg.what == CMD_UPDATE_PROGRESS_VIEWS) {
activityReference.get().updateProgressViews();
sendEmptyMessageDelayed(CMD_UPDATE_PROGRESS_VIEWS, PROGRESS_VIEW_UPDATE_INTERVAL);
}
}
}
}

View file

@ -54,8 +54,8 @@ public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity impleme
@Override
protected void onCreate(Bundle savedInstanceState) {
setStatusBarTransparent();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_playlist_detail);
ButterKnife.bind(this);
getIntentExtras();
@ -71,6 +71,11 @@ public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity impleme
setStatusBarThemeColor();
}
@Override
protected View createContentView() {
return wrapSlidingMusicPanelAndFab(R.layout.activity_playlist_detail);
}
private void setUpRecyclerView() {
recyclerView.setLayoutManager(new GridLayoutManager(this, 1));
if (playlist instanceof AbsSmartPlaylist) {
@ -168,12 +173,6 @@ public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity impleme
case android.R.id.home:
onBackPressed();
return true;
case R.id.action_now_playing:
NavigationUtil.openCurrentPlayingIfPossible(this, getSharedViewsWithPlayPauseFab(null));
return true;
case R.id.action_playing_queue:
NavigationUtil.openPlayingQueueDialog(this);
return true;
}
return super.onOptionsItemSelected(item);
}

View file

@ -46,6 +46,7 @@ public class SearchActivity extends AbsMusicStateActivity {
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
setStatusBarTransparent();
setTitle(null);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
@ -71,7 +72,8 @@ public class SearchActivity extends AbsMusicStateActivity {
//noinspection ConstantConditions
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
setNavigationBarThemeColor();
if (shouldColorNavigationBar())
setNavigationBarThemeColor();
setStatusBarThemeColor();
}

View file

@ -29,6 +29,7 @@ public class SettingsActivity extends AbsBaseActivity implements ColorChooserDia
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
setStatusBarTransparent();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_preferences);

View file

@ -47,6 +47,8 @@ public abstract class AbsMusicStateActivity extends AbsBaseActivity implements S
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
onPlayStateChanged();
onRepeatModeChanged();
onShuffleModeChanged();
onPlayingMetaChanged();
}

View file

@ -1,64 +1,223 @@
package com.kabouzeid.gramophone.ui.activities.base;
import android.animation.Animator;
import android.annotation.SuppressLint;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.util.Pair;
import android.util.Log;
import android.support.v7.graphics.Palette;
import android.support.v7.widget.CardView;
import android.support.v7.widget.Toolbar;
import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
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 android.widget.Toast;
import com.afollestad.materialdialogs.ThemeSingleton;
import com.afollestad.materialdialogs.util.DialogUtils;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.kabouzeid.gramophone.misc.SmallOnGestureListener;
import com.kabouzeid.gramophone.imageloader.BlurProcessor;
import com.kabouzeid.gramophone.misc.SimpleOnSeekbarChangeListener;
import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.service.MusicService;
import com.kabouzeid.gramophone.util.ColorUtil;
import com.kabouzeid.gramophone.util.NavigationUtil;
import com.kabouzeid.gramophone.util.MusicUtil;
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.listener.SimpleImageLoadingListener;
import com.sothree.slidinguppanel.SlidingUpPanelLayout;
import java.lang.ref.WeakReference;
import butterknife.Bind;
import butterknife.ButterKnife;
/**
* @author Karim Abou Zeid (kabouzeid)
* <p/>
* Do not use {@link #setContentView(int)} but wrap your layout with
* {@link #wrapSlidingMusicPanelAndFab(int)} first and then return it in {@link #createContentView()}
*/
public abstract class AbsSlidingMusicPanelActivity extends AbsMusicStateActivity {
public abstract class AbsSlidingMusicPanelActivity extends AbsMusicStateActivity implements SlidingUpPanelLayout.PanelSlideListener {
public static final String TAG = AbsSlidingMusicPanelActivity.class.getSimpleName();
private static final int FAB_CIRCULAR_REVEAL_ANIMATION_TIME = 1000;
private static final long DEFAULT_PROGRESS_VIEW_REFRESH_INTERVAL = 500;
private static final int CMD_REFRESH_PROGRESS_VIEWS = 1;
@Bind(R.id.play_pause_fab)
FloatingActionButton playPauseFab;
@Bind(R.id.sliding_layout)
SlidingUpPanelLayout slidingUpPanelLayout;
@Bind(R.id.mini_player)
FrameLayout miniPlayer;
@Bind(R.id.mini_player_title)
TextView miniPlayerTitle;
@Bind(R.id.mini_player_image)
ImageView miniPlayerImage;
@Bind(R.id.player_dummy_fab)
View dummyFab;
@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_footer_frame)
LinearLayout footerFrame;
@Bind(R.id.player_album_art_background)
ImageView albumArtBackground;
@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;
TextView songCurrentProgress;
TextView songTotalTime;
SeekBar seekBar;
private int lastFooterColor = -1;
private int lastTitleTextColor = -2;
private int lastCaptionTextColor = -2;
private Handler progressViewsUpdateHandler;
private boolean opaqueStatusBar;
private boolean opaqueToolBar;
private boolean forceSquareAlbumArt;
private boolean largerTitleBox;
private boolean alternativeProgressSlider;
private boolean showPlaybackControllerCard;
private Song song;
private PlayPauseDrawable playPauseDrawable;
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(createContentView());
ButterKnife.bind(this);
setUpPlayPauseButton();
setUpMiniPlayer();
setUpSlidingPanel();
initAppearanceVarsFromSharedPrefs();
initProgressSliderDependentViews();
moveSeekBarIntoPlace();
adjustTitleBoxSize();
setUpPlaybackControllerCard();
setUpMusicControllers();
setUpAlbumArtViews();
setUpPlayerToolbar();
progressViewsUpdateHandler = new MusicProgressViewsUpdateHandler(this);
}
protected abstract View createContentView();
@Override
protected void onResume() {
super.onResume();
if (slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
startUpdatingProgressViews();
}
}
@Override
protected void onPause() {
super.onPause();
stopUpdatingProgressViews();
}
@Override
public void onPlayingMetaChanged() {
super.onPlayingMetaChanged();
updateCurrentSong();
}
@Override
public void onRepeatModeChanged() {
super.onRepeatModeChanged();
updateRepeatState();
}
@Override
public void onShuffleModeChanged() {
super.onShuffleModeChanged();
updateShuffleState();
}
private void setUpPlayPauseButton() {
updateFabState(false);
getPlayPauseFab().setImageDrawable(playPauseDrawable);
playPauseFab.setImageDrawable(playPauseDrawable);
final int accentColor = ThemeSingleton.get().positiveColor;
getPlayPauseFab().setBackgroundTintList(ColorUtil.getEmptyColorStateList(accentColor));
playPauseFab.setBackgroundTintList(ColorUtil.getEmptyColorStateList(accentColor));
if (accentColor == Color.WHITE) {
getPlayPauseFab().getDrawable().setColorFilter(Color.BLACK, PorterDuff.Mode.SRC_IN);
playPauseFab.getDrawable().setColorFilter(Color.BLACK, PorterDuff.Mode.SRC_IN);
} else {
getPlayPauseFab().getDrawable().clearColorFilter();
playPauseFab.getDrawable().clearColorFilter();
}
final GestureDetector gestureDetector = new GestureDetector(this, new SmallOnGestureListener() {
final GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
NavigationUtil.openCurrentPlayingIfPossible(AbsSlidingMusicPanelActivity.this, getSharedViewsWithPlayPauseFab(null));
toggleSlidingPanel();
return true;
}
});
getPlayPauseFab().setOnClickListener(new View.OnClickListener() {
playPauseFab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (MusicPlayerRemote.getPosition() != -1) {
@ -73,26 +232,129 @@ public abstract class AbsSlidingMusicPanelActivity extends AbsMusicStateActivity
}
});
getPlayPauseFab().setOnTouchListener(new View.OnTouchListener() {
playPauseFab.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, @NonNull MotionEvent event) {
gestureDetector.onTouchEvent(event);
return false;
}
});
}
getPlayPauseFab().setOnLongClickListener(new View.OnLongClickListener() {
private void setUpMiniPlayer() {
final GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onLongClick(View view) {
final Song song = MusicPlayerRemote.getCurrentSong();
if (song.id != -1) {
Toast.makeText(AbsSlidingMusicPanelActivity.this, song.title + " - " + song.artistName, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(AbsSlidingMusicPanelActivity.this, getResources().getString(R.string.nothing_playing), Toast.LENGTH_SHORT).show();
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.back();
return true;
}
}
return true;
return false;
}
});
miniPlayer.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
});
miniPlayer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toggleSlidingPanel();
}
});
setMiniPlayerColor(ColorUtil.resolveColor(this, R.attr.card_color));
miniPlayerImage.setImageResource(R.drawable.ic_equalizer_white_24dp);
miniPlayerImage.setColorFilter(ColorUtil.resolveColor(this, R.attr.themed_drawable_color));
}
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);
}
slidingUpPanelLayout.setPanelSlideListener(this);
}
@Override
public void onPanelSlide(View view, float slideOffset) {
miniPlayer.setAlpha(1 - slideOffset);
float xTranslation = (dummyFab.getX() + mediaControllerContainer.getX() + footerFrame.getX() - playPauseFab.getLeft()) * slideOffset;
float yTranslation = (dummyFab.getY() + mediaControllerContainer.getY() + footerFrame.getY() - playPauseFab.getTop()) * slideOffset;
playPauseFab.setTranslationX(xTranslation);
playPauseFab.setTranslationY(yTranslation);
if (slideOffset > 0 && !progressViewsUpdateHandler.hasMessages(CMD_REFRESH_PROGRESS_VIEWS)) {
startUpdatingProgressViews();
}
}
@Override
public void onPanelCollapsed(View view) {
stopUpdatingProgressViews();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mediaControllerContainer.setVisibility(View.INVISIBLE);
}
}
@Override
public void onPanelExpanded(View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (mediaControllerContainer.getVisibility() == View.INVISIBLE) {
int cx = (dummyFab.getLeft() + dummyFab.getRight()) / 2;
int cy = (dummyFab.getTop() + dummyFab.getBottom()) / 2;
int finalRadius = Math.max(mediaControllerContainer.getWidth(), mediaControllerContainer.getHeight());
Animator animator = ViewAnimationUtils.createCircularReveal(mediaControllerContainer, cx, cy, dummyFab.getWidth() / 2, finalRadius);
animator.setInterpolator(new DecelerateInterpolator());
animator.setDuration(FAB_CIRCULAR_REVEAL_ANIMATION_TIME);
animator.start();
mediaControllerContainer.setVisibility(View.VISIBLE);
}
}
}
@Override
public void onPanelAnchored(View view) {
}
@Override
public void onPanelHidden(View view) {
}
private void toggleSlidingPanel() {
if (slidingUpPanelLayout.getPanelState() != SlidingUpPanelLayout.PanelState.EXPANDED) {
slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED);
} else {
slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
}
}
public FloatingActionButton getPlayPauseFab() {
return playPauseFab;
}
public SlidingUpPanelLayout getSlidingUpPanelLayout() {
return slidingUpPanelLayout;
}
protected void updateFabState(boolean animate) {
@ -106,19 +368,7 @@ public abstract class AbsSlidingMusicPanelActivity extends AbsMusicStateActivity
}
}
@NonNull
protected FloatingActionButton getPlayPauseFab() {
if (playPauseFab == null) {
playPauseFab = (FloatingActionButton) findViewById(R.id.play_pause_fab);
if (playPauseFab == null) {
playPauseFab = new FloatingActionButton(this);
Log.e(TAG, "PlayPauseFAB not found, created default FAB.");
}
}
return playPauseFab;
}
public Pair[] getSharedViewsWithPlayPauseFab(@Nullable Pair[] sharedViews) {
public Pair[] addPlayPauseFabToSharedViews(@Nullable Pair[] sharedViews) {
Pair[] sharedViewsWithFab;
if (sharedViews != null) {
sharedViewsWithFab = new Pair[sharedViews.length + 1];
@ -126,7 +376,7 @@ public abstract class AbsSlidingMusicPanelActivity extends AbsMusicStateActivity
} else {
sharedViewsWithFab = new Pair[1];
}
sharedViewsWithFab[sharedViewsWithFab.length - 1] = Pair.create((View) getPlayPauseFab(), getString(R.string.transition_fab));
sharedViewsWithFab[sharedViewsWithFab.length - 1] = Pair.create((View) playPauseFab, getString(R.string.transition_fab));
return sharedViewsWithFab;
}
@ -135,4 +385,509 @@ public abstract class AbsSlidingMusicPanelActivity extends AbsMusicStateActivity
super.onPlayStateChanged();
updateFabState(true);
}
protected View wrapSlidingMusicPanelAndFab(@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);
getLayoutInflater().inflate(resId, contentContainer);
return slidingMusicPanelLayout;
}
@Override
public void onBackPressed() {
if (slidingUpPanelLayout.getPanelState() != SlidingUpPanelLayout.PanelState.COLLAPSED) {
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();
}
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);
seekBar = (SeekBar) findViewById(R.id.player_alternative_progress_slider);
} else {
songCurrentProgress = (TextView) findViewById(R.id.player_default_song_current_progress);
songTotalTime = (TextView) findViewById(R.id.player_default_song_total_time);
seekBar = (SeekBar) findViewById(R.id.player_default_progress_slider);
}
}
private void moveSeekBarIntoPlace() {
if (!alternativeProgressSlider) {
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) seekBar.getLayoutParams();
seekBar.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
final int seekBarMarginLeftRight = getResources().getDimensionPixelSize(R.dimen.seek_bar_margin_left_right);
lp.setMargins(seekBarMarginLeftRight, 0, seekBarMarginLeftRight, -(seekBar.getMeasuredHeight() / 2));
seekBar.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);
mediaControllerContainer.setBackgroundColor(showPlaybackControllerCard ? Color.TRANSPARENT : ColorUtil.resolveColor(this, R.attr.music_controller_container_color));
}
private void setUpMusicControllers() {
setUpPrevNext();
setUpRepeatButton();
setUpShuffleButton();
setUpSeekBar();
}
private void setTint(@NonNull SeekBar seekBar, int color) {
ColorStateList s1 = ColorStateList.valueOf(color);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
seekBar.setThumbTintList(s1);
if (!alternativeProgressSlider) seekBar.setProgressTintList(s1);
} else {
seekBar.getThumb().setColorFilter(color, PorterDuff.Mode.SRC_IN);
if (!alternativeProgressSlider)
seekBar.getProgressDrawable().setColorFilter(color, PorterDuff.Mode.SRC_IN);
}
}
private void setUpSeekBar() {
setTint(seekBar, !ThemeSingleton.get().darkTheme && getThemeColorAccent() == Color.WHITE ? Color.BLACK : getThemeColorAccent());
seekBar.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, R.attr.themed_drawable_color);
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,
getThemeColorAccent() == Color.WHITE ? Color.BLACK : getThemeColorAccent()));
break;
default:
shuffleButton.setImageDrawable(Util.getTintedDrawable(this, R.drawable.ic_shuffle_white_36dp,
DialogUtils.resolveColor(this, R.attr.themed_drawable_color)));
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_NONE:
repeatButton.setImageDrawable(Util.getTintedDrawable(this, R.drawable.ic_repeat_white_36dp,
DialogUtils.resolveColor(this, R.attr.themed_drawable_color)));
break;
case MusicService.REPEAT_MODE_ALL:
repeatButton.setImageDrawable(Util.getTintedDrawable(this, R.drawable.ic_repeat_white_36dp,
getThemeColorAccent() == Color.WHITE ? Color.BLACK : getThemeColorAccent()));
break;
default:
repeatButton.setImageDrawable(Util.getTintedDrawable(this, R.drawable.ic_repeat_one_white_36dp,
getThemeColorAccent() == Color.WHITE ? Color.BLACK : getThemeColorAccent()));
break;
}
}
private void setUpAlbumArtViews() {
albumArtBackground.setAlpha(0.7f);
albumArt.forceSquare(forceSquareAlbumArt);
if (opaqueStatusBar) {
if (opaqueToolBar) {
alignAlbumArtToToolbar();
} else {
alignAlbumArtToStatusBar();
}
} else {
alignAlbumArtToTop();
}
}
private void alignAlbumArtToTop() {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) findViewById(R.id.player_album_art_frame).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) findViewById(R.id.player_album_art_frame).getLayoutParams();
params.addRule(RelativeLayout.BELOW, R.id.player_toolbar);
}
private void alignAlbumArtToStatusBar() {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) findViewById(R.id.player_album_art_frame).getLayoutParams();
params.addRule(RelativeLayout.BELOW, R.id.player_status_bar);
}
private void setUpPlayerToolbar() {
// TODO setUpPlayerToolbar
}
private void updateCurrentSong() {
getCurrentSong();
updateMiniPlayerAndHeaderText();
setUpAlbumArtAndApplyPalette();
// TODO invalidateOptionsMenu() for the custom player menu
}
private void getCurrentSong() {
song = MusicPlayerRemote.getCurrentSong();
if (song.id == -1) {
// TODO disable and hide sliding panel & fab
} else {
// TODO enable and show sliding panel & fab
}
}
private void updateMiniPlayerAndHeaderText() {
songTitle.setText(song.title);
songText.setText(song.artistName);
miniPlayerTitle.setText(song.title);
}
private void setUpAlbumArtAndApplyPalette() {
ImageLoader.getInstance().displayImage(
MusicUtil.getSongImageLoaderString(song),
albumArt,
new DisplayImageOptions.Builder()
.cacheInMemory(true)
.showImageOnFail(R.drawable.default_album_art)
.build(),
new SimpleImageLoadingListener() {
@Override
public void onLoadingFailed(String imageUri, View view, @Nullable FailReason failReason) {
applyPalette(null);
ImageLoader.getInstance().displayImage(
"drawable://" + R.drawable.default_album_art,
albumArtBackground,
new DisplayImageOptions.Builder().postProcessor(new BlurProcessor(10)).build()
);
}
@Override
public void onLoadingComplete(String imageUri, View view, @Nullable Bitmap loadedImage) {
if (loadedImage == null) {
onLoadingFailed(imageUri, view, null);
return;
}
applyPalette(loadedImage);
ImageLoader.getInstance().displayImage(
imageUri,
albumArtBackground,
new DisplayImageOptions.Builder().postProcessor(new BlurProcessor(10)).build()
);
}
}
);
}
private void applyPalette(@Nullable Bitmap bitmap) {
final int defaultBarColor = ColorUtil.resolveColor(this, R.attr.default_bar_color);
if (bitmap != null) {
Palette.from(bitmap)
.resizeBitmapSize(100)
.generate(new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(@NonNull Palette palette) {
setColors(palette.getVibrantColor(defaultBarColor));
}
});
} else {
setColors(defaultBarColor);
}
}
private void setColors(int color) {
animateColorChange(color);
animateTextColorChange(ColorUtil.getPrimaryTextColorForBackground(this, color), ColorUtil.getSecondaryTextColorForBackground(this, color));
}
private void animateColorChange(final int newColor) {
if (lastFooterColor != -1 && lastFooterColor != newColor) {
ViewUtil.animateViewColor(footer, lastFooterColor, newColor);
if (opaqueToolBar) {
ViewUtil.animateViewColor(playerToolbar, lastFooterColor, newColor);
} else {
playerToolbar.setBackgroundColor(Color.TRANSPARENT);
}
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);
}
ViewUtil.animateViewColor(playerStatusbar, oldStatusbarColor, newStatusbarColor);
} else {
playerStatusbar.setBackgroundColor(Color.TRANSPARENT);
}
} else {
footer.setBackgroundColor(newColor);
if (opaqueToolBar) {
playerToolbar.setBackgroundColor(newColor);
} else {
playerToolbar.setBackgroundColor(Color.TRANSPARENT);
}
if (opaqueStatusBar) {
int newStatusbarColor = newColor;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
newStatusbarColor = ColorUtil.shiftColorDown(newColor);
}
playerStatusbar.setBackgroundColor(newStatusbarColor);
} else {
playerStatusbar.setBackgroundColor(Color.TRANSPARENT);
}
}
if (shouldColorNavigationBar())
setNavigationBarColor(newColor);
lastFooterColor = newColor;
}
private void animateTextColorChange(int titleTextColor, int captionTextColor) {
if (lastTitleTextColor != -2 && lastTitleTextColor != titleTextColor) {
ViewUtil.animateTextColor(songTitle, lastTitleTextColor, titleTextColor);
} else {
songTitle.setTextColor(titleTextColor);
}
if (lastCaptionTextColor != -2 && lastCaptionTextColor != captionTextColor) {
ViewUtil.animateTextColor(songText, lastCaptionTextColor, captionTextColor);
} else {
songText.setTextColor(captionTextColor);
}
lastTitleTextColor = titleTextColor;
lastCaptionTextColor = captionTextColor;
}
private void startUpdatingProgressViews() {
queueNextRefresh(0);
}
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();
seekBar.setMax(totalMillis);
seekBar.setProgress(progressMillis);
songCurrentProgress.setText(MusicUtil.getReadableDurationString(progressMillis));
songTotalTime.setText(MusicUtil.getReadableDurationString(totalMillis));
if (!MusicPlayerRemote.isPlaying()) {
return DEFAULT_PROGRESS_VIEW_REFRESH_INTERVAL;
}
// 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<AbsSlidingMusicPanelActivity> 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) {
activityReference.get().queueNextRefresh(activityReference.get().refreshProgressViews());
}
}
}
// TODO use this for the custom player menu
// @Override
// public boolean onCreateOptionsMenu(@NonNull Menu menu) {
// getMenuInflater().inflate(R.menu.menu_player, menu);
// boolean isFavorite = MusicUtil.isFavorite(this, song);
// menu.findItem(R.id.action_toggle_favorite)
// .setIcon(isFavorite ? R.drawable.ic_favorite_white_24dp : R.drawable.ic_favorite_outline_white_24dp)
// .setTitle(isFavorite ? getString(R.string.action_remove_from_favorites) : getString(R.string.action_add_to_favorites));
// return true;
// }
//
// @Override
// public boolean onOptionsItemSelected(@NonNull MenuItem item) {
// int id = item.getItemId();
// switch (id) {
// 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();
// }
// invalidateOptionsMenu();
// 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 android.R.id.home:
// super.onBackPressed();
// 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, addPlayPauseFabToSharedViews(null));
// return true;
// case R.id.action_go_to_artist:
// NavigationUtil.goToArtist(this, song.artistId, addPlayPauseFabToSharedViews(null));
// return true;
// }
//
// return super.onOptionsItemSelected(item);
// }
//
// 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();
// }
}

View file

@ -3,6 +3,7 @@ package com.kabouzeid.gramophone.ui.activities.base;
import android.app.ActivityManager;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.ColorInt;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
@ -72,7 +73,7 @@ public abstract class AbsThemeActivity extends AppCompatActivity implements KabV
darkTheme != (PreferenceUtil.getInstance(this).getGeneralTheme() == R.style.Theme_MaterialMusic);
}
protected void notifyTaskColorChange(int color) {
protected void notifyTaskColorChange(@ColorInt int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// Sets color of entry in the system recents page
if (taskDescription == null || taskDescription.getPrimaryColor() != color) {
@ -108,18 +109,29 @@ public abstract class AbsThemeActivity extends AppCompatActivity implements KabV
Util.setStatusBarTranslucent(getWindow());
}
protected final void setNavigationBarColor(int color) {
protected final void setNavigationBarColor(@ColorInt int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
getWindow().setNavigationBarColor(ColorUtil.shiftColorDown(color));
}
protected final void setStatusBarColor(int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
getWindow().setStatusBarColor(ColorUtil.shiftColorDown(color));
// also do this on Lollipop in case the user modified the statusbar height
/**
* This will set the color of the view with the id "status_bar" on KitKat and Lollipop.
* On Lollipop if no such view is found it will set the statusbar color using the native method.
*
* @param color the new statusbar color (will be shifted down on Lollipop and above)
*/
protected final void setStatusBarColor(@ColorInt int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
final View statusBar = getWindow().getDecorView().getRootView().findViewById(R.id.status_bar);
if (statusBar != null) statusBar.setBackgroundColor(color);
if (statusBar != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
statusBar.setBackgroundColor(ColorUtil.shiftColorDown(color));
} else {
statusBar.setBackgroundColor(color);
}
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setStatusBarColor(ColorUtil.shiftColorDown(color));
}
}
}

View file

@ -26,7 +26,7 @@ import com.afollestad.materialdialogs.ThemeSingleton;
import com.afollestad.materialdialogs.util.DialogUtils;
import com.github.ksoichiro.android.observablescrollview.ObservableScrollView;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.misc.SmallObservableScrollViewCallbacks;
import com.kabouzeid.gramophone.misc.SimpleObservableScrollViewCallbacks;
import com.kabouzeid.gramophone.ui.activities.base.AbsBaseActivity;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.Util;
@ -116,7 +116,7 @@ public abstract class AbsTagEditorActivity extends AbsBaseActivity {
observableScrollView.setScrollViewCallbacks(observableScrollViewCallbacks);
}
private final SmallObservableScrollViewCallbacks observableScrollViewCallbacks = new SmallObservableScrollViewCallbacks() {
private final SimpleObservableScrollViewCallbacks observableScrollViewCallbacks = new SimpleObservableScrollViewCallbacks() {
@Override
public void onScrollChanged(int scrollY, boolean b, boolean b2) {
float alpha;

View file

@ -35,14 +35,14 @@ public class ColorUtil {
return color | 0xFF000000;
}
public static int getColorWithAlpha(float alpha, int baseColor) {
public static int getColorWithAlpha(float alpha, @ColorInt int baseColor) {
int a = Math.min(255, Math.max(0, (int) (alpha * 255))) << 24;
int rgb = 0x00ffffff & baseColor;
return a + rgb;
}
@SuppressWarnings("ResourceType")
public static int shiftColorDown(int color) {
public static int shiftColorDown(@ColorInt int color) {
int alpha = Color.alpha(color);
float[] hsv = new float[3];
Color.colorToHSV(color, hsv);
@ -51,7 +51,7 @@ public class ColorUtil {
}
@NonNull
public static ColorStateList getEmptyColorStateList(int color) {
public static ColorStateList getEmptyColorStateList(@ColorInt int color) {
return new ColorStateList(
new int[][]{
new int[]{}
@ -60,11 +60,15 @@ public class ColorUtil {
);
}
public static boolean useDarkTextColorOnBackground(int backgroundColor) {
public static boolean useDarkTextColorOnBackground(@ColorInt int backgroundColor) {
return (Color.red(backgroundColor) * 0.299 + Color.green(backgroundColor) * 0.587 + Color.blue(backgroundColor) * 0.114) > (255 / 2);
}
public static int getTextColorForBackground(int backgroundColor) {
return useDarkTextColorOnBackground(backgroundColor) ? Color.BLACK : Color.WHITE;
public static int getPrimaryTextColorForBackground(final Context context, @ColorInt int backgroundColor) {
return useDarkTextColorOnBackground(backgroundColor) ? context.getResources().getColor(R.color.primary_text_default_material_light) : context.getResources().getColor(R.color.primary_text_default_material_dark);
}
public static int getSecondaryTextColorForBackground(final Context context, @ColorInt int backgroundColor) {
return useDarkTextColorOnBackground(backgroundColor) ? context.getResources().getColor(R.color.secondary_text_default_material_light) : context.getResources().getColor(R.color.secondary_text_default_material_dark);
}
}

View file

@ -19,7 +19,6 @@ import com.kabouzeid.gramophone.interfaces.KabViewsDisableAble;
import com.kabouzeid.gramophone.model.Playlist;
import com.kabouzeid.gramophone.ui.activities.AlbumDetailActivity;
import com.kabouzeid.gramophone.ui.activities.ArtistDetailActivity;
import com.kabouzeid.gramophone.ui.activities.MusicControllerActivity;
import com.kabouzeid.gramophone.ui.activities.PlaylistDetailActivity;
/**
@ -85,30 +84,6 @@ public class NavigationUtil {
}
}
public static void openCurrentPlayingIfPossible(final Activity activity, @Nullable final Pair[] sharedViews) {
if (activity instanceof MusicControllerActivity) {
activity.onBackPressed();
return;
}
if (MusicPlayerRemote.getPosition() != -1) {
if ((activity instanceof KabViewsDisableAble && ((KabViewsDisableAble) activity).areViewsEnabled()) || !(activity instanceof KabViewsDisableAble)) {
if (activity instanceof KabViewsDisableAble)
((KabViewsDisableAble) activity).disableViews();
Intent intent = new Intent(activity, MusicControllerActivity.class);
if (sharedViews != null) {
@SuppressWarnings("unchecked") ActivityOptionsCompat optionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(activity,
sharedViews
);
ActivityCompat.startActivity(activity, intent, optionsCompat.toBundle());
} else {
activity.startActivity(intent);
}
}
} else {
Toast.makeText(activity, activity.getResources().getString(R.string.playing_queue_empty), Toast.LENGTH_SHORT).show();
}
}
public static void openPlayingQueueDialog(@NonNull final AppCompatActivity activity) {
PlayingQueueDialog dialog = PlayingQueueDialog.create();
if (dialog != null) {