From 5f0bfdb14b4cf26475fab2e22f7d56f542d4ca56 Mon Sep 17 00:00:00 2001 From: Karim Abou Zeid Date: Thu, 30 Jul 2015 22:44:34 +0200 Subject: [PATCH] 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 --- app/build.gradle | 1 + app/src/main/AndroidManifest.xml | 3 - .../gramophone/adapter/PlaylistAdapter.java | 7 +- .../adapter/album/AlbumAdapter.java | 7 +- .../adapter/artist/ArtistAdapter.java | 7 +- .../adapter/song/ArtistSongAdapter.java | 5 +- .../song/SmartPlaylistSongAdapter.java | 2 +- .../gramophone/adapter/song/SongAdapter.java | 16 +- .../gramophone/dialogs/SongDetailDialog.java | 30 +- .../gramophone/helper/MusicPlayerRemote.java | 5 +- .../helper/menu/SongMenuHelper.java | 9 +- .../interfaces/MusicStateListener.java | 2 - .../misc/SimpleAnimatorListener.java | 28 + ... SimpleObservableScrollViewCallbacks.java} | 2 +- .../misc/SimpleOnSeekbarChangeListener.java | 23 + ...ner.java => SimpleTransitionListener.java} | 2 +- .../misc/SmallOnGestureListener.java | 39 - .../gramophone/service/MultiPlayer.java | 3 - .../gramophone/service/MusicService.java | 5 +- .../ui/activities/AlbumDetailActivity.java | 30 +- .../ui/activities/ArtistDetailActivity.java | 74 +- .../ui/activities/MainActivity.java | 111 ++- .../activities/MusicControllerActivity.java | 706 --------------- .../ui/activities/PlaylistDetailActivity.java | 13 +- .../ui/activities/SearchActivity.java | 4 +- .../ui/activities/SettingsActivity.java | 1 + .../base/AbsMusicStateActivity.java | 2 + .../base/AbsSlidingMusicPanelActivity.java | 827 +++++++++++++++++- .../ui/activities/base/AbsThemeActivity.java | 26 +- .../tageditor/AbsTagEditorActivity.java | 4 +- .../kabouzeid/gramophone/util/ColorUtil.java | 16 +- .../gramophone/util/NavigationUtil.java | 25 - .../drawable-hdpi/ic_equalizer_white_24dp.png | Bin 0 -> 128 bytes .../drawable-mdpi/ic_equalizer_white_24dp.png | Bin 0 -> 105 bytes .../ic_equalizer_white_24dp.png | Bin 0 -> 139 bytes .../ic_equalizer_white_24dp.png | Bin 0 -> 190 bytes .../ic_equalizer_white_24dp.png | Bin 0 -> 246 bytes .../main/res/layout/activity_album_detail.xml | 11 +- .../res/layout/activity_album_tag_editor.xml | 2 +- .../res/layout/activity_artist_detail.xml | 10 +- ...ity_main.xml => activity_main_content.xml} | 39 +- .../layout/activity_main_drawer_layout.xml | 22 + .../res/layout/activity_playlist_detail.xml | 13 +- .../main/res/layout/activity_preferences.xml | 9 +- app/src/main/res/layout/activity_search.xml | 6 +- .../res/layout/activity_song_tag_editor.xml | 2 +- app/src/main/res/layout/item_grid.xml | 1 - .../res/layout/item_grid_card_horizontal.xml | 2 +- app/src/main/res/layout/item_list.xml | 4 + .../main/res/layout/item_list_single_row.xml | 4 + app/src/main/res/layout/mini_player.xml | 33 + ...tivity_music_controller.xml => player.xml} | 87 +- .../res/layout/sliding_music_panel_layout.xml | 43 + app/src/main/res/layout/status_bar.xml | 6 +- app/src/main/res/layout/widget_medium.xml | 6 +- app/src/main/res/menu/menu_album_detail.xml | 15 +- app/src/main/res/menu/menu_artist_detail.xml | 27 +- app/src/main/res/menu/menu_main.xml | 5 - .../main/res/menu/menu_media_selection.xml | 2 +- ...menu_music_playing.xml => menu_player.xml} | 4 +- .../main/res/menu/menu_playlist_detail.xml | 15 +- app/src/main/res/values-v21/dimens.xml | 3 +- app/src/main/res/values/dimens.xml | 7 +- app/src/main/res/values/styles.xml | 3 +- app/src/main/res/values/styles_parents.xml | 8 +- 65 files changed, 1247 insertions(+), 1177 deletions(-) create mode 100644 app/src/main/java/com/kabouzeid/gramophone/misc/SimpleAnimatorListener.java rename app/src/main/java/com/kabouzeid/gramophone/misc/{SmallObservableScrollViewCallbacks.java => SimpleObservableScrollViewCallbacks.java} (82%) create mode 100644 app/src/main/java/com/kabouzeid/gramophone/misc/SimpleOnSeekbarChangeListener.java rename app/src/main/java/com/kabouzeid/gramophone/misc/{SmallTransitionListener.java => SimpleTransitionListener.java} (86%) delete mode 100644 app/src/main/java/com/kabouzeid/gramophone/misc/SmallOnGestureListener.java delete mode 100644 app/src/main/java/com/kabouzeid/gramophone/ui/activities/MusicControllerActivity.java create mode 100644 app/src/main/res/drawable-hdpi/ic_equalizer_white_24dp.png create mode 100644 app/src/main/res/drawable-mdpi/ic_equalizer_white_24dp.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_equalizer_white_24dp.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_equalizer_white_24dp.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_equalizer_white_24dp.png rename app/src/main/res/layout/{activity_main.xml => activity_main_content.xml} (65%) create mode 100644 app/src/main/res/layout/activity_main_drawer_layout.xml create mode 100644 app/src/main/res/layout/mini_player.xml rename app/src/main/res/layout/{activity_music_controller.xml => player.xml} (80%) create mode 100644 app/src/main/res/layout/sliding_music_panel_layout.xml rename app/src/main/res/menu/{menu_music_playing.xml => menu_player.xml} (90%) diff --git a/app/build.gradle b/app/build.gradle index 112536ea..ef8cf136 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ab887fad..fae6ce26 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -93,9 +93,6 @@ - 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 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 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; } diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SmartPlaylistSongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SmartPlaylistSongAdapter.java index 33ac1c8e..f99f7297 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SmartPlaylistSongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SmartPlaylistSongAdapter.java @@ -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; } diff --git a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java index e7e08e10..c8528abd 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java +++ b/app/src/main/java/com/kabouzeid/gramophone/adapter/song/SongAdapter.java @@ -124,15 +124,10 @@ public class SongAdapter extends AbsMultiSelectAdapter mService; - @Nullable private MediaPlayer mCurrentMediaPlayer = new MediaPlayer(); - @Nullable private MediaPlayer mNextMediaPlayer; private Handler mHandler; diff --git a/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java b/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java index cc30a60f..351bba61 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java +++ b/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java @@ -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() { diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java index 8b8abd7e..d819785e 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java @@ -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. - *

- * 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; } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java index 05ba6749..ee3371dd 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java @@ -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. - *

- * 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(); diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java index 79869403..6a8fdb83 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java @@ -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); + } } \ No newline at end of file diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MusicControllerActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MusicControllerActivity.java deleted file mode 100644 index 82c7feae..00000000 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MusicControllerActivity.java +++ /dev/null @@ -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 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); - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/PlaylistDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/PlaylistDetailActivity.java index e829bedc..509a58a5 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/PlaylistDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/PlaylistDetailActivity.java @@ -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); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SearchActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SearchActivity.java index 9a5c0353..809b5765 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SearchActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SearchActivity.java @@ -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(); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java index f26c5748..8b1d0bed 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java @@ -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); diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsMusicStateActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsMusicStateActivity.java index b3450654..e7927397 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsMusicStateActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsMusicStateActivity.java @@ -47,6 +47,8 @@ public abstract class AbsMusicStateActivity extends AbsBaseActivity implements S @Override public void onServiceConnected(ComponentName name, IBinder service) { onPlayStateChanged(); + onRepeatModeChanged(); + onShuffleModeChanged(); onPlayingMetaChanged(); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java index c3cfdbdd..14999ba9 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java @@ -1,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) + *

+ * 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 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(); +// } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsThemeActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsThemeActivity.java index 732fd069..2c43b1c9 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsThemeActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsThemeActivity.java @@ -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)); + } } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/AbsTagEditorActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/AbsTagEditorActivity.java index 5eb831b3..6554f7b1 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/AbsTagEditorActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/AbsTagEditorActivity.java @@ -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; diff --git a/app/src/main/java/com/kabouzeid/gramophone/util/ColorUtil.java b/app/src/main/java/com/kabouzeid/gramophone/util/ColorUtil.java index c8654991..f837d66e 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/util/ColorUtil.java +++ b/app/src/main/java/com/kabouzeid/gramophone/util/ColorUtil.java @@ -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); } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/util/NavigationUtil.java b/app/src/main/java/com/kabouzeid/gramophone/util/NavigationUtil.java index ec998f8a..715865fe 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/util/NavigationUtil.java +++ b/app/src/main/java/com/kabouzeid/gramophone/util/NavigationUtil.java @@ -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) { diff --git a/app/src/main/res/drawable-hdpi/ic_equalizer_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_equalizer_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..7ffb8d1745075b68b978fb0436b012624a62a601 GIT binary patch literal 128 zcmeAS@N?(olHy`uVBq!ia0y~yU{C>J4mJh`hKCF@W-u@?xO=)dhE&{odwnApg93+x zqy1j{?K>5fI413Sa8^z)C?zdKtD&LcSQzopr0L)7#+yDRo literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_equalizer_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_equalizer_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..e5bb73123ad23613644b26ea0372110ac5781938 GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJo3_M*NLn>}1|M>sko>|xM z@Cw!|TNq?}q70gJ4rG7)u%#iS*-cksYl20TK~(Cc>r4#q9=pn&mYOh+fq{X+)78&q Iol`;+01==fIsgCw literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_equalizer_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_equalizer_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..d206fe342e8971d97c5bb8d46cd671777c6af8d3 GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?F$>@?gm>B~)y}gl_L4m{7 z@mu^a>&DjB&Jz>&Fz%QZ;OX^Sfq{vILqNfyfq_$C!TAP1b}*X}CdkOdlEHByG{d2R z0V-B2&J5K66@bft85;cZe708@nN&EyTn>Q+D|N%K<*Dcx2-`6*Ffe$!`njxgN@xNA DA0jIu literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/ic_equalizer_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_equalizer_white_24dp.png new file mode 100644 index 0000000000000000000000000000000000000000..a7335db7cc48093d3701a854bdd802a56d07408c GIT binary patch literal 246 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4mJh`hDS5XEf^RW_IkQFhE&{od+{JAg8>io z#y9)7aK|p}H*sl;KCnt<>ApD(3=Iqn0t^gH3=Rwo91IMM32Mv1})*irA ra+qP6JPW2UVG%S3Ft9K*F#Ng4nCle8Ygph?0y4nU)z4*}Q$iB} + android:layout_height="wrap_content" + android:elevation="@dimen/toolbar_elevation" + tools:ignore="UnusedAttribute"> - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_album_tag_editor.xml b/app/src/main/res/layout/activity_album_tag_editor.xml index 50ec94e2..90e75da2 100644 --- a/app/src/main/res/layout/activity_album_tag_editor.xml +++ b/app/src/main/res/layout/activity_album_tag_editor.xml @@ -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" /> diff --git a/app/src/main/res/layout/activity_artist_detail.xml b/app/src/main/res/layout/activity_artist_detail.xml index a68b3655..f00bd4a4 100644 --- a/app/src/main/res/layout/activity_artist_detail.xml +++ b/app/src/main/res/layout/activity_artist_detail.xml @@ -81,7 +81,9 @@ + android:layout_height="wrap_content" + android:elevation="@dimen/toolbar_elevation" + tools:ignore="UnusedAttribute"> - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main_content.xml similarity index 65% rename from app/src/main/res/layout/activity_main.xml rename to app/src/main/res/layout/activity_main_content.xml index 5a2a4b49..4a80c27d 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main_content.xml @@ -1,11 +1,19 @@ - + + android:orientation="vertical"> + + + + + + 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" /> @@ -54,20 +63,6 @@ android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main_drawer_layout.xml b/app/src/main/res/layout/activity_main_drawer_layout.xml new file mode 100644 index 00000000..06d43f7b --- /dev/null +++ b/app/src/main/res/layout/activity_main_drawer_layout.xml @@ -0,0 +1,22 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_playlist_detail.xml b/app/src/main/res/layout/activity_playlist_detail.xml index be298454..28ef5464 100644 --- a/app/src/main/res/layout/activity_playlist_detail.xml +++ b/app/src/main/res/layout/activity_playlist_detail.xml @@ -1,4 +1,5 @@ @@ -7,9 +8,13 @@ android:layout_height="match_parent" android:orientation="vertical"> + + + android:layout_height="wrap_content" + android:elevation="@dimen/toolbar_elevation" + tools:ignore="UnusedAttribute"> - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_preferences.xml b/app/src/main/res/layout/activity_preferences.xml index 5b042b2c..a75011c3 100644 --- a/app/src/main/res/layout/activity_preferences.xml +++ b/app/src/main/res/layout/activity_preferences.xml @@ -1,15 +1,16 @@ + android:layout_height="match_parent" + android:orientation="vertical"> + + + android:background="@android:color/transparent" /> + + + style="@style/Toolbar" /> diff --git a/app/src/main/res/layout/item_grid.xml b/app/src/main/res/layout/item_grid.xml index ad3ca6c8..83d7f8e6 100644 --- a/app/src/main/res/layout/item_grid.xml +++ b/app/src/main/res/layout/item_grid.xml @@ -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" /> diff --git a/app/src/main/res/layout/item_grid_card_horizontal.xml b/app/src/main/res/layout/item_grid_card_horizontal.xml index 9d0c5220..1aa49cee 100644 --- a/app/src/main/res/layout/item_grid_card_horizontal.xml +++ b/app/src/main/res/layout/item_grid_card_horizontal.xml @@ -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" /> diff --git a/app/src/main/res/layout/item_list.xml b/app/src/main/res/layout/item_list.xml index 24cd814f..210fa6ef 100644 --- a/app/src/main/res/layout/item_list.xml +++ b/app/src/main/res/layout/item_list.xml @@ -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" /> diff --git a/app/src/main/res/layout/item_list_single_row.xml b/app/src/main/res/layout/item_list_single_row.xml index 2849e64f..2f66a659 100644 --- a/app/src/main/res/layout/item_list_single_row.xml +++ b/app/src/main/res/layout/item_list_single_row.xml @@ -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" /> diff --git a/app/src/main/res/layout/mini_player.xml b/app/src/main/res/layout/mini_player.xml new file mode 100644 index 00000000..3e4f9076 --- /dev/null +++ b/app/src/main/res/layout/mini_player.xml @@ -0,0 +1,33 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_music_controller.xml b/app/src/main/res/layout/player.xml similarity index 80% rename from app/src/main/res/layout/activity_music_controller.xml rename to app/src/main/res/layout/player.xml index 9205ef06..8f3c1dcd 100644 --- a/app/src/main/res/layout/activity_music_controller.xml +++ b/app/src/main/res/layout/player.xml @@ -1,15 +1,13 @@ + android:layout_height="match_parent"> + android:layout_margin="0dp" + android:visibility="invisible" /> @@ -186,31 +184,30 @@ @@ -269,14 +266,18 @@ - + + android:layout_below="@id/player_status_bar" + android:background="#00000000" + tools:ignore="UnusedAttribute" /> diff --git a/app/src/main/res/layout/sliding_music_panel_layout.xml b/app/src/main/res/layout/sliding_music_panel_layout.xml new file mode 100644 index 00000000..d8906741 --- /dev/null +++ b/app/src/main/res/layout/sliding_music_panel_layout.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/status_bar.xml b/app/src/main/res/layout/status_bar.xml index cd656bf1..87c5e1d5 100644 --- a/app/src/main/res/layout/status_bar.xml +++ b/app/src/main/res/layout/status_bar.xml @@ -1,7 +1,9 @@ - \ No newline at end of file + android:elevation="@dimen/toolbar_elevation" + tools:ignore="UnusedAttribute" /> \ No newline at end of file diff --git a/app/src/main/res/layout/widget_medium.xml b/app/src/main/res/layout/widget_medium.xml index 42f72596..71a34a98 100644 --- a/app/src/main/res/layout/widget_medium.xml +++ b/app/src/main/res/layout/widget_medium.xml @@ -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" /> + android:textAppearance="@style/TextAppearance.AppCompat.Caption" + android:textColor="@color/secondary_text_default_material_light" /> diff --git a/app/src/main/res/menu/menu_album_detail.xml b/app/src/main/res/menu/menu_album_detail.xml index 25fedb3c..035ab981 100644 --- a/app/src/main/res/menu/menu_album_detail.xml +++ b/app/src/main/res/menu/menu_album_detail.xml @@ -4,21 +4,10 @@ tools:context="com.kabouzeid.gramophone.ui.activities.AlbumDetailActivity"> - - - - + 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"> + app:showAsAction="ifRoom" /> + app:showAsAction="never" /> + app:showAsAction="never" /> + app:showAsAction="never" /> diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml index 0dc607c6..d11c47ea 100644 --- a/app/src/main/res/menu/menu_main.xml +++ b/app/src/main/res/menu/menu_main.xml @@ -9,11 +9,6 @@ android:title="@string/action_search" app:showAsAction="ifRoom" /> - -

+ xmlns:app="http://schemas.android.com/apk/res-auto"> + xmlns:app="http://schemas.android.com/apk/res-auto"> - - - - + app:showAsAction="ifRoom" /> 25dp 165dp - 16dp + 16dp + 20dp -8dp \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 826cc3de..8f2426a3 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -44,7 +44,7 @@ http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout 96dp 128dp - 86dp + 44dp 8dp 8dp @@ -52,7 +52,8 @@ http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout 16dp - 0dp + 0dp + 0dp -24dp 16dp @@ -67,4 +68,6 @@ http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout 8dp + 48dp + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 277da155..beb53eec 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -41,7 +41,8 @@