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

@ -87,6 +87,7 @@ dependencies {
compile 'com.github.ksoichiro:android-observablescrollview:1.5.1'
compile 'asia.ivity.android:drag-sort-listview:1.0'
compile 'com.github.semoncat.seekarc:library:0.1'
compile 'com.sothree.slidinguppanel:library:3.0.0'
compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'com.squareup.okhttp:okhttp:2.4.0'

View file

@ -93,9 +93,6 @@
</activity>
<activity android:name=".ui.activities.AlbumDetailActivity" />
<activity android:name=".ui.activities.ArtistDetailActivity" />
<activity
android:name=".ui.activities.MusicControllerActivity"
android:parentActivityName=".ui.activities.MainActivity" />
<service
android:name=".service.MusicService"

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

View file

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
@ -80,7 +81,9 @@
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:elevation="@dimen/toolbar_elevation"
tools:ignore="UnusedAttribute">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
@ -96,10 +99,4 @@
</LinearLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/play_pause_fab"
style="@style/PlayPauseFab"
android:layout_gravity="end|right|bottom"
android:layout_margin="@dimen/fab_margin" />
</FrameLayout>

View file

@ -146,7 +146,7 @@
android:id="@+id/play_pause_fab"
style="@style/PlayPauseFab"
android:layout_gravity="bottom|right|end"
android:layout_margin="@dimen/fab_margin"
android:layout_margin="@dimen/fab_margin_top_left_right"
android:src="@drawable/ic_done_white_24dp"
tools:ignore="RtlHardcoded" />

View file

@ -81,7 +81,9 @@
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:elevation="@dimen/toolbar_elevation"
tools:ignore="UnusedAttribute">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
@ -97,10 +99,4 @@
</LinearLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/play_pause_fab"
style="@style/PlayPauseFab"
android:layout_gravity="end|bottom"
android:layout_margin="@dimen/fab_margin" />
</FrameLayout>

View file

@ -1,11 +1,19 @@
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".DrawerActivity">
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="0dp"
tools:ignore="UnusedAttribute">
<include layout="@layout/status_bar" />
</FrameLayout>
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
@ -15,7 +23,6 @@
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
tools:ignore="UnusedAttribute">
<FrameLayout
@ -43,8 +50,10 @@
android:layout_width="match_parent"
android:layout_height="@dimen/tab_height"
app:tabContentStart="72dp"
app:tabIndicatorColor="@color/white"
app:tabMode="scrollable" />
app:tabIndicatorColor="@color/primary_text_default_material_dark"
app:tabMode="scrollable"
app:tabSelectedTextColor="@color/primary_text_default_material_dark"
app:tabTextColor="@color/secondary_text_default_material_dark" />
</android.support.design.widget.AppBarLayout>
@ -54,20 +63,6 @@
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/play_pause_fab"
style="@style/PlayPauseFab"
android:layout_gravity="end|bottom"
android:layout_margin="@dimen/fab_margin" />
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="@+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:menu="@menu/menu_drawer" />
</android.support.v4.widget.DrawerLayout>
</LinearLayout>

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.internal.ScrimInsetsFrameLayout
android:fitsSystemWindows="true"
android:id="@+id/drawer_content_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="@+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="@menu/menu_drawer" />
</android.support.v4.widget.DrawerLayout>

View file

@ -1,4 +1,5 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
@ -7,9 +8,13 @@
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/status_bar" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:elevation="@dimen/toolbar_elevation"
tools:ignore="UnusedAttribute">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
@ -45,10 +50,4 @@
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/empty_text_size" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/play_pause_fab"
style="@style/PlayPauseFab"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin" />
</FrameLayout>

View file

@ -1,15 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:fitsSystemWindows="true"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/status_bar" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
style="@style/Toolbar"
android:background="?colorPrimary" />
android:background="@android:color/transparent" />
<FrameLayout
android:id="@+id/content_frame"

View file

@ -1,13 +1,13 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/status_bar" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
style="@style/Toolbar"
app:elevation="@dimen/toolbar_elevation" />
style="@style/Toolbar" />
<FrameLayout
android:layout_width="match_parent"

View file

@ -177,7 +177,7 @@
android:id="@+id/play_pause_fab"
style="@style/PlayPauseFab"
android:layout_gravity="bottom|right|end"
android:layout_margin="@dimen/fab_margin"
android:layout_margin="@dimen/fab_margin_top_left_right"
android:src="@drawable/ic_done_white_24dp"
tools:ignore="RtlHardcoded" />

View file

@ -43,7 +43,6 @@
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
android:textColor="?caption_text_color" />

View file

@ -48,7 +48,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
android:textColor="?caption_text_color"
android:textSize="12sp" />

View file

@ -46,6 +46,8 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:orientation="vertical">
@ -74,6 +76,8 @@
style="@style/OverFlowButton"
android:layout_gravity="center_vertical"
android:layout_marginEnd="2dp"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp"
android:layout_marginStart="2dp"
tools:ignore="ContentDescription" />

View file

@ -48,6 +48,8 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:fontFamily="sans-serif"
@ -60,6 +62,8 @@
style="@style/OverFlowButton"
android:layout_gravity="center_vertical"
android:layout_marginEnd="2dp"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp"
android:layout_marginStart="2dp"
tools:ignore="ContentDescription" />

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mini_player"
android:layout_width="match_parent"
android:layout_height="@dimen/mini_player_height"
android:background="?android:colorBackground">
<ImageView
android:id="@+id/mini_player_image"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:scaleType="centerCrop"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/mini_player_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginEnd="88dp"
android:layout_marginLeft="72dp"
android:layout_marginRight="88dp"
android:layout_marginStart="72dp"
android:gravity="center_vertical"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
</FrameLayout>

View file

@ -1,15 +1,13 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.kabouzeid.gramophone.ui.activities.MusicControllerActivity">
android:layout_height="match_parent">
<!-- BOTTOM-->
<LinearLayout
android:id="@+id/footer_frame"
android:id="@+id/player_footer_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
@ -17,7 +15,7 @@
android:orientation="vertical">
<RelativeLayout
android:id="@+id/alternative_progress_container"
android:id="@+id/player_alternative_progress_container"
android:layout_width="match_parent"
android:layout_height="@dimen/progress_container_height"
android:background="?music_controller_container_color"
@ -26,7 +24,7 @@
tools:ignore="UnusedAttribute">
<TextView
android:id="@+id/alternative_song_current_progress"
android:id="@+id/player_alternative_song_current_progress"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
@ -40,7 +38,7 @@
tools:ignore="RtlHardcoded,RtlSymmetry,SmallSp" />
<TextView
android:id="@+id/alternative_song_total_time"
android:id="@+id/player_alternative_song_total_time"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
@ -54,17 +52,17 @@
tools:ignore="RtlHardcoded,RtlSymmetry,SmallSp" />
<SeekBar
android:id="@+id/alternative_progress_slider"
android:id="@+id/player_alternative_progress_slider"
style="@style/MusicProgressSlider"
android:layout_height="match_parent"
android:layout_toLeftOf="@id/alternative_song_total_time"
android:layout_toRightOf="@id/alternative_song_current_progress"
android:layout_toLeftOf="@id/player_alternative_song_total_time"
android:layout_toRightOf="@id/player_alternative_song_current_progress"
tools:ignore="RtlHardcoded,UnusedAttribute" />
</RelativeLayout>
<LinearLayout
android:id="@+id/footer"
android:id="@+id/player_footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?default_bar_color"
@ -74,11 +72,10 @@
android:paddingLeft="72dp"
android:paddingRight="72dp"
android:paddingTop="@dimen/title_box_padding_large"
android:transitionName="@string/transition_album_art"
tools:ignore="UnusedAttribute">
<TextView
android:id="@+id/title"
android:id="@+id/player_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
@ -87,7 +84,7 @@
android:textColor="?attr/title_text_color" />
<TextView
android:id="@+id/text"
android:id="@+id/player_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif"
@ -98,14 +95,14 @@
</LinearLayout>
<RelativeLayout
android:id="@+id/media_controller_container"
android:id="@+id/player_media_controller_container"
android:layout_width="match_parent"
android:layout_height="@dimen/media_controller_container_height"
android:background="?music_controller_container_color"
tools:ignore="ContentDescription,UnusedAttribute">
<android.support.v7.widget.CardView
android:id="@+id/playback_controller_card"
android:id="@+id/player_playback_controller_card"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
@ -114,14 +111,14 @@
app:elevation="@dimen/card_elevation" />
<ImageButton
android:id="@+id/prev_button"
android:id="@+id/player_prev_button"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_centerVertical="true"
android:layout_marginEnd="@dimen/tmp_now_playing_skip_rewind_margin"
android:layout_marginRight="@dimen/tmp_now_playing_skip_rewind_margin"
android:layout_toLeftOf="@+id/play_pause_fab"
android:layout_toStartOf="@+id/play_pause_fab"
android:layout_toLeftOf="@+id/player_dummy_fab"
android:layout_toStartOf="@+id/player_dummy_fab"
android:background="?round_selector"
android:elevation="8dp"
android:padding="22dp"
@ -129,14 +126,14 @@
android:src="@drawable/ic_skip_previous_white_36dp" />
<ImageButton
android:id="@+id/next_button"
android:id="@+id/player_next_button"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_centerVertical="true"
android:layout_marginLeft="@dimen/tmp_now_playing_skip_rewind_margin"
android:layout_marginStart="@dimen/tmp_now_playing_skip_rewind_margin"
android:layout_toEndOf="@+id/play_pause_fab"
android:layout_toRightOf="@+id/play_pause_fab"
android:layout_toEndOf="@+id/player_dummy_fab"
android:layout_toRightOf="@+id/player_dummy_fab"
android:background="?round_selector"
android:elevation="8dp"
android:padding="22dp"
@ -144,7 +141,7 @@
android:src="@drawable/ic_skip_next_white_36dp" />
<ImageButton
android:id="@+id/repeat_button"
android:id="@+id/player_repeat_button"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_alignParentLeft="true"
@ -159,7 +156,7 @@
android:src="@drawable/ic_repeat_white_36dp" />
<ImageButton
android:id="@+id/shuffle_button"
android:id="@+id/player_shuffle_button"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_alignParentEnd="true"
@ -174,10 +171,11 @@
android:src="@drawable/ic_shuffle_white_36dp" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/play_pause_fab"
android:id="@+id/player_dummy_fab"
style="@style/PlayPauseFab"
android:layout_centerInParent="true"
android:layout_margin="0dp" />
android:layout_margin="0dp"
android:visibility="invisible" />
</RelativeLayout>
@ -186,31 +184,30 @@
<!-- ALBUMART-->
<FrameLayout
android:id="@+id/album_art_frame"
android:id="@+id/player_album_art_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/footer_frame"
android:layout_above="@id/player_footer_frame"
android:background="@color/black">
<ImageView
android:id="@+id/album_art_background"
android:id="@+id/player_album_art_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
tools:ignore="ContentDescription" />
<com.kabouzeid.gramophone.views.SquareIfPlaceImageView
android:id="@+id/image"
android:id="@+id/player_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:scaleType="centerCrop"
android:src="@drawable/default_album_art"
android:transitionName="@string/transition_album_art"
tools:ignore="ContentDescription,UnusedAttribute" />
<ImageView
android:id="@+id/favorite_icon"
android:id="@+id/player_favorite_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
@ -219,14 +216,14 @@
tools:ignore="ContentDescription" />
<RelativeLayout
android:id="@+id/default_progress_container"
android:id="@+id/player_default_progress_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="@drawable/shadow_up">
<TextView
android:id="@+id/default_song_current_progress"
android:id="@+id/player_default_song_current_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
@ -240,7 +237,7 @@
tools:ignore="RtlHardcoded,RtlSymmetry,SmallSp" />
<TextView
android:id="@+id/default_song_total_time"
android:id="@+id/player_default_song_total_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
@ -259,9 +256,9 @@
<!-- PROGRESS SLIDER-->
<SeekBar
android:id="@+id/default_progress_slider"
android:id="@+id/player_default_progress_slider"
style="@style/TraditionalMusicProgressSlider"
android:layout_above="@+id/footer_frame"
android:layout_above="@id/player_footer_frame"
android:elevation="2dp"
tools:ignore="UnusedAttribute" />
@ -269,14 +266,18 @@
<include layout="@layout/shadow_statusbar_actionbar" />
<include
android:id="@+id/status_bar"
layout="@layout/status_bar" />
<View
android:id="@+id/player_status_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/status_bar_padding"
android:background="@android:color/transparent"
android:elevation="@dimen/toolbar_elevation" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:id="@+id/player_toolbar"
style="@style/Toolbar"
android:layout_below="@id/status_bar"
android:background="#00000000" />
android:layout_below="@id/player_status_bar"
android:background="#00000000"
tools:ignore="UnusedAttribute" />
</RelativeLayout>

View file

@ -0,0 +1,43 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:sothree="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.sothree.slidinguppanel.SlidingUpPanelLayout
android:id="@+id/sliding_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom"
sothree:umanoPanelHeight="@dimen/mini_player_height"
sothree:umanoParalaxOffset="0dp"
sothree:umanoShadowHeight="@dimen/card_elevation">
<FrameLayout
android:id="@+id/content_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<FrameLayout
android:id="@+id/player_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:colorBackground">
<include layout="@layout/player" />
<include layout="@layout/mini_player" />
</FrameLayout>
</com.sothree.slidinguppanel.SlidingUpPanelLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/play_pause_fab"
style="@style/PlayPauseFab"
android:layout_gravity="end|bottom"
android:layout_marginBottom="@dimen/fab_margin_bottom"
android:layout_marginLeft="@dimen/fab_margin_top_left_right"
android:layout_marginRight="@dimen/fab_margin_top_left_right"
android:layout_marginTop="@dimen/fab_margin_top_left_right" />
</FrameLayout>

View file

@ -1,7 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<View
<View xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/status_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/status_bar_padding"
android:background="@android:color/transparent"
xmlns:android="http://schemas.android.com/apk/res/android" />
android:elevation="@dimen/toolbar_elevation"
tools:ignore="UnusedAttribute" />

View file

@ -67,7 +67,8 @@
android:gravity="center_vertical"
android:singleLine="true"
android:text="@string/nothing_playing"
android:textAppearance="@style/Theme.MaterialMusic.Notification.Title" />
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
android:textColor="@color/primary_text_default_material_light" />
<TextView
android:id="@+id/song_secondary_information"
@ -76,7 +77,8 @@
android:layout_weight="1"
android:gravity="center_vertical"
android:singleLine="true"
android:textAppearance="@style/Theme.MaterialMusic.Notification" />
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
android:textColor="@color/secondary_text_default_material_light" />
</LinearLayout>

View file

@ -4,21 +4,10 @@
tools:context="com.kabouzeid.gramophone.ui.activities.AlbumDetailActivity">
<item
android:id="@+id/action_now_playing"
android:icon="@drawable/ic_play_circle_fill_white_24dp"
android:title="@string/action_now_playing"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_playing_queue"
android:icon="@drawable/ic_queue_music_white_24dp"
android:title="@string/action_playing_queue"
app:showAsAction="ifRoom" />
<item
android:icon="@drawable/ic_shuffle_white_24dp"
android:id="@+id/action_shuffle_album"
android:title="@string/action_shuffle_album"
app:showAsAction="never" />
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_go_to_artist"

View file

@ -1,34 +1,23 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.kabouzeid.gramophone.ui.activities.AlbumDetailActivity">
<item
android:id="@+id/action_now_playing"
android:icon="@drawable/ic_play_circle_fill_white_24dp"
android:title="@string/action_now_playing"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/action_playing_queue"
android:icon="@drawable/ic_queue_music_white_24dp"
android:title="@string/action_playing_queue"
app:showAsAction="ifRoom" />
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.kabouzeid.gramophone.ui.activities.AlbumDetailActivity">
<item
android:id="@+id/action_shuffle_artist"
android:icon="@drawable/ic_shuffle_white_24dp"
android:title="@string/action_shuffle_artist"
app:showAsAction="never"/>
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_biography"
android:title="@string/biography"
app:showAsAction="never"/>
app:showAsAction="never" />
<item
android:id="@+id/action_re_download_artist_image"
android:title="@string/action_re_download_artist_image"
app:showAsAction="never"/>
app:showAsAction="never" />
<item
android:id="@+id/action_sleep_timer"
@ -39,6 +28,6 @@
android:id="@+id/action_equalizer"
android:orderInCategory="99"
android:title="@string/equalizer"
app:showAsAction="never"/>
app:showAsAction="never" />
</menu>

View file

@ -9,11 +9,6 @@
android:title="@string/action_search"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_playing_queue"
android:title="@string/action_playing_queue"
app:showAsAction="never" />
<item
android:id="@+id/action_shuffle_all"
android:title="@string/action_shuffle_all"

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_add_to_playlist"

View file

@ -1,7 +1,5 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.kabouzeid.gramophone.ui.activities.MusicControllerActivity">
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_toggle_favorite"

View file

@ -3,22 +3,11 @@
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.kabouzeid.gramophone.ui.activities.PlaylistDetailActivity">
<item
android:id="@+id/action_now_playing"
android:icon="@drawable/ic_play_circle_fill_white_24dp"
android:title="@string/action_now_playing"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_playing_queue"
android:icon="@drawable/ic_queue_music_white_24dp"
android:title="@string/action_playing_queue"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_shuffle_playlist"
android:icon="@drawable/ic_shuffle_white_24dp"
android:title="@string/action_shuffle_playlist"
app:showAsAction="never" />
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_sleep_timer"

View file

@ -3,6 +3,7 @@
<dimen name="status_bar_padding">25dp</dimen>
<dimen name="navigation_drawer_header_height">165dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<dimen name="fab_margin_top_left_right">16dp</dimen>
<dimen name="fab_margin_bottom">20dp</dimen>
<dimen name="tmp_now_playing_skip_rewind_margin">-8dp</dimen>
</resources>

View file

@ -44,7 +44,7 @@ http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout
<dimen name="widget_medium_image_size">96dp</dimen>
<dimen name="notification_big_image_size">128dp</dimen>
<dimen name="bottom_offset_fab_activity">86dp</dimen>
<dimen name="bottom_offset_fab_activity">44dp</dimen>
<dimen name="scrollbar_width">8dp</dimen>
<dimen name="scrollbar_inset">8dp</dimen>
@ -52,7 +52,8 @@ http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout
<dimen name="scrollbar_width_plus_inset">16dp</dimen>
<!-- ONLY 0dp WHILE THERE IS THE BUG IN DESIGN SUPPORT LIBRARY 22.2.0-->
<dimen name="fab_margin">0dp</dimen>
<dimen name="fab_margin_top_left_right">0dp</dimen>
<dimen name="fab_margin_bottom">0dp</dimen>
<dimen name="tmp_now_playing_skip_rewind_margin">-24dp</dimen>
<dimen name="title_box_padding_small">16dp</dimen>
@ -67,4 +68,6 @@ http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout
<!-- For use with 24dp drawables in the item_list layouts-->
<dimen name="list_item_image_icon_padding">8dp</dimen>
<dimen name="mini_player_height">48dp</dimen>
</resources>

View file

@ -41,7 +41,8 @@
</style>
<style name="Toolbar">
<item name="titleMarginStart">16dp</item>
<item name="titleMarginStart">16dp</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">?attr/actionBarSize</item>
<item name="android:theme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>

View file

@ -10,8 +10,8 @@
<item name="md_dark_theme">true</item>
<item name="title_text_color">?android:attr/textColorPrimary</item>
<item name="caption_text_color">?android:attr/textColorSecondary</item>
<item name="title_text_color">@color/primary_text_default_material_dark</item>
<item name="caption_text_color">@color/secondary_text_default_material_dark</item>
<item name="music_controller_container_color">
@color/materialmusic_dark_music_controller_container_color
@ -43,8 +43,8 @@
<item name="md_dark_theme">false</item>
<item name="title_text_color">?android:attr/textColorPrimary</item>
<item name="caption_text_color">?android:attr/textColorSecondary</item>
<item name="title_text_color">@color/primary_text_default_material_light</item>
<item name="caption_text_color">@color/secondary_text_default_material_light</item>
<item name="music_controller_container_color">
@color/materialmusic_music_controller_container_color