Initial commit retro music app

This commit is contained in:
h4h13 2018-07-27 18:37:33 +05:30
parent ab332473bc
commit fe890632fd
932 changed files with 83126 additions and 0 deletions

View file

@ -0,0 +1,167 @@
package code.name.monkey.retromusic.ui.activities;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.AppBarLayout;
import android.support.v4.app.ShareCompat;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.Constants;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.RetroApplication;
import code.name.monkey.retromusic.ui.activities.base.AbsBaseActivity;
import code.name.monkey.retromusic.util.NavigationUtil;
import static code.name.monkey.retromusic.Constants.APP_INSTAGRAM_LINK;
import static code.name.monkey.retromusic.Constants.APP_TWITTER_LINK;
import static code.name.monkey.retromusic.Constants.GITHUB_PROJECT;
import static code.name.monkey.retromusic.Constants.GOOGLE_PLUS_COMMUNITY;
import static code.name.monkey.retromusic.Constants.RATE_ON_GOOGLE_PLAY;
import static code.name.monkey.retromusic.Constants.TELEGRAM_CHANGE_LOG;
import static code.name.monkey.retromusic.Constants.TRANSLATE;
/**
* @author Hemanth S (h4h13)
*/
public class AboutActivity extends AbsBaseActivity {
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.app_bar)
AppBarLayout appBar;
@BindView(R.id.buy_pro)
TextView supportText;
@BindView(R.id.app_version)
TextView appVersion;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_about);
ButterKnife.bind(this);
setStatusbarColorAuto();
setNavigationbarColorAuto();
setTaskDescriptionColorAuto();
setLightNavigationBar(true);
setUpToolbar();
appVersion.setText(getAppVersion());
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
private void setUpToolbar() {
int primaryColor = ThemeStore.primaryColor(this);
toolbar.setBackgroundColor(primaryColor);
appBar.setBackgroundColor(primaryColor);
setTitle(R.string.action_about);
setSupportActionBar(toolbar);
//noinspection ConstantConditions
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
supportText.setText(RetroApplication.isProVersion() ? R.string.thank_you : R.string.buy_retromusic_pro);
}
private void openUrl(String url) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
@OnClick({R.id.app_github, R.id.faq_link,
R.id.app_google_plus, R.id.app_translation,
R.id.support_container, R.id.app_rate, R.id.app_share, R.id.pro_container,
R.id.instagram_link, R.id.twitter_link, R.id.changelog,
R.id.open_source, R.id.discord_link, R.id.telegram_link})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.faq_link:
openUrl(Constants.FAQ_LINK);
break;
case R.id.telegram_link:
openUrl(Constants.APP_TELEGRAM_LINK);
break;
case R.id.discord_link:
openUrl(Constants.DISCORD_LINK);
break;
case R.id.app_github:
openUrl(GITHUB_PROJECT);
break;
case R.id.app_google_plus:
openUrl(GOOGLE_PLUS_COMMUNITY);
break;
case R.id.support_container:
startActivity(new Intent(this, SupportDevelopmentActivity.class));
break;
case R.id.app_translation:
openUrl(TRANSLATE);
break;
case R.id.app_rate:
openUrl(RATE_ON_GOOGLE_PLAY);
break;
case R.id.app_share:
shareApp();
break;
case R.id.pro_container:
NavigationUtil.goToProVersion(this);
break;
case R.id.instagram_link:
openUrl(APP_INSTAGRAM_LINK);
break;
case R.id.twitter_link:
openUrl(APP_TWITTER_LINK);
break;
case R.id.changelog:
openUrl(TELEGRAM_CHANGE_LOG);
break;
case R.id.open_source:
NavigationUtil.goToOpenSource(this);
break;
}
}
private String getAppVersion() {
try {
PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
return packageInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return "0.0.0";
}
}
private void shareApp() {
Intent shareIntent = ShareCompat.IntentBuilder.from(this)
.setType("songText/plain")
.setText(String.format(getString(R.string.app_share), getPackageName()))
.getIntent();
if (shareIntent.resolveActivity(getPackageManager()) != null) {
startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.action_share)));
}
}
}

View file

@ -0,0 +1,414 @@
package code.name.monkey.retromusic.ui.activities;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.NestedScrollView;
import android.support.v7.widget.AppCompatTextView;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
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.PopupMenu;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import java.util.ArrayList;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog;
import code.name.monkey.retromusic.dialogs.DeleteSongsDialog;
import code.name.monkey.retromusic.glide.ArtistGlideRequest;
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget;
import code.name.monkey.retromusic.glide.SongGlideRequest;
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.SortOrder.AlbumSongSortOrder;
import code.name.monkey.retromusic.loaders.ArtistLoader;
import code.name.monkey.retromusic.misc.AppBarStateChangeListener;
import code.name.monkey.retromusic.model.Album;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.mvp.contract.AlbumDetailsContract;
import code.name.monkey.retromusic.mvp.presenter.AlbumDetailsPresenter;
import code.name.monkey.retromusic.ui.activities.base.AbsSlidingMusicPanelActivity;
import code.name.monkey.retromusic.ui.activities.tageditor.AbsTagEditorActivity;
import code.name.monkey.retromusic.ui.activities.tageditor.AlbumTagEditorActivity;
import code.name.monkey.retromusic.ui.adapter.album.AlbumAdapter;
import code.name.monkey.retromusic.ui.adapter.album.HorizontalAlbumAdapter;
import code.name.monkey.retromusic.ui.adapter.song.SimpleSongAdapter;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.NavigationUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.util.RetroUtil;
public class AlbumDetailsActivity extends AbsSlidingMusicPanelActivity implements
AlbumDetailsContract.AlbumDetailsView {
public static final String EXTRA_ALBUM_ID = "extra_album_id";
private static final int TAG_EDITOR_REQUEST = 2001;
@BindView(R.id.image)
ImageView image;
@BindView(R.id.recycler_view)
RecyclerView recyclerView;
@BindView(R.id.title)
TextView title;
@BindView(R.id.text)
TextView text;
@BindView(R.id.song_title)
AppCompatTextView songTitle;
@BindView(R.id.action_shuffle_all)
FloatingActionButton shuffleButton;
@BindView(R.id.collapsing_toolbar)
@Nullable
CollapsingToolbarLayout collapsingToolbarLayout;
@BindView(R.id.app_bar)
@Nullable
AppBarLayout appBarLayout;
@BindView(R.id.image_container)
@Nullable
View imageContainer;
@BindView(R.id.content)
View contentContainer;
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.more_recycler_view)
RecyclerView moreRecyclerView;
@BindView(R.id.more_title)
TextView moreTitle;
@BindView(R.id.artist_image)
ImageView artistImage;
private AlbumDetailsPresenter albumDetailsPresenter;
private Album album;
private SimpleSongAdapter adapter;
@Override
protected View createContentView() {
return wrapSlidingMusicPanel(R.layout.activity_album);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
setDrawUnderStatusbar(true);
super.onCreate(savedInstanceState);
ButterKnife.bind(this);
supportPostponeEnterTransition();
setupToolbarMarginHeight();
setBottomBarVisibility(View.GONE);
setLightNavigationBar(true);
setNavigationbarColorAuto();
int albumId = getIntent().getIntExtra(EXTRA_ALBUM_ID, -1);
albumDetailsPresenter = new AlbumDetailsPresenter(this, albumId);
}
private void setupToolbarMarginHeight() {
int primaryColor = ThemeStore.primaryColor(this);
TintHelper.setTintAuto(contentContainer, primaryColor, true);
if (collapsingToolbarLayout != null) {
collapsingToolbarLayout.setContentScrimColor(primaryColor);
collapsingToolbarLayout.setStatusBarScrimColor(ColorUtil.darkenColor(primaryColor));
}
toolbar.setNavigationIcon(R.drawable.ic_keyboard_backspace_black_24dp);
setSupportActionBar(toolbar);
//noinspection ConstantConditions
getSupportActionBar().setTitle(null);
if (toolbar != null && !PreferenceUtil.getInstance(this).getFullScreenMode()) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams();
params.topMargin = RetroUtil.getStatusBarHeight(this);
toolbar.setLayoutParams(params);
}
if (appBarLayout != null) {
appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() {
@Override
public void onStateChanged(AppBarLayout appBarLayout, State state) {
int color;
switch (state) {
case COLLAPSED:
setLightStatusbar(!ATHUtil.isWindowBackgroundDark(AlbumDetailsActivity.this));
color = ATHUtil.resolveColor(AlbumDetailsActivity.this, R.attr.iconColor);
break;
default:
case EXPANDED:
case IDLE:
setLightStatusbar(false);
color = ContextCompat.getColor(AlbumDetailsActivity.this, R.color.md_white_1000);
break;
}
ToolbarContentTintHelper.colorizeToolbar(toolbar, color, AlbumDetailsActivity.this);
}
});
}
}
@OnClick({R.id.action_shuffle_all})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.menu_close:
onBackPressed();
break;
case R.id.menu:
PopupMenu popupMenu = new PopupMenu(this, view);
popupMenu.inflate(R.menu.menu_album_detail);
MenuItem sortOrder = popupMenu.getMenu().findItem(R.id.action_sort_order);
setUpSortOrderMenu(sortOrder.getSubMenu());
popupMenu.setOnMenuItemClickListener(this::onOptionsItemSelected);
popupMenu.show();
break;
case R.id.action_shuffle_all:
MusicPlayerRemote.openAndShuffleQueue(album.songs, true);
break;
}
}
@Override
protected void onResume() {
super.onResume();
albumDetailsPresenter.subscribe();
}
@Override
protected void onPause() {
super.onPause();
albumDetailsPresenter.unsubscribe();
}
@Override
public void loading() {
}
@Override
public void showEmptyView() {
}
@Override
public void completed() {
supportStartPostponedEnterTransition();
}
@Override
public void showData(Album album) {
if (album.songs.isEmpty()) {
finish();
return;
}
this.album = album;
title.setText(album.getTitle());
text.setText(String.format("%s%s • %s", album.getArtistName(), "" + MusicUtil.getYearString(album.getYear()),
MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(this, album.songs))));
loadAlbumCover();
adapter = new SimpleSongAdapter(this, this.album.songs, R.layout.item_song);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
recyclerView.setNestedScrollingEnabled(false);
loadMoreFrom(album);
}
private void loadMoreFrom(Album album) {
ArtistGlideRequest.Builder.from(Glide.with(this),
ArtistLoader.getArtist(this, album.getArtistId()).blockingFirst())
.forceDownload(true)
.generatePalette(this).build()
.dontAnimate()
.into(new RetroMusicColoredTarget(artistImage) {
@Override
public void onColorReady(int color) {
setColors(color);
}
});
ArrayList<Album> albums = ArtistLoader.getArtist(this, album.getArtistId()).blockingFirst().albums;
albums.remove(album);
if (!albums.isEmpty()) {
moreTitle.setVisibility(View.VISIBLE);
moreRecyclerView.setVisibility(View.VISIBLE);
} else {
return;
}
moreTitle.setText(String.format("More from %s", album.getArtistName()));
AlbumAdapter albumAdapter = new HorizontalAlbumAdapter(this, albums,
false, null);
moreRecyclerView.setLayoutManager(new GridLayoutManager(this, 1, GridLayoutManager.HORIZONTAL, false));
moreRecyclerView.setAdapter(albumAdapter);
}
public Album getAlbum() {
return album;
}
private void loadAlbumCover() {
SongGlideRequest.Builder.from(Glide.with(this), getAlbum().safeGetFirstSong())
.checkIgnoreMediaStore(this)
.generatePalette(this).build()
.dontAnimate()
.listener(new RequestListener<Object, BitmapPaletteWrapper>() {
@Override
public boolean onException(Exception e, Object model, Target<BitmapPaletteWrapper> target,
boolean isFirstResource) {
supportStartPostponedEnterTransition();
return false;
}
@Override
public boolean onResourceReady(BitmapPaletteWrapper resource, Object model,
Target<BitmapPaletteWrapper> target, boolean isFromMemoryCache,
boolean isFirstResource) {
supportStartPostponedEnterTransition();
return false;
}
})
.into(new RetroMusicColoredTarget(image) {
@Override
public void onColorReady(int color) {
setColors(color);
}
});
}
private void setColors(int color) {
int themeColor = PreferenceUtil.getInstance(this).getAdaptiveColor() ? color : ThemeStore.accentColor(this);
songTitle.setTextColor(themeColor);
moreTitle.setTextColor(themeColor);
TintHelper.setTintAuto(shuffleButton, themeColor, true);
findViewById(R.id.root).setBackgroundColor(ThemeStore.primaryColor(this));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_album_detail, menu);
MenuItem sortOrder = menu.findItem(R.id.action_sort_order);
setUpSortOrderMenu(sortOrder.getSubMenu());
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return handleSortOrderMenuItem(item);
}
private boolean handleSortOrderMenuItem(@NonNull MenuItem item) {
String sortOrder = null;
final ArrayList<Song> songs = adapter.getDataSet();
switch (item.getItemId()) {
case R.id.action_play_next:
MusicPlayerRemote.playNext(songs);
return true;
case R.id.action_add_to_current_playing:
MusicPlayerRemote.enqueue(songs);
return true;
case R.id.action_add_to_playlist:
AddToPlaylistDialog.create(songs).show(getSupportFragmentManager(), "ADD_PLAYLIST");
return true;
case R.id.action_delete_from_device:
DeleteSongsDialog.create(songs).show(getSupportFragmentManager(), "DELETE_SONGS");
return true;
case android.R.id.home:
super.onBackPressed();
return true;
case R.id.action_tag_editor:
Intent intent = new Intent(this, AlbumTagEditorActivity.class);
intent.putExtra(AbsTagEditorActivity.EXTRA_ID, getAlbum().getId());
startActivityForResult(intent, TAG_EDITOR_REQUEST);
return true;
case R.id.action_go_to_artist:
NavigationUtil.goToArtist(this, getAlbum().getArtistId());
return true;
/*Sort*/
case R.id.action_sort_order_title:
sortOrder = AlbumSongSortOrder.SONG_A_Z;
break;
case R.id.action_sort_order_title_desc:
sortOrder = AlbumSongSortOrder.SONG_Z_A;
break;
case R.id.action_sort_order_track_list:
sortOrder = AlbumSongSortOrder.SONG_TRACK_LIST;
break;
case R.id.action_sort_order_artist_song_duration:
sortOrder = AlbumSongSortOrder.SONG_DURATION;
break;
}
if (sortOrder != null) {
item.setChecked(true);
setSaveSortOrder(sortOrder);
}
return true;
}
private String getSavedSortOrder() {
return PreferenceUtil.getInstance(this).getAlbumDetailSongSortOrder();
}
private void setUpSortOrderMenu(@NonNull SubMenu sortOrder) {
switch (getSavedSortOrder()) {
case AlbumSongSortOrder.SONG_A_Z:
sortOrder.findItem(R.id.action_sort_order_title).setChecked(true);
break;
case AlbumSongSortOrder.SONG_Z_A:
sortOrder.findItem(R.id.action_sort_order_title_desc).setChecked(true);
break;
case AlbumSongSortOrder.SONG_TRACK_LIST:
sortOrder.findItem(R.id.action_sort_order_track_list).setChecked(true);
break;
case AlbumSongSortOrder.SONG_DURATION:
sortOrder.findItem(R.id.action_sort_order_artist_song_duration).setChecked(true);
break;
}
}
private void setSaveSortOrder(String sortOrder) {
PreferenceUtil.getInstance(this).setAlbumDetailSongSortOrder(sortOrder);
reload();
}
@Override
public void onMediaStoreChanged() {
super.onMediaStoreChanged();
reload();
}
private void reload() {
albumDetailsPresenter.subscribe();
}
}

View file

@ -0,0 +1,429 @@
package code.name.monkey.retromusic.ui.activities;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.AppCompatTextView;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.Html;
import android.text.Spanned;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
import java.util.Locale;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog;
import code.name.monkey.retromusic.glide.ArtistGlideRequest;
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.misc.AppBarStateChangeListener;
import code.name.monkey.retromusic.model.Artist;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.mvp.contract.ArtistDetailContract;
import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsPresenter;
import code.name.monkey.retromusic.rest.LastFMRestClient;
import code.name.monkey.retromusic.rest.model.LastFmArtist;
import code.name.monkey.retromusic.ui.activities.base.AbsSlidingMusicPanelActivity;
import code.name.monkey.retromusic.ui.adapter.album.AlbumAdapter;
import code.name.monkey.retromusic.ui.adapter.album.HorizontalAlbumAdapter;
import code.name.monkey.retromusic.ui.adapter.song.SimpleSongAdapter;
import code.name.monkey.retromusic.util.CustomArtistImageUtil;
import code.name.monkey.retromusic.util.DensityUtil;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.util.RetroUtil;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implements
ArtistDetailContract.ArtistsDetailsView {
public static final String EXTRA_ARTIST_ID = "extra_artist_id";
private static final int REQUEST_CODE_SELECT_IMAGE = 9003;
@BindView(R.id.image)
ImageView image;
@BindView(R.id.biography)
TextView biographyTextView;
@BindView(R.id.recycler_view)
RecyclerView recyclerView;
@BindView(R.id.album_recycler_view)
RecyclerView albumRecyclerView;
@BindView(R.id.album_title)
AppCompatTextView albumTitle;
@BindView(R.id.song_title)
AppCompatTextView songTitle;
@BindView(R.id.biography_title)
AppCompatTextView biographyTitle;
@BindView(R.id.title)
TextView title;
@BindView(R.id.text)
TextView text;
@BindView(R.id.action_shuffle_all)
FloatingActionButton shuffleButton;
@BindView(R.id.collapsing_toolbar)
@Nullable
CollapsingToolbarLayout collapsingToolbarLayout;
@BindView(R.id.app_bar)
@Nullable
AppBarLayout appBarLayout;
@BindView(R.id.gradient_background)
@Nullable
View background;
@BindView(R.id.image_container)
@Nullable
View imageContainer;
@BindView(R.id.content)
View contentContainer;
@BindView(R.id.toolbar)
Toolbar toolbar;
@Nullable
private Spanned biography;
private Artist artist;
private LastFMRestClient lastFMRestClient;
private ArtistDetailsPresenter artistDetailsPresenter;
private SimpleSongAdapter songAdapter;
private AlbumAdapter albumAdapter;
private boolean forceDownload;
@Override
protected View createContentView() {
return wrapSlidingMusicPanel(R.layout.activity_artist_details);
}
@Override
protected void onCreate(Bundle bundle) {
setDrawUnderStatusbar(true);
super.onCreate(bundle);
ButterKnife.bind(this);
supportPostponeEnterTransition();
setBottomBarVisibility(View.GONE);
setNavigationbarColorAuto();
setLightNavigationBar(true);
lastFMRestClient = new LastFMRestClient(this);
setUpViews();
int artistID = getIntent().getIntExtra(EXTRA_ARTIST_ID, -1);
artistDetailsPresenter = new ArtistDetailsPresenter(this, artistID);
}
private void setUpViews() {
setupRecyclerView();
setupToolbar();
setupContainerHeight();
}
private void setupContainerHeight() {
if (imageContainer != null) {
LayoutParams params = imageContainer.getLayoutParams();
params.width = DensityUtil.getScreenHeight(this) / 2;
imageContainer.setLayoutParams(params);
}
}
private void setupToolbar() {
toolbar.setNavigationIcon(R.drawable.ic_keyboard_backspace_black_24dp);
setSupportActionBar(toolbar);
//noinspection ConstantConditions
getSupportActionBar().setTitle(null);
if (toolbar != null && !PreferenceUtil.getInstance(this).getFullScreenMode()) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams();
params.topMargin = RetroUtil.getStatusBarHeight(this);
toolbar.setLayoutParams(params);
}
int primaryColor = ThemeStore.primaryColor(this);
TintHelper.setTintAuto(contentContainer, primaryColor, true);
if (appBarLayout != null) {
appBarLayout.setBackgroundColor(primaryColor);
appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() {
@Override
public void onStateChanged(AppBarLayout appBarLayout, AppBarStateChangeListener.State state) {
int color;
switch (state) {
case COLLAPSED:
setLightStatusbar(!ATHUtil.isWindowBackgroundDark(ArtistDetailActivity.this));
color = ATHUtil.resolveColor(ArtistDetailActivity.this, R.attr.iconColor);
break;
default:
case EXPANDED:
case IDLE:
setLightStatusbar(false);
color = ContextCompat.getColor(ArtistDetailActivity.this, R.color.md_white_1000);
break;
}
ToolbarContentTintHelper.colorizeToolbar(toolbar, color, ArtistDetailActivity.this);
}
});
}
if (collapsingToolbarLayout != null) {
collapsingToolbarLayout.setContentScrimColor(primaryColor);
collapsingToolbarLayout.setStatusBarScrimColor(ColorUtil.darkenColor(primaryColor));
}
}
private void setupRecyclerView() {
albumAdapter = new HorizontalAlbumAdapter(this, new ArrayList<>(), false, null);
albumRecyclerView.setItemAnimator(new DefaultItemAnimator());
albumRecyclerView
.setLayoutManager(new GridLayoutManager(this, 1, GridLayoutManager.HORIZONTAL, false));
albumRecyclerView.setAdapter(albumAdapter);
songAdapter = new SimpleSongAdapter(this, new ArrayList<>(), R.layout.item_song);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(songAdapter);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_CODE_SELECT_IMAGE:
if (resultCode == RESULT_OK) {
CustomArtistImageUtil.getInstance(this).setCustomArtistImage(artist, data.getData());
}
break;
default:
if (resultCode == RESULT_OK) {
reload();
}
break;
}
}
@Override
protected void onResume() {
super.onResume();
artistDetailsPresenter.subscribe();
}
@Override
protected void onPause() {
super.onPause();
artistDetailsPresenter.unsubscribe();
}
@Override
public void loading() {
}
@Override
public void showEmptyView() {
}
@Override
public void completed() {
supportStartPostponedEnterTransition();
}
@Override
public void showData(Artist artist) {
setArtist(artist);
}
private Artist getArtist() {
if (artist == null) {
artist = new Artist();
}
return artist;
}
private void setArtist(Artist artist) {
if (artist.getSongCount() <= 0) {
finish();
}
this.artist = artist;
loadArtistImage();
if (RetroUtil.isAllowedToDownloadMetadata(this)) {
loadBiography();
}
title.setText(artist.getName());
text.setText(String.format("%s • %s", MusicUtil.getArtistInfoString(this, artist), MusicUtil
.getReadableDurationString(MusicUtil.getTotalDuration(this, artist.getSongs()))));
songAdapter.swapDataSet(artist.getSongs());
albumAdapter.swapDataSet(artist.albums);
}
private void loadBiography() {
loadBiography(Locale.getDefault().getLanguage());
}
private void loadBiography(@Nullable final String lang) {
biography = null;
lastFMRestClient.getApiService()
.getArtistInfo(getArtist().getName(), lang, null)
.enqueue(new Callback<LastFmArtist>() {
@Override
public void onResponse(@NonNull Call<LastFmArtist> call,
@NonNull Response<LastFmArtist> response) {
final LastFmArtist lastFmArtist = response.body();
if (lastFmArtist != null && lastFmArtist.getArtist() != null) {
final String bioContent = lastFmArtist.getArtist().getBio().getContent();
if (bioContent != null && !bioContent.trim().isEmpty()) {
//TransitionManager.beginDelayedTransition(titleContainer);
biographyTextView.setVisibility(View.VISIBLE);
biographyTitle.setVisibility(View.VISIBLE);
biography = Html.fromHtml(bioContent);
biographyTextView.setText(biography);
}
}
// If the "lang" parameter is set and no biography is given, retry with default language
if (biography == null && lang != null) {
loadBiography(null);
return;
}
}
@Override
public void onFailure(@NonNull Call<LastFmArtist> call, @NonNull Throwable t) {
t.printStackTrace();
biography = null;
}
});
}
@OnClick(R.id.biography)
void toggleArtistBiography() {
if (biographyTextView.getMaxLines() == 4) {
biographyTextView.setMaxLines(Integer.MAX_VALUE);
} else {
biographyTextView.setMaxLines(4);
}
}
private void loadArtistImage() {
ArtistGlideRequest.Builder.from(Glide.with(this), artist)
.forceDownload(forceDownload)
.generatePalette(this).build()
.dontAnimate()
.into(new RetroMusicColoredTarget(image) {
@Override
public void onColorReady(int color) {
setColors(color);
}
});
forceDownload = false;
}
private void setColors(int color) {
int textColor =
PreferenceUtil.getInstance(this).getAdaptiveColor() ? color : ThemeStore.accentColor(this);
albumTitle.setTextColor(textColor);
songTitle.setTextColor(textColor);
biographyTitle.setTextColor(textColor);
TintHelper.setTintAuto(shuffleButton, textColor, true);
if (background != null) {
background.setBackgroundTintList(ColorStateList.valueOf(color));
}
findViewById(R.id.root).setBackgroundColor(ThemeStore.primaryColor(this));
}
@OnClick({R.id.action_shuffle_all})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.action_shuffle_all:
MusicPlayerRemote.openAndShuffleQueue(getArtist().getSongs(), true);
break;
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return handleSortOrderMenuItem(item);
}
private boolean handleSortOrderMenuItem(@NonNull MenuItem item) {
final ArrayList<Song> songs = getArtist().getSongs();
switch (item.getItemId()) {
case android.R.id.home:
super.onBackPressed();
return true;
case R.id.action_play_next:
MusicPlayerRemote.playNext(songs);
return true;
case R.id.action_add_to_current_playing:
MusicPlayerRemote.enqueue(songs);
return true;
case R.id.action_add_to_playlist:
AddToPlaylistDialog.create(songs).show(getSupportFragmentManager(), "ADD_PLAYLIST");
return true;
case R.id.action_set_artist_image:
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(
Intent.createChooser(intent, getString(R.string.pick_from_local_storage)),
REQUEST_CODE_SELECT_IMAGE);
return true;
case R.id.action_reset_artist_image:
Toast.makeText(ArtistDetailActivity.this, getResources().getString(R.string.updating),
Toast.LENGTH_SHORT).show();
CustomArtistImageUtil.getInstance(ArtistDetailActivity.this).resetCustomArtistImage(artist);
forceDownload = true;
return true;
}
return true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_artist_detail, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public void onMediaStoreChanged() {
super.onMediaStoreChanged();
reload();
}
private void reload() {
artistDetailsPresenter.unsubscribe();
artistDetailsPresenter.subscribe();
}
}

View file

@ -0,0 +1,223 @@
package code.name.monkey.retromusic.ui.activities;
import android.os.Bundle;
import android.support.design.widget.AppBarLayout;
import android.support.v7.widget.SwitchCompat;
import android.support.v7.widget.Toolbar;
import android.transition.TransitionManager;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.EqualizerHelper;
import code.name.monkey.retromusic.ui.activities.base.AbsMusicServiceActivity;
/**
* @author Hemanth S (h4h13).
*/
public class EqualizerActivity extends AbsMusicServiceActivity implements
AdapterView.OnItemSelectedListener {
@BindView(R.id.equalizer)
SwitchCompat mEnable;
@BindView(R.id.content)
LinearLayout mContent;
@BindView(R.id.bands)
LinearLayout mLinearLayout;
@BindView(R.id.bass_boost_strength)
SeekBar mBassBoostStrength;
@BindView(R.id.virtualizer_strength)
SeekBar mVirtualizerStrength;
@BindView(R.id.bass_boost)
TextView mBassBoost;
@BindView(R.id.virtualizer)
TextView mVirtualizer;
@BindView(R.id.toolbar)
Toolbar mToolbar;
@BindView(R.id.app_bar)
AppBarLayout mAppBar;
@BindView(R.id.presets)
Spinner mPresets;
private CompoundButton.OnCheckedChangeListener mListener = (buttonView, isChecked) -> {
switch (buttonView.getId()) {
case R.id.equalizer:
EqualizerHelper.getInstance().getEqualizer().setEnabled(isChecked);
TransitionManager.beginDelayedTransition(mContent);
mContent.setVisibility(isChecked ? View.VISIBLE : View.GONE);
break;
}
};
private SeekBar.OnSeekBarChangeListener mSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
if (seekBar == mBassBoostStrength) {
mBassBoost.setEnabled(progress > 0);
EqualizerHelper.getInstance().setBassBoostStrength(progress);
EqualizerHelper.getInstance().setBassBoostEnabled(progress > 0);
} else if (seekBar == mVirtualizerStrength) {
mVirtualizer.setEnabled(progress > 0);
EqualizerHelper.getInstance().setVirtualizerEnabled(progress > 0);
EqualizerHelper.getInstance().setVirtualizerStrength(progress);
}
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
private ArrayAdapter<String> mPresetsNamesAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_equalizer);
ButterKnife.bind(this);
setStatusbarColorAuto();
setNavigationbarColorAuto();
setTaskDescriptionColorAuto();
setLightNavigationBar(true);
int primaryColor = ThemeStore.primaryColor(this);
mToolbar.setBackgroundColor(primaryColor);
mAppBar.setBackgroundColor(primaryColor);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
mToolbar.setTitle(R.string.equalizer);
setSupportActionBar(mToolbar);
//noinspection ConstantConditions
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mEnable.setChecked(EqualizerHelper.getInstance().getEqualizer().getEnabled());
mEnable.setOnCheckedChangeListener(mListener);
mPresetsNamesAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
mPresets.setAdapter(mPresetsNamesAdapter);
mPresets.setOnItemSelectedListener(this);
mBassBoostStrength.setProgress(EqualizerHelper.getInstance().getBassBoostStrength());
mBassBoostStrength.setOnSeekBarChangeListener(mSeekBarChangeListener);
mVirtualizerStrength.setProgress(EqualizerHelper.getInstance().getVirtualizerStrength());
mVirtualizerStrength.setOnSeekBarChangeListener(mSeekBarChangeListener);
setupUI();
addPresets();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
}
return super.onOptionsItemSelected(item);
}
private void addPresets() {
mPresetsNamesAdapter.clear();
mPresetsNamesAdapter.add("Custom");
for (int j = 0; j < EqualizerHelper.getInstance().getEqualizer().getNumberOfPresets(); j++) {
mPresetsNamesAdapter
.add(EqualizerHelper.getInstance().getEqualizer().getPresetName((short) j));
mPresetsNamesAdapter.notifyDataSetChanged();
}
mPresets
.setSelection((int) EqualizerHelper.getInstance().getEqualizer().getCurrentPreset() + 1);
}
private void setupUI() {
mLinearLayout.removeAllViews();
short bands;
try {
// get number of supported bands
bands = (short) EqualizerHelper.getInstance().getNumberOfBands();
// for each of the supported bands, we will set up a slider from -10dB to 10dB boost/attenuation,
// as well as text labels to assist the user
for (short i = 0; i < bands; i++) {
final short band = i;
View view = LayoutInflater.from(this).inflate(R.layout.retro_seekbar, mLinearLayout, false);
TextView freqTextView = view.findViewById(R.id.hurtz);
freqTextView.setText(
String.format("%d Hz", EqualizerHelper.getInstance().getCenterFreq((int) band) / 1000));
TextView minDbTextView = view.findViewById(R.id.minus_db);
minDbTextView
.setText(String.format("%d dB", EqualizerHelper.getInstance().getBandLevelLow() / 100));
TextView maxDbTextView = view.findViewById(R.id.plus_db);
maxDbTextView.setText(
String.format("%d dB", EqualizerHelper.getInstance().getBandLevelHigh() / 100));
SeekBar bar = view.findViewById(R.id.seekbar);
bar.setMax(EqualizerHelper.getInstance().getBandLevelHigh() - EqualizerHelper.getInstance()
.getBandLevelLow());
bar.setProgress(
EqualizerHelper.getInstance().getBandLevel((int) band) - EqualizerHelper.getInstance()
.getBandLevelLow());
bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
EqualizerHelper.getInstance().setBandLevel((int) band,
(int) (progress + EqualizerHelper.getInstance().getBandLevelLow()));
if (fromUser) {
mPresets.setSelection(0);
}
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
mLinearLayout.addView(view);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (position == 0) {
return;
}
EqualizerHelper.getInstance().getEqualizer().usePreset((short) (position - 1));
setupUI();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
}

View file

@ -0,0 +1,272 @@
package code.name.monkey.retromusic.ui.activities;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.afollestad.materialcab.MaterialCab;
import code.name.monkey.retromusic.ui.activities.base.AbsSlidingMusicPanelActivity;
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView;
import java.util.ArrayList;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.menu.GenreMenuHelper;
import code.name.monkey.retromusic.interfaces.CabHolder;
import code.name.monkey.retromusic.misc.AppBarStateChangeListener;
import code.name.monkey.retromusic.model.Genre;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.mvp.contract.GenreDetailsContract;
import code.name.monkey.retromusic.mvp.presenter.GenreDetailsPresenter;
import code.name.monkey.retromusic.ui.adapter.song.SongAdapter;
import code.name.monkey.retromusic.util.RetroColorUtil;
import code.name.monkey.retromusic.util.RetroUtil;
import code.name.monkey.retromusic.util.ViewUtil;
/**
* @author Hemanth S (h4h13).
*/
public class GenreDetailsActivity extends AbsSlidingMusicPanelActivity implements
GenreDetailsContract.GenreDetailsView, CabHolder {
public static final String EXTRA_GENRE_ID = "extra_genre_id";
@BindView(R.id.recycler_view)
RecyclerView recyclerView;
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(android.R.id.empty)
TextView empty;
@BindView(R.id.status_bar)
View statusBar;
@BindView(R.id.action_shuffle)
FloatingActionButton shuffleButton;
@BindView(R.id.progress_bar)
ProgressBar progressBar;
@BindView(R.id.app_bar)
AppBarLayout appBarLayout;
@BindView(R.id.collapsing_toolbar)
CollapsingToolbarLayout toolbarLayout;
private Genre genre;
private GenreDetailsPresenter presenter;
private SongAdapter songAdapter;
private MaterialCab cab;
private void checkIsEmpty() {
empty.setVisibility(
songAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE
);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
setDrawUnderStatusbar(true);
super.onCreate(savedInstanceState);
ButterKnife.bind(this);
setStatusbarColorAuto();
setNavigationbarColorAuto();
setTaskDescriptionColorAuto();
setLightNavigationBar(true);
setBottomBarVisibility(View.GONE);
RetroUtil.statusBarHeight(statusBar);
genre = getIntent().getParcelableExtra(EXTRA_GENRE_ID);
presenter = new GenreDetailsPresenter(this, genre.id);
setUpToolBar();
setupRecyclerView();
}
@OnClick({R.id.action_shuffle})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.action_shuffle:
MusicPlayerRemote.openAndShuffleQueue(songAdapter.getDataSet(), true);
break;
}
}
private void setUpToolBar() {
int primaryColor = ThemeStore.primaryColor(this);
toolbar.setBackgroundColor(primaryColor);
appBarLayout.setBackgroundColor(primaryColor);
toolbar.setNavigationIcon(R.drawable.ic_keyboard_backspace_black_24dp);
setSupportActionBar(toolbar);
//noinspection ConstantConditions
getSupportActionBar().setTitle(genre.name);
setTitle(R.string.app_name);
appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() {
@Override
public void onStateChanged(AppBarLayout appBarLayout, AppBarStateChangeListener.State state) {
int color;
switch (state) {
default:
case COLLAPSED:
case EXPANDED:
case IDLE:
color = ATHUtil.resolveColor(GenreDetailsActivity.this, android.R.attr.textColorPrimary);
break;
}
toolbarLayout.setExpandedTitleColor(color);
ToolbarContentTintHelper.colorizeToolbar(toolbar, color, GenreDetailsActivity.this);
}
});
TintHelper.setTintAuto(shuffleButton, ThemeStore.accentColor(this), true);
}
@Override
protected void onResume() {
super.onResume();
presenter.subscribe();
}
@Override
protected void onPause() {
super.onPause();
presenter.unsubscribe();
}
@Override
protected View createContentView() {
return wrapSlidingMusicPanel(R.layout.activity_playlist_detail);
}
@Override
public void loading() {
}
@Override
public void showEmptyView() {
}
@Override
public void completed() {
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_genre_detail, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
}
return GenreMenuHelper.handleMenuClick(this, genre, item);
}
private void setupRecyclerView() {
ViewUtil.setUpFastScrollRecyclerViewColor(this,
((FastScrollRecyclerView) recyclerView), ThemeStore.accentColor(this));
songAdapter = new SongAdapter(this, new ArrayList<Song>(), R.layout.item_list, false, this);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(songAdapter);
songAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
super.onChanged();
checkIsEmpty();
}
});
}
@Override
public void showData(ArrayList<Song> songs) {
songAdapter.swapDataSet(songs);
}
public void showHeartAnimation() {
shuffleButton.clearAnimation();
shuffleButton.setScaleX(0.9f);
shuffleButton.setScaleY(0.9f);
shuffleButton.setVisibility(View.VISIBLE);
shuffleButton.setPivotX(shuffleButton.getWidth() / 2);
shuffleButton.setPivotY(shuffleButton.getHeight() / 2);
shuffleButton.animate()
.setDuration(200)
.setInterpolator(new DecelerateInterpolator())
.scaleX(1.1f)
.scaleY(1.1f)
.withEndAction(() -> shuffleButton.animate()
.setDuration(200)
.setInterpolator(new AccelerateInterpolator())
.scaleX(1f)
.scaleY(1f)
.alpha(1f)
.start())
.start();
}
@NonNull
@Override
public MaterialCab openCab(final int menu, final MaterialCab.Callback callback) {
if (cab != null && cab.isActive()) cab.finish();
cab = new MaterialCab(this, R.id.cab_stub)
.setMenu(menu)
.setCloseDrawableRes(R.drawable.ic_close_white_24dp)
.setBackgroundColor(RetroColorUtil.shiftBackgroundColorForLightText(ThemeStore.primaryColor(this)))
.start(callback);
return cab;
}
@Override
public void onBackPressed() {
if (cab != null && cab.isActive()) cab.finish();
else {
recyclerView.stopScroll();
super.onBackPressed();
}
}
@Override
public void onMediaStoreChanged() {
super.onMediaStoreChanged();
presenter.subscribe();
}
}

View file

@ -0,0 +1,52 @@
package code.name.monkey.retromusic.ui.activities;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.AppBarLayout;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.webkit.WebView;
import butterknife.BindView;
import butterknife.ButterKnife;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.ui.activities.base.AbsBaseActivity;
public class LicenseActivity extends AbsBaseActivity {
@BindView(R.id.license)
WebView mLicense;
@BindView(R.id.toolbar)
Toolbar mToolbar;
@BindView(R.id.appbar)
AppBarLayout mAppbar;
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_license);
ButterKnife.bind(this);
setStatusbarColorAuto();
setNavigationbarColorAuto();
setTaskDescriptionColorAuto();
setLightNavigationBar(true);
mLicense.loadUrl("file:///android_asset/index.html");
mToolbar.setTitle(R.string.licenses);
mToolbar.setNavigationIcon(R.drawable.ic_keyboard_backspace_black_24dp);
mToolbar.setNavigationOnClickListener(view -> onBackPressed());
mToolbar.setBackgroundColor(ThemeStore.primaryColor(this));
mAppbar.setBackgroundColor(ThemeStore.primaryColor(this));
setSupportActionBar(mToolbar);
}
}

View file

@ -0,0 +1,86 @@
package code.name.monkey.retromusic.ui.activities;
import android.os.Bundle;
import android.support.v4.view.ViewCompat;
import android.view.WindowManager;
import com.bumptech.glide.Glide;
import com.r0adkll.slidr.Slidr;
import com.r0adkll.slidr.model.SlidrConfig;
import com.r0adkll.slidr.model.SlidrPosition;
import butterknife.ButterKnife;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget;
import code.name.monkey.retromusic.glide.SongGlideRequest;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.ui.activities.base.AbsMusicServiceActivity;
import code.name.monkey.retromusic.ui.fragments.player.lockscreen.LockScreenPlayerControlsFragment;
public class LockScreenActivity extends AbsMusicServiceActivity {
private LockScreenPlayerControlsFragment mFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
setDrawUnderStatusbar(true);
setContentView(R.layout.activity_lock_screen_old_style);
hideStatusBar();
setStatusbarColorAuto();
setNavigationbarColorAuto();
setTaskDescriptionColorAuto();
setLightNavigationBar(true);
SlidrConfig config = new SlidrConfig.Builder()
.position(SlidrPosition.BOTTOM)
.build();
Slidr.attach(this, config);
ButterKnife.bind(this);
mFragment = (LockScreenPlayerControlsFragment) getSupportFragmentManager().findFragmentById(R.id.playback_controls_fragment);
findViewById(R.id.slide).setTranslationY(100f);
findViewById(R.id.slide).setAlpha(0f);
ViewCompat.animate(findViewById(R.id.slide))
.translationY(0f)
.alpha(1f)
.setDuration(1500)
.start();
findViewById(R.id.root_layout).setBackgroundColor(ThemeStore.primaryColor(this));
}
@Override
public void onPlayingMetaChanged() {
super.onPlayingMetaChanged();
updateSongs();
}
@Override
public void onServiceConnected() {
super.onServiceConnected();
updateSongs();
}
private void updateSongs() {
Song song = MusicPlayerRemote.getCurrentSong();
SongGlideRequest.Builder.from(Glide.with(this), song)
.checkIgnoreMediaStore(this)
.generatePalette(this)
.build().into(new RetroMusicColoredTarget(findViewById(R.id.image)) {
@Override
public void onColorReady(int color) {
mFragment.setDark(color);
}
});
}
}

View file

@ -0,0 +1,392 @@
package code.name.monkey.retromusic.ui.activities;
import android.annotation.SuppressLint;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.Toolbar;
import android.text.InputType;
import android.text.TextUtils;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.bumptech.glide.Glide;
import org.jaudiotagger.tag.FieldKey;
import java.io.File;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget;
import code.name.monkey.retromusic.glide.SongGlideRequest;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.model.lyrics.Lyrics;
import code.name.monkey.retromusic.ui.activities.base.AbsMusicServiceActivity;
import code.name.monkey.retromusic.ui.activities.tageditor.WriteTagsAsyncTask;
import code.name.monkey.retromusic.util.LyricUtil;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.util.RetroUtil;
import code.name.monkey.retromusic.views.LyricView;
import io.reactivex.disposables.CompositeDisposable;
public class LyricsActivity extends AbsMusicServiceActivity implements MusicProgressViewUpdateHelper.Callback {
@BindView(R.id.title)
TextView songTitle;
@BindView(R.id.text)
TextView songText;
@BindView(R.id.lyrics)
LyricView lyricView;
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.offline_lyrics)
TextView offlineLyrics;
@BindView(R.id.actions)
RadioGroup actionsLayout;
@BindView(R.id.gradient_background)
View background;
private MusicProgressViewUpdateHelper updateHelper;
private AsyncTask updateLyricsAsyncTask;
private CompositeDisposable disposable;
private Song song;
private Lyrics lyrics;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lyrics);
ButterKnife.bind(this);
setStatusbarColorAuto();
setNavigationbarColorAuto();
setTaskDescriptionColorAuto();
setLightNavigationBar(true);
updateHelper = new MusicProgressViewUpdateHelper(this, 500, 1000);
setupToolbar();
setupLyricsView();
setupWakelock();
actionsLayout.setOnCheckedChangeListener((group, checkedId) -> selectLyricsTye(checkedId));
}
private void selectLyricsTye(int group) {
RadioButton radioButton = actionsLayout.findViewById(group);
radioButton.setBackgroundTintList(ColorStateList.valueOf(ThemeStore.accentColor(this)));
radioButton.setTextColor(ThemeStore.textColorPrimary(this));
offlineLyrics.setVisibility(View.GONE);
lyricView.setVisibility(View.GONE);
switch (group) {
case R.id.synced_lyrics:
loadLRCLyrics();
lyricView.setVisibility(View.VISIBLE);
break;
default:
case R.id.normal_lyrics:
loadSongLyrics();
offlineLyrics.setVisibility(View.VISIBLE);
break;
}
}
private void loadLRCLyrics() {
if (LyricUtil.isLrcFileExist(song.title, song.artistName)) {
showLyricsLocal(LyricUtil.getLocalLyricFile(song.title, song.artistName));
}
}
private void setupWakelock() {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
private void setupLyricsView() {
disposable = new CompositeDisposable();
//lyricView.setLineSpace(15.0f);
//lyricView.setTextSize(17.0f);
//lyricView.setPlayable(true);
//lyricView.setTranslationY(DensityUtil.getScreenWidth(this) + DensityUtil.dip2px(this, 120));
lyricView.setOnPlayerClickListener((progress, content) -> MusicPlayerRemote.seekTo((int) progress));
//lyricView.setHighLightTextColor(ThemeStore.accentColor(this));
lyricView.setDefaultColor(ContextCompat.getColor(this, R.color.md_grey_400));
//lyricView.setTouchable(false);
lyricView.setHintColor(Color.WHITE);
}
private void setupToolbar() {
toolbar.setBackgroundColor(ThemeStore.primaryColor(this));
toolbar.setTitle("");
toolbar.setNavigationOnClickListener(v -> onBackPressed());
setSupportActionBar(toolbar);
}
@Override
public void onPlayingMetaChanged() {
super.onPlayingMetaChanged();
loadLrcFile();
}
@Override
protected void onResume() {
super.onResume();
updateHelper.start();
}
@Override
protected void onPause() {
super.onPause();
updateHelper.stop();
}
@Override
public void onServiceConnected() {
super.onServiceConnected();
loadLrcFile();
}
@Override
public void onDestroy() {
super.onDestroy();
disposable.clear();
lyricView.setOnPlayerClickListener(null);
if (updateLyricsAsyncTask != null && !updateLyricsAsyncTask.isCancelled()) {
updateLyricsAsyncTask.cancel(true);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
}
return super.onOptionsItemSelected(item);
}
@Override
public void onUpdateProgressViews(int progress, int total) {
lyricView.setCurrentTimeMillis(progress);
}
private void loadLrcFile() {
song = MusicPlayerRemote.getCurrentSong();
songTitle.setText(song.title);
songText.setText(song.artistName);
SongGlideRequest.Builder.from(Glide.with(this), song)
.checkIgnoreMediaStore(this)
.generatePalette(this)
.build()
.into(new RetroMusicColoredTarget(findViewById(R.id.image)) {
@Override
public void onColorReady(int color) {
if (PreferenceUtil.getInstance(LyricsActivity.this).getAdaptiveColor()) {
background.setBackgroundColor(color);
}
}
});
selectLyricsTye(actionsLayout.getCheckedRadioButtonId());
}
private void showLyricsLocal(File file) {
if (file == null) {
lyricView.reset();
lyricView.setVisibility(View.GONE);
} else {
lyricView.setVisibility(View.VISIBLE);
lyricView.setLyricFile(file, "UTF-8");
}
}
@OnClick({R.id.edit_lyrics})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.edit_lyrics:
switch (actionsLayout.getCheckedRadioButtonId()) {
case R.id.synced_lyrics:
showSyncedLyrics();
break;
case R.id.normal_lyrics:
showLyricsSaveDialog();
break;
}
break;
}
}
@SuppressLint("StaticFieldLeak")
private void loadSongLyrics() {
if (updateLyricsAsyncTask != null) updateLyricsAsyncTask.cancel(false);
final Song song = MusicPlayerRemote.getCurrentSong();
updateLyricsAsyncTask = new AsyncTask<Void, Void, Lyrics>() {
@Override
protected Lyrics doInBackground(Void... params) {
String data = MusicUtil.getLyrics(song);
if (TextUtils.isEmpty(data)) {
return null;
}
return Lyrics.parse(song, data);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
lyrics = null;
}
@Override
protected void onPostExecute(Lyrics l) {
lyrics = l;
offlineLyrics.setVisibility(View.VISIBLE);
if (l == null) {
offlineLyrics.setText(R.string.no_lyrics_found);
return;
}
offlineLyrics.setText(l.data);
}
@Override
protected void onCancelled(Lyrics s) {
onPostExecute(null);
}
}.execute();
}
private void showSyncedLyrics() {
String content = "";
try {
content = LyricUtil.getStringFromFile(song.title, song.artistName);
} catch (Exception e) {
e.printStackTrace();
}
new MaterialDialog.Builder(this)
.title("Add lyrics")
.neutralText("Search")
.content("Add time frame lyrics")
.negativeText("Delete")
.onNegative((dialog, which) -> {
LyricUtil.deleteLrcFile(song.title, song.artistName);
loadLrcFile();
})
.onNeutral((dialog, which) -> RetroUtil.openUrl(LyricsActivity.this, getGoogleSearchLrcUrl()))
.inputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE)
.input("Paste lyrics here", content, (dialog, input) -> {
LyricUtil.writeLrcToLoc(song.title, song.artistName, input.toString());
loadLrcFile();
}).show();
}
private String getGoogleSearchLrcUrl() {
String baseUrl = "http://www.google.com/search?";
String query = song.title + "+" + song.artistName;
query = "q=" + query.replace(" ", "+") + " .lrc";
baseUrl += query;
return baseUrl;
}
private void showLyricsSaveDialog() {
String content = "";
if (lyrics == null) {
content = "";
} else {
content = lyrics.data;
}
new MaterialDialog.Builder(this)
.title("Add lyrics")
.neutralText("Search")
.onNeutral(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
RetroUtil.openUrl(LyricsActivity.this, getGoogleSearchUrl(song.title, song.artistName));
}
})
.inputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE)
.input("Paste lyrics here", content, (dialog, input) -> {
Map<FieldKey, String> fieldKeyValueMap = new EnumMap<>(FieldKey.class);
fieldKeyValueMap.put(FieldKey.LYRICS, input.toString());
new WriteTagsAsyncTask(LyricsActivity.this)
.execute(new WriteTagsAsyncTask.LoadingInfo(getSongPaths(song), fieldKeyValueMap, null));
loadLrcFile();
})
.show();
}
private ArrayList<String> getSongPaths(Song song) {
ArrayList<String> paths = new ArrayList<>(1);
paths.add(song.data);
return paths;
}
private String getGoogleSearchUrl(String title, String text) {
String baseUrl = "http://www.google.com/search?";
String query = title + "+" + text;
query = "q=" + query.replace(" ", "+") + " lyrics";
baseUrl += query;
return baseUrl;
}
/*
private void loadLyricsWIki(String title, String artist) {
offlineLyrics.setVisibility(View.GONE);
if (lyricsWikiTask != null) {
lyricsWikiTask.cancel(false);
}
lyricsWikiTask = new ParseLyrics(new ParseLyrics.LyricsCallback() {
@Override
public void onShowLyrics(String lyrics) {
offlineLyrics.setVisibility(View.VISIBLE);
offlineLyrics.setText(lyrics);
}
@Override
public void onError() {
loadSongLyrics();
}
}).execute(title, artist);
}
private void callAgain(final String title, final String artist) {
disposable.clear();
disposable.add(loadLyrics.downloadLrcFile(title, artist, MusicPlayerRemote.getSongDurationMillis())
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.doOnSubscribe(disposable -> {
refresh.startAnimation(rotateAnimation);
})
.subscribe(this::showLyricsLocal, throwable -> {
refresh.clearAnimation();
showLyricsLocal(null);
//loadLyricsWIki(songTitle, artist);
toggleSyncLyrics(View.GONE);
}, () -> {
refresh.clearAnimation();
Toast.makeText(this, "Lyrics downloaded", Toast.LENGTH_SHORT).show();
}));
}
*/
}

View file

@ -0,0 +1,336 @@
package code.name.monkey.retromusic.ui.activities;
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import com.afollestad.materialdialogs.MaterialDialog;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import butterknife.BindView;
import butterknife.ButterKnife;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.SearchQueryHelper;
import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks;
import code.name.monkey.retromusic.loaders.AlbumLoader;
import code.name.monkey.retromusic.loaders.ArtistLoader;
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.service.MusicService;
import code.name.monkey.retromusic.ui.activities.base.AbsSlidingMusicPanelActivity;
import code.name.monkey.retromusic.ui.fragments.mainactivity.LibraryFragment;
import code.name.monkey.retromusic.ui.fragments.mainactivity.home.HomeFragment;
import code.name.monkey.retromusic.util.PreferenceUtil;
import io.reactivex.Observable;
import io.reactivex.disposables.CompositeDisposable;
public class MainActivity extends AbsSlidingMusicPanelActivity implements
SharedPreferences.OnSharedPreferenceChangeListener,
BottomNavigationView.OnNavigationItemSelectedListener {
public static final int APP_INTRO_REQUEST = 2323;
private static final String TAG = "MainActivity";
private static final int APP_USER_INFO_REQUEST = 9003;
private static final int REQUEST_CODE_THEME = 9002;
@Nullable
MainActivityFragmentCallbacks currentFragment;
@BindView(R.id.parent_container)
FrameLayout drawerLayout;
private boolean blockRequestPermissions;
private CompositeDisposable disposable = new CompositeDisposable();
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action != null && action.equals(Intent.ACTION_SCREEN_OFF)) {
if (PreferenceUtil.getInstance(context).getLockScreen() && MusicPlayerRemote.isPlaying()) {
Intent activity = new Intent(context, LockScreenActivity.class);
activity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
activity.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
ActivityCompat.startActivity(context, activity, null);
}
}
}
};
@Override
protected View createContentView() {
@SuppressLint("InflateParams")
View contentView = getLayoutInflater().inflate(R.layout.activity_main_drawer_layout, null);
ViewGroup drawerContent = contentView.findViewById(R.id.drawer_content_container);
drawerContent.addView(wrapSlidingMusicPanel(R.layout.activity_main_content));
return contentView;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
setDrawUnderStatusbar(true);
super.onCreate(savedInstanceState);
ButterKnife.bind(this);
setBottomBarVisibility(View.VISIBLE);
drawerLayout.setOnApplyWindowInsetsListener((view, windowInsets) ->
windowInsets.replaceSystemWindowInsets(0, 0, 0, 0));
if (savedInstanceState == null) {
setCurrentFragment(PreferenceUtil.getInstance(this).getLastPage());
} else {
restoreCurrentFragment();
}
/*if (!RetroApplication.isProVersion() &&
!PreferenceManager.getDefaultSharedPreferences(this)
.getBoolean("shown", false)) {
showPromotionalOffer();
}*/
getBottomNavigationView().setOnNavigationItemSelectedListener(this);
}
@Override
protected void onResume() {
super.onResume();
IntentFilter screenOnOff = new IntentFilter();
screenOnOff.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(broadcastReceiver, screenOnOff);
PreferenceUtil.getInstance(this).registerOnSharedPreferenceChangedListener(this);
if (getIntent().hasExtra("expand")) {
if (getIntent().getBooleanExtra("expand", false)) {
expandPanel();
getIntent().putExtra("expand", false);
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
disposable.clear();
if (broadcastReceiver == null) {
return;
}
unregisterReceiver(broadcastReceiver);
PreferenceUtil.getInstance(this).unregisterOnSharedPreferenceChangedListener(this);
}
public void setCurrentFragment(@Nullable Fragment fragment, boolean isStackAdd) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment, TAG);
if (isStackAdd) {
fragmentTransaction.addToBackStack(TAG);
}
fragmentTransaction.commit();
currentFragment = (MainActivityFragmentCallbacks) fragment;
}
private void restoreCurrentFragment() {
currentFragment = (MainActivityFragmentCallbacks) getSupportFragmentManager()
.findFragmentById(R.id.fragment_container);
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
PreferenceUtil.getInstance(this).setLastPage(item.getItemId());
disposable.add(Observable.just(item.getItemId())
.throttleFirst(3, TimeUnit.SECONDS)
.subscribe(this::setCurrentFragment));
return true;
}
private void setCurrentFragment(int menuItem) {
switch (menuItem) {
case R.id.action_song:
case R.id.action_album:
case R.id.action_artist:
case R.id.action_playlist:
setCurrentFragment(LibraryFragment.newInstance(menuItem), false);
break;
default:
case R.id.action_home:
setCurrentFragment(HomeFragment.newInstance(), false);
break;
}
}
private void handlePlaybackIntent(@Nullable Intent intent) {
if (intent == null) {
return;
}
Uri uri = intent.getData();
String mimeType = intent.getType();
boolean handled = false;
if (intent.getAction() != null && intent.getAction()
.equals(MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH)) {
final ArrayList<Song> songs = SearchQueryHelper.getSongs(this, intent.getExtras());
if (MusicPlayerRemote.getShuffleMode() == MusicService.SHUFFLE_MODE_SHUFFLE) {
MusicPlayerRemote.openAndShuffleQueue(songs, true);
} else {
MusicPlayerRemote.openQueue(songs, 0, true);
}
handled = true;
}
if (uri != null && uri.toString().length() > 0) {
MusicPlayerRemote.playFromUri(uri);
handled = true;
} else if (MediaStore.Audio.Playlists.CONTENT_TYPE.equals(mimeType)) {
final int id = (int) parseIdFromIntent(intent, "playlistId", "playlist");
if (id >= 0) {
int position = intent.getIntExtra("position", 0);
ArrayList<Song> songs = new ArrayList<>(
PlaylistSongsLoader.getPlaylistSongList(this, id).blockingFirst());
MusicPlayerRemote.openQueue(songs, position, true);
handled = true;
}
} else if (MediaStore.Audio.Albums.CONTENT_TYPE.equals(mimeType)) {
final int id = (int) parseIdFromIntent(intent, "albumId", "album");
if (id >= 0) {
int position = intent.getIntExtra("position", 0);
MusicPlayerRemote
.openQueue(AlbumLoader.getAlbum(this, id).blockingFirst().songs, position, true);
handled = true;
}
} else if (MediaStore.Audio.Artists.CONTENT_TYPE.equals(mimeType)) {
final int id = (int) parseIdFromIntent(intent, "artistId", "artist");
if (id >= 0) {
int position = intent.getIntExtra("position", 0);
MusicPlayerRemote.openQueue(ArtistLoader.getArtist(this, id).blockingFirst().getSongs(), position, true);
handled = true;
}
}
if (handled) {
setIntent(new Intent());
}
}
private long parseIdFromIntent(@NonNull Intent intent, String longKey, String stringKey) {
long id = intent.getLongExtra(longKey, -1);
if (id < 0) {
String idString = intent.getStringExtra(stringKey);
if (idString != null) {
try {
id = Long.parseLong(idString);
} catch (NumberFormatException e) {
Log.e(TAG, e.getMessage());
}
}
}
return id;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case APP_INTRO_REQUEST:
blockRequestPermissions = false;
if (!hasPermissions()) {
requestPermissions();
}
break;
case REQUEST_CODE_THEME:
case APP_USER_INFO_REQUEST:
postRecreate();
break;
}
}
@Override
public boolean handleBackPress() {
return super.handleBackPress() || (currentFragment != null &&
currentFragment.handleBackPress());
}
@Override
public void onServiceConnected() {
super.onServiceConnected();
handlePlaybackIntent(getIntent());
}
@Override
protected void requestPermissions() {
if (!blockRequestPermissions) {
super.requestPermissions();
}
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
return super.onOptionsItemSelected(item);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equalsIgnoreCase(PreferenceUtil.GENERAL_THEME) ||
key.equalsIgnoreCase(PreferenceUtil.ADAPTIVE_COLOR_APP) ||
key.equalsIgnoreCase(PreferenceUtil.DOMINANT_COLOR) ||
key.equalsIgnoreCase(PreferenceUtil.USER_NAME) ||
key.equalsIgnoreCase(PreferenceUtil.TOGGLE_FULL_SCREEN) ||
key.equalsIgnoreCase(PreferenceUtil.TOGGLE_VOLUME) ||
key.equalsIgnoreCase(PreferenceUtil.TOGGLE_TAB_TITLES) ||
key.equalsIgnoreCase(PreferenceUtil.ROUND_CORNERS) ||
key.equals(PreferenceUtil.CAROUSEL_EFFECT) ||
key.equals(PreferenceUtil.NOW_PLAYING_SCREEN_ID) ||
key.equals(PreferenceUtil.TOGGLE_GENRE) ||
key.equals(PreferenceUtil.BANNER_IMAGE_PATH) ||
key.equals(PreferenceUtil.PROFILE_IMAGE_PATH) ||
key.equals(PreferenceUtil.CIRCULAR_ALBUM_ART) ||
key.equals(PreferenceUtil.KEEP_SCREEN_ON) ||
key.equals(PreferenceUtil.TOGGLE_SEPARATE_LINE)) {
postRecreate();
}
}
private void showPromotionalOffer() {
new MaterialDialog.Builder(this)
.positiveText("Buy")
.onPositive((dialog, which) ->
startActivity(new Intent(MainActivity.this, ProVersionActivity.class)))
.negativeText(android.R.string.cancel)
.customView(R.layout.dialog_promotional_offer, false)
.dismissListener(dialog -> {
PreferenceManager.getDefaultSharedPreferences(MainActivity.this)
.edit()
.putBoolean("shown", true)
.apply();
})
.show();
}
}

View file

@ -0,0 +1,68 @@
package code.name.monkey.retromusic.ui.activities;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.design.widget.AppBarLayout;
import android.support.v7.widget.Toolbar;
import android.widget.TextView;
import butterknife.BindDrawable;
import butterknife.BindString;
import butterknife.BindView;
import butterknife.ButterKnife;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.ui.activities.base.AbsMusicServiceActivity;
import code.name.monkey.retromusic.ui.fragments.PlayingQueueFragment;
import code.name.monkey.retromusic.util.MusicUtil;
public class PlayingQueueActivity extends AbsMusicServiceActivity {
@BindView(R.id.toolbar)
Toolbar mToolbar;
@BindDrawable(R.drawable.ic_close_white_24dp)
Drawable mClose;
@BindView(R.id.player_queue_sub_header)
TextView mPlayerQueueSubHeader;
@BindString(R.string.queue)
String queue;
@BindView(R.id.app_bar)
AppBarLayout mAppBarLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_playing_queue);
ButterKnife.bind(this);
setStatusbarColorAuto();
setNavigationbarColorAuto();
setTaskDescriptionColorAuto();
setLightNavigationBar(true);
setupToolbar();
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, new PlayingQueueFragment())
.commit();
}
}
protected String getUpNextAndQueueTime() {
return getResources().getString(R.string.up_next) + "" + MusicUtil
.getReadableDurationString(
MusicPlayerRemote.getQueueDurationMillis(MusicPlayerRemote.getPosition()));
}
private void setupToolbar() {
mPlayerQueueSubHeader.setText(getUpNextAndQueueTime());
mPlayerQueueSubHeader.setTextColor(ThemeStore.accentColor(this));
mAppBarLayout.setBackgroundColor(ThemeStore.primaryColor(this));
mToolbar.setBackgroundColor(ThemeStore.primaryColor(this));
mToolbar.setNavigationIcon(mClose);
setSupportActionBar(mToolbar);
setTitle(queue);
mToolbar.setNavigationOnClickListener(v -> onBackPressed());
}
}

View file

@ -0,0 +1,353 @@
package code.name.monkey.retromusic.ui.activities;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.TextView;
import com.afollestad.materialcab.MaterialCab;
import com.h6ah4i.android.widget.advrecyclerview.animator.GeneralItemAnimator;
import com.h6ah4i.android.widget.advrecyclerview.animator.RefactoredDefaultItemAnimator;
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager;
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils;
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView;
import java.util.ArrayList;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper;
import code.name.monkey.retromusic.interfaces.CabHolder;
import code.name.monkey.retromusic.loaders.PlaylistLoader;
import code.name.monkey.retromusic.misc.AppBarStateChangeListener;
import code.name.monkey.retromusic.model.AbsCustomPlaylist;
import code.name.monkey.retromusic.model.Playlist;
import code.name.monkey.retromusic.model.PlaylistSong;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.mvp.contract.PlaylistSongsContract;
import code.name.monkey.retromusic.mvp.presenter.PlaylistSongsPresenter;
import code.name.monkey.retromusic.ui.activities.base.AbsSlidingMusicPanelActivity;
import code.name.monkey.retromusic.ui.adapter.song.OrderablePlaylistSongAdapter;
import code.name.monkey.retromusic.ui.adapter.song.PlaylistSongAdapter;
import code.name.monkey.retromusic.ui.adapter.song.SongAdapter;
import code.name.monkey.retromusic.util.PlaylistsUtil;
import code.name.monkey.retromusic.util.RetroColorUtil;
import code.name.monkey.retromusic.util.RetroUtil;
import code.name.monkey.retromusic.util.ViewUtil;
public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity implements CabHolder,
PlaylistSongsContract.PlaylistSongsView {
@NonNull
public static String EXTRA_PLAYLIST = "extra_playlist";
@BindView(R.id.recycler_view)
RecyclerView recyclerView;
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(android.R.id.empty)
TextView empty;
@BindView(R.id.action_shuffle)
FloatingActionButton shuffleButton;
@BindView(R.id.app_bar)
AppBarLayout appBarLayout;
@BindView(R.id.collapsing_toolbar)
CollapsingToolbarLayout toolbarLayout;
@BindView(R.id.status_bar)
View statusBar;
private Playlist playlist;
private MaterialCab cab;
private SongAdapter adapter;
private RecyclerView.Adapter wrappedAdapter;
private RecyclerViewDragDropManager recyclerViewDragDropManager;
private PlaylistSongsPresenter songsPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
setDrawUnderStatusbar(true);
super.onCreate(savedInstanceState);
ButterKnife.bind(this);
RetroUtil.statusBarHeight(statusBar);
setStatusbarColorAuto();
setNavigationbarColorAuto();
setTaskDescriptionColorAuto();
setLightNavigationBar(true);
setBottomBarVisibility(View.GONE);
playlist = getIntent().getExtras().getParcelable(EXTRA_PLAYLIST);
if (playlist != null) {
songsPresenter = new PlaylistSongsPresenter(this, playlist);
}
setUpToolBar();
setUpRecyclerView();
}
public void showHeartAnimation() {
shuffleButton.clearAnimation();
shuffleButton.setScaleX(0.9f);
shuffleButton.setScaleY(0.9f);
shuffleButton.setVisibility(View.VISIBLE);
shuffleButton.setPivotX(shuffleButton.getWidth() / 2);
shuffleButton.setPivotY(shuffleButton.getHeight() / 2);
shuffleButton.animate()
.setDuration(200)
.setInterpolator(new DecelerateInterpolator())
.scaleX(1.1f)
.scaleY(1.1f)
.withEndAction(() -> shuffleButton.animate()
.setDuration(200)
.setInterpolator(new AccelerateInterpolator())
.scaleX(1f)
.scaleY(1f)
.alpha(1f)
.start())
.start();
}
@Override
protected View createContentView() {
return wrapSlidingMusicPanel(R.layout.activity_playlist_detail);
}
private void setUpRecyclerView() {
ViewUtil.setUpFastScrollRecyclerViewColor(this, ((FastScrollRecyclerView) recyclerView),
ThemeStore.accentColor(this));
recyclerView.setLayoutManager(new LinearLayoutManager(this));
if (playlist instanceof AbsCustomPlaylist) {
adapter = new PlaylistSongAdapter(this, new ArrayList<Song>(), R.layout.item_list, false,
this);
recyclerView.setAdapter(adapter);
} else {
recyclerViewDragDropManager = new RecyclerViewDragDropManager();
final GeneralItemAnimator animator = new RefactoredDefaultItemAnimator();
adapter = new OrderablePlaylistSongAdapter(this, new ArrayList<PlaylistSong>(),
R.layout.item_list, false, this, (fromPosition, toPosition) -> {
if (PlaylistsUtil
.moveItem(PlaylistDetailActivity.this, playlist.id, fromPosition, toPosition)) {
Song song = adapter.getDataSet().remove(fromPosition);
adapter.getDataSet().add(toPosition, song);
adapter.notifyItemMoved(fromPosition, toPosition);
}
});
wrappedAdapter = recyclerViewDragDropManager.createWrappedAdapter(adapter);
recyclerView.setAdapter(wrappedAdapter);
recyclerView.setItemAnimator(animator);
recyclerViewDragDropManager.attachRecyclerView(recyclerView);
}
adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
super.onChanged();
checkIsEmpty();
}
});
}
@Override
protected void onResume() {
super.onResume();
songsPresenter.subscribe();
}
private void setUpToolBar() {
int primaryColor = ThemeStore.primaryColor(this);
toolbar.setBackgroundColor(primaryColor);
appBarLayout.setBackgroundColor(primaryColor);
toolbar.setNavigationIcon(R.drawable.ic_keyboard_backspace_black_24dp);
setSupportActionBar(toolbar);
//noinspection ConstantConditions
getSupportActionBar().setTitle(playlist.name);
appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() {
@Override
public void onStateChanged(AppBarLayout appBarLayout, AppBarStateChangeListener.State state) {
int color;
switch (state) {
default:
case COLLAPSED:
case EXPANDED:
case IDLE:
color = ThemeStore.textColorPrimary(PlaylistDetailActivity.this);
break;
}
toolbarLayout.setExpandedTitleColor(color);
ToolbarContentTintHelper.colorizeToolbar(toolbar, color, PlaylistDetailActivity.this);
}
});
TintHelper.setTintAuto(shuffleButton, ThemeStore.accentColor(this), true);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(
playlist instanceof AbsCustomPlaylist ? R.menu.menu_smart_playlist_detail
: R.menu.menu_playlist_detail, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();
switch (id) {
case android.R.id.home:
onBackPressed();
return true;
}
return PlaylistMenuHelper.handleMenuClick(this, playlist, item);
}
@NonNull
@Override
public MaterialCab openCab(final int menu, final MaterialCab.Callback callback) {
if (cab != null && cab.isActive()) {
cab.finish();
}
cab = new MaterialCab(this, R.id.cab_stub)
.setMenu(menu)
.setCloseDrawableRes(R.drawable.ic_close_white_24dp)
.setBackgroundColor(
RetroColorUtil.shiftBackgroundColorForLightText(ThemeStore.primaryColor(this)))
.start(callback);
return cab;
}
@Override
public void onBackPressed() {
if (cab != null && cab.isActive()) {
cab.finish();
} else {
recyclerView.stopScroll();
super.onBackPressed();
}
}
@Override
public void onMediaStoreChanged() {
super.onMediaStoreChanged();
if (!(playlist instanceof AbsCustomPlaylist)) {
// Playlist deleted
if (!PlaylistsUtil.doesPlaylistExist(this, playlist.id)) {
finish();
return;
}
// Playlist renamed
final String playlistName = PlaylistsUtil.getNameForPlaylist(this, playlist.id);
if (!playlistName.equals(playlist.name)) {
playlist = PlaylistLoader.getPlaylist(this, playlist.id).blockingFirst();
setToolbarTitle(playlist.name);
}
}
songsPresenter.subscribe();
}
private void setToolbarTitle(String title) {
//noinspection ConstantConditions
getSupportActionBar().setTitle(title);
}
private void checkIsEmpty() {
empty.setVisibility(
adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE
);
}
@Override
public void onPause() {
if (recyclerViewDragDropManager != null) {
recyclerViewDragDropManager.cancelDrag();
}
super.onPause();
songsPresenter.unsubscribe();
}
@Override
public void onDestroy() {
if (recyclerViewDragDropManager != null) {
recyclerViewDragDropManager.release();
recyclerViewDragDropManager = null;
}
if (recyclerView != null) {
recyclerView.setItemAnimator(null);
recyclerView.setAdapter(null);
recyclerView = null;
}
if (wrappedAdapter != null) {
WrapperAdapterUtils.releaseAll(wrappedAdapter);
wrappedAdapter = null;
}
adapter = null;
super.onDestroy();
}
@Override
public void onPlayingMetaChanged() {
super.onPlayingMetaChanged();
songsPresenter.subscribe();
}
@Override
public void loading() {
}
@Override
public void showEmptyView() {
empty.setVisibility(View.VISIBLE);
}
@Override
public void completed() {
}
@Override
public void showData(ArrayList<Song> songs) {
adapter.swapDataSet(songs);
}
@OnClick(R.id.action_shuffle)
public void onViewClicked() {
showHeartAnimation();
if (adapter.getDataSet().isEmpty()) {
return;
}
MusicPlayerRemote.openAndShuffleQueue(adapter.getDataSet(), true);
}
}

View file

@ -0,0 +1,203 @@
package code.name.monkey.retromusic.ui.activities;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.AppBarLayout;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import com.anjlab.android.iab.v3.BillingProcessor;
import com.anjlab.android.iab.v3.TransactionDetails;
import java.lang.ref.WeakReference;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.BuildConfig;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.RetroApplication;
import code.name.monkey.retromusic.ui.activities.base.AbsBaseActivity;
import code.name.monkey.retromusic.util.RetroUtil;
/**
* @author Hemanth S (h4h13).
*/
public class ProVersionActivity extends AbsBaseActivity implements
BillingProcessor.IBillingHandler {
private static final String TAG = "ProVersionActivity";
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.restore_button)
View restoreButton;
@BindView(R.id.purchase_button)
View purchaseButton;
@BindView(R.id.app_bar)
AppBarLayout appBar;
@BindView(R.id.status_bar)
View statusBar;
private BillingProcessor billingProcessor;
private AsyncTask restorePurchaseAsyncTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pro_version);
setDrawUnderStatusbar(true);
ButterKnife.bind(this);
RetroUtil.statusBarHeight(statusBar);
setStatusbarColorAuto();
setNavigationbarColorAuto();
setTaskDescriptionColorAuto();
setLightNavigationBar(true);
int primaryColor = ThemeStore.primaryColor(this);
toolbar.setBackgroundColor(primaryColor);
appBar.setBackgroundColor(primaryColor);
toolbar.setNavigationIcon(R.drawable.ic_keyboard_backspace_black_24dp);
toolbar.setNavigationOnClickListener(v -> onBackPressed());
setSupportActionBar(toolbar);
//noinspection ConstantConditions
getSupportActionBar().setTitle("RetroMusic Pro");
restoreButton.setEnabled(false);
purchaseButton.setEnabled(false);
billingProcessor = new BillingProcessor(this, BuildConfig.GOOGLE_PLAY_LICENSE_KEY, this);
}
private void restorePurchase() {
if (restorePurchaseAsyncTask != null) {
restorePurchaseAsyncTask.cancel(false);
}
restorePurchaseAsyncTask = new RestorePurchaseAsyncTask(this).execute();
}
@OnClick({R.id.restore_button, R.id.purchase_button})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.restore_button:
if (restorePurchaseAsyncTask == null
|| restorePurchaseAsyncTask.getStatus() != AsyncTask.Status.RUNNING) {
restorePurchase();
}
break;
case R.id.purchase_button:
billingProcessor.purchase(ProVersionActivity.this, RetroApplication.PRO_VERSION_PRODUCT_ID);
break;
}
}
@Override
public void onProductPurchased(@NonNull String productId, @Nullable TransactionDetails details) {
Toast.makeText(this, R.string.thank_you, Toast.LENGTH_SHORT).show();
setResult(RESULT_OK);
}
@Override
public void onPurchaseHistoryRestored() {
if (RetroApplication.isProVersion()) {
Toast.makeText(this, R.string.restored_previous_purchase_please_restart, Toast.LENGTH_LONG)
.show();
setResult(RESULT_OK);
} else {
Toast.makeText(this, R.string.no_purchase_found, Toast.LENGTH_SHORT).show();
}
}
@Override
public void onBillingError(int errorCode, @Nullable Throwable error) {
Log.e(TAG, "Billing error: code = " + errorCode, error);
}
@Override
public void onBillingInitialized() {
restoreButton.setEnabled(true);
purchaseButton.setEnabled(true);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (!billingProcessor.handleActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
break;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onDestroy() {
if (billingProcessor != null) {
billingProcessor.release();
}
super.onDestroy();
}
private static class RestorePurchaseAsyncTask extends AsyncTask<Void, Void, Boolean> {
private final WeakReference<ProVersionActivity> buyActivityWeakReference;
RestorePurchaseAsyncTask(ProVersionActivity purchaseActivity) {
this.buyActivityWeakReference = new WeakReference<>(purchaseActivity);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
ProVersionActivity purchaseActivity = buyActivityWeakReference.get();
if (purchaseActivity != null) {
Toast.makeText(purchaseActivity, R.string.restoring_purchase, Toast.LENGTH_SHORT).show();
} else {
cancel(false);
}
}
@Override
protected Boolean doInBackground(Void... params) {
ProVersionActivity purchaseActivity = buyActivityWeakReference.get();
if (purchaseActivity != null) {
return purchaseActivity.billingProcessor.loadOwnedPurchasesFromGoogle();
}
cancel(false);
return null;
}
@Override
protected void onPostExecute(Boolean b) {
super.onPostExecute(b);
ProVersionActivity purchaseActivity = buyActivityWeakReference.get();
if (purchaseActivity == null || b == null) {
return;
}
if (b) {
purchaseActivity.onPurchaseHistoryRestored();
} else {
Toast.makeText(purchaseActivity, R.string.could_not_restore_purchase, Toast.LENGTH_SHORT)
.show();
}
}
}
}

View file

@ -0,0 +1,267 @@
package code.name.monkey.retromusic.ui.activities;
import android.app.SearchManager;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.support.annotation.NonNull;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CoordinatorLayout;
import android.support.transition.TransitionManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView.OnQueryTextListener;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.TextView.BufferType;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Locale;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.mvp.contract.SearchContract;
import code.name.monkey.retromusic.mvp.presenter.SearchPresenter;
import code.name.monkey.retromusic.ui.activities.base.AbsMusicServiceActivity;
import code.name.monkey.retromusic.ui.adapter.SearchAdapter;
import code.name.monkey.retromusic.util.RetroUtil;
import code.name.monkey.retromusic.util.ViewUtil;
public class SearchActivity extends AbsMusicServiceActivity implements OnQueryTextListener,
SearchContract.SearchView, TextWatcher {
public static final String TAG = SearchActivity.class.getSimpleName();
public static final String QUERY = "query";
private static final int REQ_CODE_SPEECH_INPUT = 9002;
@BindView(R.id.voice_search)
View micIcon;
@BindView(R.id.recycler_view)
RecyclerView recyclerView;
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(android.R.id.empty)
TextView empty;
@BindView(R.id.search_view)
EditText searchView;
@BindView(R.id.root)
CoordinatorLayout container;
@BindView(R.id.appbar)
AppBarLayout appbar;
@BindView(R.id.status_bar)
View statusBar;
private SearchPresenter searchPresenter;
private SearchAdapter adapter;
private String query;
private boolean isMicSearch = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
setDrawUnderStatusbar(true);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
ButterKnife.bind(this);
ViewUtil.setStatusBarHeight(this, statusBar);
searchPresenter = new SearchPresenter(this);
setStatusbarColorAuto();
setNavigationbarColorAuto();
setTaskDescriptionColorAuto();
setLightNavigationBar(true);
setupRecyclerview();
setUpToolBar();
setupSearchView();
if (savedInstanceState != null) {
query = savedInstanceState.getString(QUERY);
searchPresenter.search(query);
}
if (getIntent().getBooleanExtra("mic_search", false)) {
startMicSearch();
isMicSearch = true;
}
}
private void setupRecyclerview() {
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new SearchAdapter(this, Collections.emptyList());
adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
super.onChanged();
empty.setVisibility(adapter.getItemCount() < 1 ? View.VISIBLE : View.GONE);
}
});
recyclerView.setAdapter(adapter);
}
private void setupSearchView() {
SearchManager searchManager = (SearchManager) getSystemService(SEARCH_SERVICE);
if (searchManager != null) {
searchView.addTextChangedListener(this);
}
}
@Override
protected void onResume() {
super.onResume();
//Log.i(TAG, "onResume: " + query);
searchPresenter.subscribe();
searchPresenter.search(query);
}
@Override
public void onDestroy() {
super.onDestroy();
searchPresenter.unsubscribe();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(QUERY, query);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
searchPresenter.search(savedInstanceState.getString(QUERY, ""));
}
private void setUpToolBar() {
int primaryColor = ThemeStore.primaryColor(this);
toolbar.setBackgroundColor(primaryColor);
appbar.setBackgroundColor(primaryColor);
setSupportActionBar(toolbar);
//noinspection ConstantConditions
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
}
return super.onOptionsItemSelected(item);
}
private void search(@NonNull String query) {
this.query = query.trim();
TransitionManager.beginDelayedTransition(toolbar);
micIcon.setVisibility(query.length() > 0 ? View.GONE : View.VISIBLE);
searchPresenter.search(query);
}
@Override
public void onMediaStoreChanged() {
super.onMediaStoreChanged();
searchPresenter.search(query);
}
@Override
public boolean onQueryTextSubmit(String query) {
hideSoftKeyboard();
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
search(newText);
return false;
}
private void hideSoftKeyboard() {
RetroUtil.hideSoftKeyboard(SearchActivity.this);
if (searchView != null) {
searchView.clearFocus();
}
}
@Override
public void loading() {
}
@Override
public void showEmptyView() {
adapter.swapDataSet(new ArrayList<>());
}
@Override
public void completed() {
}
@Override
public void showData(ArrayList<Object> list) {
adapter.swapDataSet(list);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQ_CODE_SPEECH_INPUT: {
if (resultCode == RESULT_OK && null != data) {
ArrayList<String> result = data
.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
query = result.get(0);
searchView.setText(query, BufferType.EDITABLE);
searchPresenter.search(query);
}
break;
}
}
}
@OnClick(R.id.voice_search)
void searchImageView() {
startMicSearch();
}
private void startMicSearch() {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent
.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, getString(R.string.speech_prompt));
try {
startActivityForResult(intent, REQ_CODE_SPEECH_INPUT);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
Toast.makeText(this, getString(R.string.speech_not_supported), Toast.LENGTH_SHORT).show();
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence newText, int start, int before, int count) {
search(newText.toString());
}
@Override
public void afterTextChanged(Editable s) {
}
}

View file

@ -0,0 +1,150 @@
package code.name.monkey.retromusic.ui.activities;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.AppBarLayout;
import android.support.transition.TransitionManager;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.widget.FrameLayout;
import com.afollestad.materialdialogs.color.ColorChooserDialog;
import butterknife.BindView;
import butterknife.ButterKnife;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager;
import code.name.monkey.retromusic.ui.activities.base.AbsBaseActivity;
import code.name.monkey.retromusic.ui.fragments.settings.MainSettingsFragment;
import code.name.monkey.retromusic.util.PreferenceUtil;
public class SettingsActivity extends AbsBaseActivity implements ColorChooserDialog.ColorCallback {
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.app_bar)
AppBarLayout appBarLayout;
@BindView(R.id.detail_content_frame)
@Nullable
FrameLayout detailsFrame;
private FragmentManager fragmentManager = getSupportFragmentManager();
@Override
public void onColorSelection(@NonNull ColorChooserDialog dialog, @ColorInt int selectedColor) {
switch (dialog.getTitle()) {
case R.string.primary_color:
int theme = ColorUtil.isColorLight(selectedColor) ?
PreferenceUtil.getThemeResFromPrefValue("light") :
PreferenceUtil.getThemeResFromPrefValue("dark");
ThemeStore.editTheme(this).activityTheme(theme).primaryColor(selectedColor).commit();
break;
case R.string.accent_color:
ThemeStore.editTheme(this).accentColor(selectedColor).commit();
break;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
new DynamicShortcutManager(this).updateDynamicShortcuts();
}
recreate();
}
@Override
public void onColorChooserDismissed(@NonNull ColorChooserDialog dialog) {
}
@Override
protected void onCreate(@Nullable Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_settings);
ButterKnife.bind(this);
setStatusbarColorAuto();
setNavigationbarColorAuto();
setTaskDescriptionColorAuto();
setLightNavigationBar(true);
setupToolbar();
if (bundle == null) {
fragmentManager.beginTransaction().replace(R.id.content_frame, new MainSettingsFragment()).commit();
} else {
restoreFragment();
}
}
private void setupToolbar() {
appBarLayout.setBackgroundColor(ThemeStore.primaryColor(this));
toolbar.setBackgroundColor(ThemeStore.primaryColor(this));
toolbar.setNavigationOnClickListener(v -> onBackPressed());
setTitle(R.string.action_settings);
setSupportActionBar(toolbar);
}
private void restoreFragment() {
toolbar.setNavigationIcon(R.drawable.ic_keyboard_backspace_black_24dp);
if (fragmentManager.getBackStackEntryCount() > 0) {
appBarLayout.setExpanded(false, true);
} else {
appBarLayout.setExpanded(true, true);
}
setupToolbar();
}
public void setupFragment(Fragment fragment) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction()
.setCustomAnimations(R.animator.slide_up, 0, 0, R.animator.slide_down);
if (detailsFrame == null) {
fragmentTransaction.replace(R.id.content_frame, fragment, fragment.getTag());
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
} else {
fragmentTransaction.replace(R.id.detail_content_frame, fragment, fragment.getTag());
fragmentTransaction.commit();
}
fragmentManager.addOnBackStackChangedListener(() -> {
if (fragmentManager.getBackStackEntryCount() > 0) {
appBarLayout.setExpanded(false, true);
} else {
appBarLayout.setExpanded(true, true);
}
setupToolbar();
});
}
@Override
public void onBackPressed() {
if (fragmentManager.getBackStackEntryCount() == 0) {
super.onBackPressed();
} else {
fragmentManager.popBackStack();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
public void addAppbarLayoutElevation(float v) {
TransitionManager.beginDelayedTransition(appBarLayout);
appBarLayout.setElevation(v);
}
}

View file

@ -0,0 +1,318 @@
package code.name.monkey.retromusic.ui.activities;
import android.content.Intent;
import android.graphics.Paint;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.AppBarLayout;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.afollestad.materialdialogs.internal.MDTintHelper;
import com.anjlab.android.iab.v3.BillingProcessor;
import com.anjlab.android.iab.v3.SkuDetails;
import com.anjlab.android.iab.v3.TransactionDetails;
import org.json.JSONException;
import org.json.JSONObject;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.retromusic.BuildConfig;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.ui.activities.base.AbsBaseActivity;
import code.name.monkey.retromusic.util.RetroUtil;
import code.name.monkey.retromusic.views.IconImageView;
import static code.name.monkey.retromusic.Constants.PAYPAL_ME_URL;
/**
* @author Hemanth S (h4h13).
*/
public class SupportDevelopmentActivity extends AbsBaseActivity implements BillingProcessor.IBillingHandler {
public static final String TAG = SupportDevelopmentActivity.class.getSimpleName();
private static final int DONATION_PRODUCT_IDS = R.array.donation_ids;
@BindView(R.id.progress)
ProgressBar mProgressBar;
@BindView(R.id.progress_container)
View mProgressContainer;
@BindView(R.id.list)
RecyclerView mListView;
@BindView(R.id.toolbar)
Toolbar mToolbar;
@BindView(R.id.app_bar)
AppBarLayout mAppBarLayout;
@BindView(R.id.root)
ViewGroup mViewGroup;
private BillingProcessor mBillingProcessor;
private AsyncTask skuDetailsLoadAsyncTask;
private static List<SkuDetails> getDetails() {
List<SkuDetails> skuDetails = new ArrayList<>();
JSONObject jsonObject = new JSONObject();
try {
for (int i = 0; i < 6; i++) {
jsonObject.put("songTitle", "Coffee");
jsonObject.put("price", "$100");
jsonObject.put("description", "" + i);
skuDetails.add(new SkuDetails(jsonObject));
}
} catch (JSONException e) {
e.printStackTrace();
}
return skuDetails;
}
private void donate(int i) {
final String[] ids = getResources().getStringArray(DONATION_PRODUCT_IDS);
mBillingProcessor.purchase(this, ids[i]);
}
@OnClick(R.id.donate)
void donate() {
RetroUtil.openUrl(this, PAYPAL_ME_URL);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_donation);
ButterKnife.bind(this);
setStatusbarColorAuto();
setNavigationbarColorAuto();
setTaskDescriptionColorAuto();
setLightNavigationBar(true);
int primaryColor = ThemeStore.primaryColor(this);
mAppBarLayout.setBackgroundColor(primaryColor);
mToolbar.setBackgroundColor(primaryColor);
setSupportActionBar(mToolbar);
//noinspection ConstantConditions
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mToolbar.setNavigationOnClickListener(view -> onBackPressed());
mBillingProcessor
= new BillingProcessor(this, BuildConfig.GOOGLE_PLAY_LICENSE_KEY, this);
MDTintHelper.setTint(mProgressBar, ThemeStore.accentColor(this));
((TextView) findViewById(R.id.donation)).setTextColor(ThemeStore.accentColor(this));
}
@Override
public void onBillingInitialized() {
loadSkuDetails();
}
private void loadSkuDetails() {
if (skuDetailsLoadAsyncTask != null) {
skuDetailsLoadAsyncTask.cancel(false);
}
skuDetailsLoadAsyncTask = new SkuDetailsLoadAsyncTask(this).execute();
}
@Override
public void onProductPurchased(@NonNull String productId, TransactionDetails details) {
//loadSkuDetails();
Toast.makeText(this, R.string.thank_you, Toast.LENGTH_SHORT).show();
}
@Override
public void onBillingError(int errorCode, Throwable error) {
Log.e(TAG, "Billing error: code = " + errorCode, error);
}
@Override
public void onPurchaseHistoryRestored() {
//loadSkuDetails();
Toast.makeText(this, R.string.restored_previous_purchases, Toast.LENGTH_SHORT).show();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (!mBillingProcessor.handleActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
@Override
public void onDestroy() {
if (mBillingProcessor != null) {
mBillingProcessor.release();
}
if (skuDetailsLoadAsyncTask != null) {
skuDetailsLoadAsyncTask.cancel(true);
}
super.onDestroy();
}
private static class SkuDetailsLoadAsyncTask extends AsyncTask<Void, Void, List<SkuDetails>> {
private final WeakReference<SupportDevelopmentActivity> donationDialogWeakReference;
public SkuDetailsLoadAsyncTask(SupportDevelopmentActivity donationsDialog) {
this.donationDialogWeakReference = new WeakReference<>(donationsDialog);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
SupportDevelopmentActivity dialog = donationDialogWeakReference.get();
if (dialog == null) return;
dialog.mProgressContainer.setVisibility(View.VISIBLE);
dialog.mListView.setVisibility(View.GONE);
}
@Override
protected List<SkuDetails> doInBackground(Void... params) {
SupportDevelopmentActivity dialog = donationDialogWeakReference.get();
if (dialog != null) {
final String[] ids = dialog.getResources().getStringArray(DONATION_PRODUCT_IDS);
return dialog.mBillingProcessor.getPurchaseListingDetails(new ArrayList<>(Arrays.asList(ids)));
}
cancel(false);
return null;
}
@Override
protected void onPostExecute(List<SkuDetails> skuDetails) {
super.onPostExecute(skuDetails);
SupportDevelopmentActivity dialog = donationDialogWeakReference.get();
if (dialog == null) return;
if (skuDetails == null || skuDetails.isEmpty()) {
//Toast.makeText(dialog, "Error loading items", Toast.LENGTH_SHORT).show();
//dialog.finish();
dialog.mProgressContainer.setVisibility(View.GONE);
return;
}
//noinspection ConstantConditions
dialog.mProgressContainer.setVisibility(View.GONE);
dialog.mListView.setItemAnimator(new DefaultItemAnimator());
dialog.mListView.setLayoutManager(new GridLayoutManager(dialog, 2));
dialog.mListView.setAdapter(new SkuDetailsAdapter(dialog, skuDetails));
dialog.mListView.setVisibility(View.VISIBLE);
}
}
static class SkuDetailsAdapter extends RecyclerView.Adapter<SkuDetailsAdapter.ViewHolder> {
@LayoutRes
private static int LAYOUT_RES_ID = R.layout.item_donation_option;
SupportDevelopmentActivity donationsDialog;
List<SkuDetails> skuDetailsList = new ArrayList<>();
public SkuDetailsAdapter(@NonNull SupportDevelopmentActivity donationsDialog, @NonNull List<SkuDetails> objects) {
this.donationsDialog = donationsDialog;
skuDetailsList = objects;
}
private static void strikeThrough(TextView textView, boolean strikeThrough) {
textView.setPaintFlags(strikeThrough ? textView.getPaintFlags() |
Paint.STRIKE_THRU_TEXT_FLAG : textView.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
}
private int getIcon(int position) {
switch (position) {
case 0:
return R.drawable.ic_cookie_white_24dp;
case 1:
return R.drawable.ic_take_away_white_24dp;
case 2:
return R.drawable.ic_take_away_coffe_white_24dp;
case 3:
return R.drawable.ic_beer_white_24dp;
case 4:
return R.drawable.ic_fast_food_meal_white_24dp;
case 5:
return R.drawable.ic_popcorn_white_24dp;
case 6:
return R.drawable.ic_card_giftcard_white_24dp;
default:
return R.drawable.ic_card_giftcard_white_24dp;
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
return new ViewHolder(LayoutInflater.from(donationsDialog)
.inflate(LAYOUT_RES_ID, viewGroup, false));
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
SkuDetails skuDetails = skuDetailsList.get(i);
if (skuDetails != null) {
viewHolder.title.setText(skuDetails.title.replace("(Retro Music Player)", "").trim());
viewHolder.text.setText(skuDetails.description);
viewHolder.text.setVisibility(View.GONE);
viewHolder.price.setText(skuDetails.priceText);
viewHolder.image.setImageResource(getIcon(i));
final boolean purchased = donationsDialog.mBillingProcessor.isPurchased(skuDetails.productId);
int titleTextColor = purchased ? ATHUtil.resolveColor(donationsDialog, android.R.attr.textColorHint) : ThemeStore.textColorPrimary(donationsDialog);
int contentTextColor = purchased ? titleTextColor : ThemeStore.textColorSecondary(donationsDialog);
//noinspection ResourceAsColor
viewHolder.title.setTextColor(titleTextColor);
viewHolder.text.setTextColor(contentTextColor);
viewHolder.price.setTextColor(titleTextColor);
strikeThrough(viewHolder.title, purchased);
strikeThrough(viewHolder.text, purchased);
strikeThrough(viewHolder.price, purchased);
viewHolder.itemView.setOnTouchListener((v, event) -> purchased);
viewHolder.itemView.setOnClickListener(v -> donationsDialog.donate(i));
}
}
@Override
public int getItemCount() {
return skuDetailsList.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.title)
TextView title;
@BindView(R.id.text)
TextView text;
@BindView(R.id.price)
TextView price;
@BindView(R.id.image)
IconImageView image;
public ViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
}
}
}

View file

@ -0,0 +1,33 @@
package code.name.monkey.retromusic.ui.activities;
import android.os.Bundle;
import butterknife.ButterKnife;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.ui.activities.base.AbsBaseActivity;
import code.name.monkey.retromusic.ui.fragments.intro.NameFragment;
public class UserInfoActivity extends AbsBaseActivity {
private static final String TAG = "UserInfoActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
setDrawUnderStatusbar(true);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_info);
ButterKnife.bind(this);
setStatusbarColorAuto();
setNavigationbarColorAuto();
setTaskDescriptionColorAuto();
setLightNavigationBar(true);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, new NameFragment(), TAG)
.commit();
}
}
}

View file

@ -0,0 +1,156 @@
package code.name.monkey.retromusic.ui.activities.base;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.view.KeyEvent;
import android.view.View;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.R;
import uk.co.chrisjenx.calligraphy.CalligraphyContextWrapper;
public abstract class AbsBaseActivity extends AbsThemeActivity {
public static final int PERMISSION_REQUEST = 100;
private boolean hadPermissions;
private String[] permissions;
private String permissionDeniedMessage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
permissions = getPermissionsToRequest();
hadPermissions = hasPermissions();
setPermissionDeniedMessage(null);
}
@Override
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
if (!hasPermissions()) {
requestPermissions();
}
}
@Override
protected void onResume() {
super.onResume();
final boolean hasPermissions = hasPermissions();
if (hasPermissions != hadPermissions) {
hadPermissions = hasPermissions;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
onHasPermissionsChanged(hasPermissions);
}
}
}
protected void onHasPermissionsChanged(boolean hasPermissions) {
// implemented by sub classes
}
@Override
public boolean dispatchKeyEvent(@NonNull KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP) {
showOverflowMenu();
return true;
}
return super.dispatchKeyEvent(event);
}
protected void showOverflowMenu() {
}
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
}
@Nullable
protected String[] getPermissionsToRequest() {
return null;
}
protected View getSnackBarContainer() {
return getWindow().getDecorView();
}
private String getPermissionDeniedMessage() {
return permissionDeniedMessage == null ? getString(R.string.permissions_denied) : permissionDeniedMessage;
}
protected void setPermissionDeniedMessage(String message) {
permissionDeniedMessage = message;
}
protected void requestPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && permissions != null) {
requestPermissions(permissions, PERMISSION_REQUEST);
}
}
protected boolean hasPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && permissions != null) {
for (String permission : permissions) {
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSION_REQUEST) {
for (int grantResult : grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(AbsBaseActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
//User has deny from permission dialog
Snackbar.make(getSnackBarContainer(), getPermissionDeniedMessage(),
Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.action_grant, view -> requestPermissions())
.setActionTextColor(ThemeStore.accentColor(this))
.show();
} else {
// User has deny permission and checked never show permission dialog so you can redirect to Application settings page
Snackbar.make(getSnackBarContainer(), getPermissionDeniedMessage(),
Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.action_settings, view -> {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", AbsBaseActivity.this.getPackageName(), null);
intent.setData(uri);
startActivity(intent);
})
.setActionTextColor(ThemeStore.accentColor(this))
.show();
}
return;
}
}
hadPermissions = true;
onHasPermissionsChanged(true);
}
}
}

View file

@ -0,0 +1,222 @@
package code.name.monkey.retromusic.ui.activities.base;
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import static code.name.monkey.retromusic.Constants.MEDIA_STORE_CHANGED;
import static code.name.monkey.retromusic.Constants.META_CHANGED;
import static code.name.monkey.retromusic.Constants.PLAY_STATE_CHANGED;
import static code.name.monkey.retromusic.Constants.QUEUE_CHANGED;
import static code.name.monkey.retromusic.Constants.REPEAT_MODE_CHANGED;
import static code.name.monkey.retromusic.Constants.SHUFFLE_MODE_CHANGED;
public abstract class AbsMusicServiceActivity extends AbsBaseActivity implements MusicServiceEventListener {
public static final String TAG = AbsMusicServiceActivity.class.getSimpleName();
private final ArrayList<MusicServiceEventListener> mMusicServiceEventListeners = new ArrayList<>();
private MusicPlayerRemote.ServiceToken serviceToken;
private MusicStateReceiver musicStateReceiver;
private boolean receiverRegistered;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
serviceToken = MusicPlayerRemote.bindToService(this, new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
AbsMusicServiceActivity.this.onServiceConnected();
}
@Override
public void onServiceDisconnected(ComponentName name) {
AbsMusicServiceActivity.this.onServiceDisconnected();
}
});
setPermissionDeniedMessage(getString(R.string.permission_external_storage_denied));
}
@Override
public void onDestroy() {
super.onDestroy();
MusicPlayerRemote.unbindFromService(serviceToken);
if (receiverRegistered) {
unregisterReceiver(musicStateReceiver);
receiverRegistered = false;
}
}
public void addMusicServiceEventListener(final MusicServiceEventListener listener) {
if (listener != null) {
mMusicServiceEventListeners.add(listener);
}
}
public void removeMusicServiceEventListener(final MusicServiceEventListener listener) {
if (listener != null) {
mMusicServiceEventListeners.remove(listener);
}
}
@Override
public void onServiceConnected() {
if (!receiverRegistered) {
musicStateReceiver = new MusicStateReceiver(this);
final IntentFilter filter = new IntentFilter();
filter.addAction(PLAY_STATE_CHANGED);
filter.addAction(SHUFFLE_MODE_CHANGED);
filter.addAction(REPEAT_MODE_CHANGED);
filter.addAction(META_CHANGED);
filter.addAction(QUEUE_CHANGED);
filter.addAction(MEDIA_STORE_CHANGED);
registerReceiver(musicStateReceiver, filter);
receiverRegistered = true;
}
for (MusicServiceEventListener listener : mMusicServiceEventListeners) {
if (listener != null) {
listener.onServiceConnected();
}
}
}
@Override
public void onServiceDisconnected() {
if (receiverRegistered) {
unregisterReceiver(musicStateReceiver);
receiverRegistered = false;
}
for (MusicServiceEventListener listener : mMusicServiceEventListeners) {
if (listener != null) {
listener.onServiceDisconnected();
}
}
}
@Override
public void onPlayingMetaChanged() {
for (MusicServiceEventListener listener : mMusicServiceEventListeners) {
if (listener != null) {
listener.onPlayingMetaChanged();
}
}
}
@Override
public void onQueueChanged() {
for (MusicServiceEventListener listener : mMusicServiceEventListeners) {
if (listener != null) {
listener.onQueueChanged();
}
}
}
@Override
public void onPlayStateChanged() {
for (MusicServiceEventListener listener : mMusicServiceEventListeners) {
if (listener != null) {
listener.onPlayStateChanged();
}
}
}
@Override
public void onMediaStoreChanged() {
for (MusicServiceEventListener listener : mMusicServiceEventListeners) {
if (listener != null) {
listener.onMediaStoreChanged();
}
}
}
@Override
public void onRepeatModeChanged() {
for (MusicServiceEventListener listener : mMusicServiceEventListeners) {
if (listener != null) {
listener.onRepeatModeChanged();
}
}
}
@Override
public void onShuffleModeChanged() {
for (MusicServiceEventListener listener : mMusicServiceEventListeners) {
if (listener != null) {
listener.onShuffleModeChanged();
}
}
}
@Override
protected void onHasPermissionsChanged(boolean hasPermissions) {
super.onHasPermissionsChanged(hasPermissions);
Intent intent = new Intent(MEDIA_STORE_CHANGED);
intent.putExtra("from_permissions_changed", true); // just in case we need to know this at some point
sendBroadcast(intent);
}
@Nullable
@Override
protected String[] getPermissionsToRequest() {
return new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
}
private static final class MusicStateReceiver extends BroadcastReceiver {
private final WeakReference<AbsMusicServiceActivity> reference;
public MusicStateReceiver(final AbsMusicServiceActivity activity) {
reference = new WeakReference<>(activity);
}
@Override
public void onReceive(final Context context, @NonNull final Intent intent) {
final String action = intent.getAction();
AbsMusicServiceActivity activity = reference.get();
if (activity != null && action != null) {
switch (action) {
case META_CHANGED:
activity.onPlayingMetaChanged();
break;
case QUEUE_CHANGED:
activity.onQueueChanged();
break;
case PLAY_STATE_CHANGED:
activity.onPlayStateChanged();
break;
case REPEAT_MODE_CHANGED:
activity.onRepeatModeChanged();
break;
case SHUFFLE_MODE_CHANGED:
activity.onShuffleModeChanged();
break;
case MEDIA_STORE_CHANGED:
activity.onMediaStoreChanged();
break;
}
}
}
}
}

View file

@ -0,0 +1,434 @@
package code.name.monkey.retromusic.ui.activities.base;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.support.annotation.ColorInt;
import android.support.annotation.FloatRange;
import android.support.annotation.LayoutRes;
import android.support.v4.app.Fragment;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.animation.PathInterpolator;
import com.sothree.slidinguppanel.SlidingUpPanelLayout;
import com.sothree.slidinguppanel.SlidingUpPanelLayout.PanelState;
import butterknife.BindView;
import butterknife.ButterKnife;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.ui.fragments.MiniPlayerFragment;
import code.name.monkey.retromusic.ui.fragments.NowPlayingScreen;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerFragment;
import code.name.monkey.retromusic.ui.fragments.player.adaptive.AdaptiveFragment;
import code.name.monkey.retromusic.ui.fragments.player.blur.BlurPlayerFragment;
import code.name.monkey.retromusic.ui.fragments.player.card.CardFragment;
import code.name.monkey.retromusic.ui.fragments.player.cardblur.CardBlurFragment;
import code.name.monkey.retromusic.ui.fragments.player.color.ColorFragment;
import code.name.monkey.retromusic.ui.fragments.player.flat.FlatPlayerFragment;
import code.name.monkey.retromusic.ui.fragments.player.full.FullPlayerFragment;
import code.name.monkey.retromusic.ui.fragments.player.hmm.HmmPlayerFragment;
import code.name.monkey.retromusic.ui.fragments.player.material.MaterialFragment;
import code.name.monkey.retromusic.ui.fragments.player.normal.PlayerFragment;
import code.name.monkey.retromusic.ui.fragments.player.plain.PlainPlayerFragment;
import code.name.monkey.retromusic.ui.fragments.player.simple.SimplePlayerFragment;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.util.ViewUtil;
import code.name.monkey.retromusic.views.BottomNavigationViewEx;
public abstract class AbsSlidingMusicPanelActivity extends AbsMusicServiceActivity implements
SlidingUpPanelLayout.PanelSlideListener,
PlayerFragment.Callbacks {
public static final String TAG = AbsSlidingMusicPanelActivity.class.getSimpleName();
@BindView(R.id.bottom_navigation)
BottomNavigationViewEx bottomNavigationView;
@BindView(R.id.sliding_layout)
SlidingUpPanelLayout slidingUpPanelLayout;
private int navigationbarColor;
private int taskColor;
private boolean lightStatusBar;
private boolean lightNavigationBar;
private NowPlayingScreen currentNowPlayingScreen;
private AbsPlayerFragment playerFragment;
private MiniPlayerFragment miniPlayerFragment;
private ValueAnimator navigationBarColorAnimator;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(createContentView());
ButterKnife.bind(this);
choosFragmentForTheme();
//noinspection ConstantConditions
miniPlayerFragment.getView().setOnClickListener(v -> expandPanel());
slidingUpPanelLayout.getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
slidingUpPanelLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
if (getPanelState() == PanelState.EXPANDED) {
onPanelSlide(slidingUpPanelLayout, 1);
onPanelExpanded(slidingUpPanelLayout);
} else if (getPanelState() == PanelState.COLLAPSED) {
onPanelCollapsed(slidingUpPanelLayout);
} else {
playerFragment.onHide();
}
}
});
setupBottomView();
slidingUpPanelLayout.addPanelSlideListener(this);
}
private void choosFragmentForTheme() {
currentNowPlayingScreen = PreferenceUtil.getInstance(this).getNowPlayingScreen();
Fragment fragment; // must implement AbsPlayerFragment
switch (currentNowPlayingScreen) {
case MATERIAL:
fragment = new MaterialFragment();
break;
case BLUR:
fragment = new BlurPlayerFragment();
break;
case FLAT:
fragment = new FlatPlayerFragment();
break;
case PLAIN:
fragment = new PlainPlayerFragment();
break;
case FULL:
fragment = new FullPlayerFragment();
break;
case COLOR:
fragment = new ColorFragment();
break;
case CARD:
fragment = new CardFragment();
break;
case SIMPLE:
fragment = new SimplePlayerFragment();
break;
case TINY:
fragment = new HmmPlayerFragment();
break;
case BLUR_CARD:
fragment = new CardBlurFragment();
break;
case ADAPTIVE:
fragment = new AdaptiveFragment();
break;
case NORMAL:
default:
fragment = new PlayerFragment();
break;
}
getSupportFragmentManager().beginTransaction().replace(R.id.player_fragment_container, fragment)
.commit();
getSupportFragmentManager().executePendingTransactions();
playerFragment = (AbsPlayerFragment) getSupportFragmentManager()
.findFragmentById(R.id.player_fragment_container);
miniPlayerFragment = (MiniPlayerFragment) getSupportFragmentManager()
.findFragmentById(R.id.mini_player_fragment);
}
private void setupBottomView() {
bottomNavigationView.setSelectedItemId(PreferenceUtil.getInstance(this).getLastPage());
bottomNavigationView.setBackgroundColor(ThemeStore.primaryColor(this));
bottomNavigationView.enableAnimation(false);
bottomNavigationView.enableItemShiftingMode(false);
bottomNavigationView.enableShiftingMode(false);
bottomNavigationView.setTextSize(10f);
bottomNavigationView.setTextVisibility(PreferenceUtil.getInstance(this).tabTitles());
}
@Override
protected void onResume() {
super.onResume();
if (currentNowPlayingScreen != PreferenceUtil.getInstance(this).getNowPlayingScreen()) {
postRecreate();
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (navigationBarColorAnimator != null) {
navigationBarColorAnimator.cancel(); // just in case
}
}
protected abstract View createContentView();
@Override
public void onServiceConnected() {
super.onServiceConnected();
if (!MusicPlayerRemote.getPlayingQueue().isEmpty()) {
slidingUpPanelLayout.getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
slidingUpPanelLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
hideBottomBar(false);
}
});
}// don't call hideBottomBar(true) here as it causes a bug with the SlidingUpPanelLayout
}
@Override
public void onQueueChanged() {
super.onQueueChanged();
hideBottomBar(MusicPlayerRemote.getPlayingQueue().isEmpty());
}
@Override
public void onPanelSlide(View panel, @FloatRange(from = 0, to = 1) float slideOffset) {
bottomNavigationView.setTranslationY(slideOffset * 400);
setMiniPlayerAlphaProgress(slideOffset);
//findViewById(R.id.player_fragment_container).setAlpha(slideOffset);
}
@Override
public void onPanelStateChanged(View panel, PanelState previousState, PanelState newState) {
switch (newState) {
case COLLAPSED:
onPanelCollapsed(panel);
break;
case EXPANDED:
onPanelExpanded(panel);
break;
case ANCHORED:
collapsePanel(); // this fixes a bug where the panel would get stuck for some reason
break;
}
}
public void onPanelCollapsed(View panel) {
// restore values
super.setLightStatusbar(lightStatusBar);
super.setTaskDescriptionColor(taskColor);
super.setNavigationbarColor(navigationbarColor);
super.setLightNavigationBar(lightNavigationBar);
playerFragment.setMenuVisibility(false);
playerFragment.setUserVisibleHint(false);
playerFragment.onHide();
}
public void onPanelExpanded(View panel) {
// setting fragments values
int playerFragmentColor = playerFragment.getPaletteColor();
super.setTaskDescriptionColor(playerFragmentColor);
if (currentNowPlayingScreen == NowPlayingScreen.COLOR) {
super.setNavigationbarColor(playerFragmentColor);
} else {
super.setNavigationbarColor(ThemeStore.primaryColor(this));
}
setLightStatusBar();
playerFragment.setMenuVisibility(true);
playerFragment.setUserVisibleHint(true);
playerFragment.onShow();
}
private void setLightStatusBar() {
super.setLightStatusbar(!PreferenceUtil.getInstance(this).getAdaptiveColor() &&
ColorUtil.isColorLight(ThemeStore.primaryColor(this)) && (
currentNowPlayingScreen == NowPlayingScreen.FLAT
|| currentNowPlayingScreen == NowPlayingScreen.PLAIN
|| currentNowPlayingScreen == NowPlayingScreen.SIMPLE
|| currentNowPlayingScreen == NowPlayingScreen.NORMAL
|| currentNowPlayingScreen == NowPlayingScreen.ADAPTIVE)
|| currentNowPlayingScreen == NowPlayingScreen.TINY);
}
@Override
public void setLightStatusbar(boolean enabled) {
lightStatusBar = enabled;
if (getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) {
super.setLightStatusbar(enabled);
}
}
@Override
public void setLightNavigationBar(boolean enabled) {
lightNavigationBar = enabled;
/*if (getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) {
super.setLightNavigationBar(enabled);
}*/
}
@Override
public void setTaskDescriptionColor(@ColorInt int color) {
taskColor = color;
if (getPanelState() == null || getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) {
super.setTaskDescriptionColor(color);
}
}
@Override
public void setNavigationbarColor(int color) {
navigationbarColor = color;
if (getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) {
if (navigationBarColorAnimator != null) {
navigationBarColorAnimator.cancel();
}
super.setNavigationbarColor(color);
}
}
@Override
public void onPaletteColorChanged() {
int playerFragmentColor = playerFragment.getPaletteColor();
if (getPanelState() == PanelState.EXPANDED) {
super.setTaskDescriptionColor(playerFragmentColor);
if (currentNowPlayingScreen == NowPlayingScreen.COLOR) {
super.setNavigationbarColor(playerFragmentColor);
}
}
}
private void setMiniPlayerAlphaProgress(@FloatRange(from = 0, to = 1) float progress) {
if (miniPlayerFragment == null) {
return;
}
float alpha = 1 - progress;
miniPlayerFragment.getView().setAlpha(alpha);
// necessary to make the views below clickable
miniPlayerFragment.getView().setVisibility(alpha == 0 ? View.GONE : View.VISIBLE);
}
public void hideBottomBar(final boolean hide) {
int heightOfBar =
getResources().getDimensionPixelSize(R.dimen.mini_player_height);
int heightOfBarWithTabs =
getResources().getDimensionPixelSize(R.dimen.mini_player_height_expanded);
if (hide) {
slidingUpPanelLayout.setPanelHeight(0);
collapsePanel();
} else {
if (!MusicPlayerRemote.getPlayingQueue().isEmpty()) {
slidingUpPanelLayout.setPanelHeight(bottomNavigationView.getVisibility() == View.VISIBLE ?
heightOfBarWithTabs : heightOfBar);
}
}
}
public void setBottomBarVisibility(int gone) {
if (bottomNavigationView != null) {
//TransitionManager.beginDelayedTransition(bottomNavigationView);
bottomNavigationView.setVisibility(gone);
hideBottomBar(false);
}
}
protected View wrapSlidingMusicPanel(@LayoutRes int resId) {
@SuppressLint("InflateParams")
View slidingMusicPanelLayout = getLayoutInflater()
.inflate(R.layout.sliding_music_panel_layout, null);
ViewGroup contentContainer = slidingMusicPanelLayout.findViewById(R.id.content_container);
getLayoutInflater().inflate(resId, contentContainer);
return slidingMusicPanelLayout;
}
@Override
public void onBackPressed() {
if (!handleBackPress()) {
super.onBackPressed();
}
}
public boolean handleBackPress() {
if (slidingUpPanelLayout.getPanelHeight() != 0 && playerFragment.onBackPressed()) {
return true;
}
if (getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
collapsePanel();
return true;
}
return false;
}
private void animateNavigationBarColor(int color) {
if (navigationBarColorAnimator != null) {
navigationBarColorAnimator.cancel();
}
navigationBarColorAnimator = ValueAnimator.ofArgb(getWindow().getNavigationBarColor(), color)
.setDuration(ViewUtil.RETRO_MUSIC_ANIM_TIME);
navigationBarColorAnimator.setInterpolator(new PathInterpolator(0.4f, 0f, 1f, 1f));
navigationBarColorAnimator.addUpdateListener(animation -> {
int playerFragmentColorDark = ColorUtil.darkenColor((Integer) animation.getAnimatedValue());
bottomNavigationView.setBackgroundColor(playerFragmentColorDark);
miniPlayerFragment.setColor(playerFragmentColorDark);
AbsSlidingMusicPanelActivity.super.setNavigationbarColor(playerFragmentColorDark);
View view = getWindow().getDecorView().getRootView();
view.setBackgroundColor(playerFragmentColorDark);
if (view.findViewById(R.id.toolbar) != null) {
view.findViewById(R.id.toolbar).setBackgroundColor(playerFragmentColorDark);
}
if (view.findViewById(R.id.appbar) != null) {
view.findViewById(R.id.appbar).setBackgroundColor(playerFragmentColorDark);
}
if (view.findViewById(R.id.status_bar) != null) {
view.findViewById(R.id.status_bar)
.setBackgroundColor(ColorUtil.darkenColor(playerFragmentColorDark));
}
});
navigationBarColorAnimator.start();
}
@Override
protected View getSnackBarContainer() {
return findViewById(R.id.content_container);
}
public SlidingUpPanelLayout getSlidingUpPanelLayout() {
return slidingUpPanelLayout;
}
public MiniPlayerFragment getMiniPlayerFragment() {
return miniPlayerFragment;
}
public AbsPlayerFragment getPlayerFragment() {
return playerFragment;
}
public BottomNavigationViewEx getBottomNavigationView() {
return bottomNavigationView;
}
public SlidingUpPanelLayout.PanelState getPanelState() {
return slidingUpPanelLayout == null ? null : slidingUpPanelLayout.getPanelState();
}
public void collapsePanel() {
slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
}
public void expandPanel() {
slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED);
}
}

View file

@ -0,0 +1,213 @@
package code.name.monkey.retromusic.ui.activities.base;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.ColorInt;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import code.name.monkey.appthemehelper.ATH;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.common.ATHToolbarActivity;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialDialogsUtil;
import code.name.monkey.appthemehelper.util.VersionUtils;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.util.RetroUtil;
public abstract class AbsThemeActivity extends ATHToolbarActivity implements Runnable {
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(PreferenceUtil.getInstance(this).getGeneralTheme());
hideStatusBar();
super.onCreate(savedInstanceState);
MaterialDialogsUtil.updateMaterialDialogsThemeSingleton(this);
changeBackgroundShape();
setImmersiveFullscreen();
registerSystemUiVisibility();
toggleScreenOn();
}
private void toggleScreenOn() {
if (PreferenceUtil.getInstance(this).isScreenOnEnabled()) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
hideStatusBar();
handler.removeCallbacks(this);
handler.postDelayed(this, 300);
} else {
handler.removeCallbacks(this);
}
}
public void hideStatusBar() {
hideStatusBar(PreferenceUtil.getInstance(this).getFullScreenMode());
}
private void hideStatusBar(boolean fullscreen) {
final View statusBar = getWindow().getDecorView().getRootView().findViewById(R.id.status_bar);
if (statusBar != null) {
statusBar.setVisibility(fullscreen ? View.GONE : View.VISIBLE);
}
}
private void changeBackgroundShape() {
if (PreferenceUtil.getInstance(this).isRoundCorners()) {
getWindow().setBackgroundDrawableResource(R.drawable.round_window);
} else {
getWindow().setBackgroundDrawableResource(R.drawable.square_window);
}
View decor = getWindow().getDecorView();
GradientDrawable gradientDrawable = (GradientDrawable) decor.getBackground();
gradientDrawable.setColor(ThemeStore.primaryColor(this));
}
protected void setDrawUnderStatusbar(boolean drawUnderStatusbar) {
if (VersionUtils.hasLollipop()) {
RetroUtil.setAllowDrawUnderStatusBar(getWindow());
} else if (VersionUtils.hasKitKat()) {
RetroUtil.setStatusBarTranslucent(getWindow());
}
}
/**
* 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)
*/
public void setStatusbarColor(int color) {
if (VersionUtils.hasKitKat()) {
final View statusBar = getWindow().getDecorView().getRootView().findViewById(R.id.status_bar);
if (statusBar != null) {
if (VersionUtils.hasLollipop()) {
statusBar.setBackgroundColor(ColorUtil.darkenColor(color));
setLightStatusbarAuto(color);
} else {
statusBar.setBackgroundColor(color);
}
} else if (Build.VERSION.SDK_INT >= 21) {
getWindow().setStatusBarColor(ColorUtil.darkenColor(color));
setLightStatusbarAuto(color);
}
}
}
public void setStatusbarColorAuto() {
// we don't want to use statusbar color because we are doing the color darkening on our own to support KitKat
setStatusbarColor(ThemeStore.primaryColor(this));
}
public void setTaskDescriptionColor(@ColorInt int color) {
ATH.setTaskDescriptionColor(this, color);
}
public void setTaskDescriptionColorAuto() {
setTaskDescriptionColor(ThemeStore.primaryColor(this));
}
public void setNavigationbarColor(int color) {
if (ThemeStore.coloredNavigationBar(this)) {
ATH.setNavigationbarColor(this, color);
} else {
ATH.setNavigationbarColor(this, Color.BLACK);
}
}
public void setNavigationbarColorAuto() {
setNavigationbarColor(ThemeStore.navigationBarColor(this));
}
public void setLightStatusbar(boolean enabled) {
ATH.setLightStatusbar(this, enabled);
}
public void setLightStatusbarAuto(int bgColor) {
setLightStatusbar(ColorUtil.isColorLight(bgColor));
}
public void setLightNavigationBar(boolean enabled) {
if (!ATHUtil.isWindowBackgroundDark(this) && ThemeStore.coloredNavigationBar(this)) {
ATH.setLightNavigationbar(this, enabled);
}
}
private void registerSystemUiVisibility() {
final View decorView = getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener(visibility -> {
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
setImmersiveFullscreen();
}
});
}
private void unregisterSystemUiVisibility() {
final View decorView = getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener(null);
}
public void setImmersiveFullscreen() {
int flags = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
if (PreferenceUtil.getInstance(this).getFullScreenMode()) {
getWindow().getDecorView().setSystemUiVisibility(flags);
}
}
public void exitFullscreen() {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
}
@Override
public void run() {
setImmersiveFullscreen();
}
@Override
protected void onStop() {
handler.removeCallbacks(this);
super.onStop();
}
@Override
public void onDestroy() {
super.onDestroy();
unregisterSystemUiVisibility();
exitFullscreen();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP)) {
handler.removeCallbacks(this);
handler.postDelayed(this, 500);
}
return super.onKeyDown(keyCode, event);
}
}

View file

@ -0,0 +1,367 @@
package code.name.monkey.retromusic.ui.activities.tageditor;
import android.app.SearchManager;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.OvershootInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.afollestad.materialdialogs.MaterialDialog;
import org.jaudiotagger.audio.AudioFile;
import org.jaudiotagger.audio.AudioFileIO;
import org.jaudiotagger.tag.FieldKey;
import org.jaudiotagger.tag.images.Artwork;
import java.io.File;
import java.util.List;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.ui.activities.base.AbsBaseActivity;
import code.name.monkey.retromusic.util.RetroUtil;
public abstract class AbsTagEditorActivity extends AbsBaseActivity {
public static final String EXTRA_ID = "extra_id";
public static final String EXTRA_PALETTE = "extra_palette";
private static final String TAG = AbsTagEditorActivity.class.getSimpleName();
private static final int REQUEST_CODE_SELECT_IMAGE = 1000;
@BindView(R.id.save_fab)
FloatingActionButton save;
@BindView(R.id.image)
ImageView image;
@BindView(R.id.image_container)
FrameLayout imageContainer;
CharSequence[] items;
private int id;
private int paletteColorPrimary;
private boolean isInNoImageMode;
private List<String> songPaths;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getContentViewLayout());
ButterKnife.bind(this);
getIntentExtras();
songPaths = getSongPaths();
if (songPaths.isEmpty()) {
finish();
return;
}
setUpViews();
setTaskDescriptionColorAuto();
}
private void setUpViews() {
setUpScrollView();
setUpFab();
setUpImageView();
}
private void setUpScrollView() {
//observableScrollView.setScrollViewCallbacks(observableScrollViewCallbacks);
}
private void setUpImageView() {
loadCurrentImage();
items = new CharSequence[]{
getString(R.string.download_from_last_fm),
getString(R.string.pick_from_local_storage),
getString(R.string.web_search),
getString(R.string.remove_cover)
};
image.setOnClickListener(v -> getShow());
}
protected MaterialDialog getShow() {
return new MaterialDialog.Builder(AbsTagEditorActivity.this)
.title(R.string.update_image)
.items(items)
.itemsCallback((dialog, itemView, position, text) -> {
switch (position) {
case 0:
getImageFromLastFM();
break;
case 1:
startImagePicker();
break;
case 2:
searchImageOnWeb();
break;
case 3:
deleteImage();
break;
}
}).show();
}
private void startImagePicker() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(
Intent.createChooser(intent, getString(R.string.pick_from_local_storage)),
REQUEST_CODE_SELECT_IMAGE);
}
protected abstract void loadCurrentImage();
protected abstract void getImageFromLastFM();
protected abstract void searchImageOnWeb();
protected abstract void deleteImage();
private void setUpFab() {
save.setScaleX(0);
save.setScaleY(0);
save.setEnabled(false);
save.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
save();
}
});
TintHelper.setTintAuto(save, ThemeStore.accentColor(this), true);
}
protected abstract void save();
private void getIntentExtras() {
Bundle intentExtras = getIntent().getExtras();
if (intentExtras != null) {
id = intentExtras.getInt(EXTRA_ID);
}
}
protected abstract int getContentViewLayout();
@NonNull
protected abstract List<String> getSongPaths();
protected void searchWebFor(String... keys) {
StringBuilder stringBuilder = new StringBuilder();
for (String key : keys) {
stringBuilder.append(key);
stringBuilder.append(" ");
}
Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY, stringBuilder.toString());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();
switch (id) {
case android.R.id.home:
super.onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
protected void setNoImageMode() {
isInNoImageMode = true;
imageContainer.setVisibility(View.GONE);
image.setVisibility(View.GONE);
image.setEnabled(false);
setColors(getIntent().getIntExtra(EXTRA_PALETTE, ThemeStore.primaryColor(this)));
}
protected void dataChanged() {
showFab();
}
private void showFab() {
save.animate()
.setDuration(500)
.setInterpolator(new OvershootInterpolator())
.scaleX(1)
.scaleY(1)
.start();
save.setEnabled(true);
}
protected void setImageBitmap(@Nullable final Bitmap bitmap, int bgColor) {
if (bitmap == null) {
image.setImageResource(R.drawable.default_album_art);
} else {
image.setImageBitmap(bitmap);
}
setColors(bgColor);
}
protected void setColors(int color) {
paletteColorPrimary = color;
}
protected void writeValuesToFiles(@NonNull final Map<FieldKey, String> fieldKeyValueMap,
@Nullable final ArtworkInfo artworkInfo) {
RetroUtil.hideSoftKeyboard(this);
new WriteTagsAsyncTask(this)
.execute(new WriteTagsAsyncTask.LoadingInfo(getSongPaths(), fieldKeyValueMap, artworkInfo));
}
protected int getId() {
return id;
}
@Override
protected void onActivityResult(int requestCode, int resultCode,
@NonNull Intent imageReturnedIntent) {
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
switch (requestCode) {
case REQUEST_CODE_SELECT_IMAGE:
if (resultCode == RESULT_OK) {
Uri selectedImage = imageReturnedIntent.getData();
loadImageFromFile(selectedImage);
}
break;
}
}
protected abstract void loadImageFromFile(Uri selectedFile);
@NonNull
private AudioFile getAudioFile(@NonNull String path) {
try {
return AudioFileIO.read(new File(path));
} catch (Exception e) {
Log.e(TAG, "Could not read audio file " + path, e);
return new AudioFile();
}
}
@Nullable
String getAlbumArtist() {
try {
return getAudioFile(songPaths.get(0)).getTagOrCreateAndSetDefault()
.getFirst(FieldKey.ALBUM_ARTIST);
} catch (Exception ignored) {
return null;
}
}
@Nullable
protected String getSongTitle() {
try {
return getAudioFile(songPaths.get(0)).getTagOrCreateAndSetDefault().getFirst(FieldKey.TITLE);
} catch (Exception ignored) {
return null;
}
}
@Nullable
protected String getAlbumTitle() {
try {
return getAudioFile(songPaths.get(0)).getTagOrCreateAndSetDefault().getFirst(FieldKey.ALBUM);
} catch (Exception ignored) {
return null;
}
}
@Nullable
protected String getArtistName() {
try {
return getAudioFile(songPaths.get(0)).getTagOrCreateAndSetDefault().getFirst(FieldKey.ARTIST);
} catch (Exception ignored) {
return null;
}
}
@Nullable
protected String getAlbumArtistName() {
try {
return getAudioFile(songPaths.get(0)).getTagOrCreateAndSetDefault()
.getFirst(FieldKey.ALBUM_ARTIST);
} catch (Exception ignored) {
return null;
}
}
@Nullable
protected String getGenreName() {
try {
return getAudioFile(songPaths.get(0)).getTagOrCreateAndSetDefault().getFirst(FieldKey.GENRE);
} catch (Exception ignored) {
return null;
}
}
@Nullable
protected String getSongYear() {
try {
return getAudioFile(songPaths.get(0)).getTagOrCreateAndSetDefault().getFirst(FieldKey.YEAR);
} catch (Exception ignored) {
return null;
}
}
@Nullable
protected String getTrackNumber() {
try {
return getAudioFile(songPaths.get(0)).getTagOrCreateAndSetDefault().getFirst(FieldKey.TRACK);
} catch (Exception ignored) {
return null;
}
}
@Nullable
protected String getLyrics() {
try {
return getAudioFile(songPaths.get(0)).getTagOrCreateAndSetDefault().getFirst(FieldKey.LYRICS);
} catch (Exception ignored) {
return null;
}
}
@Nullable
protected Bitmap getAlbumArt() {
try {
Artwork artworkTag = getAudioFile(songPaths.get(0)).getTagOrCreateAndSetDefault()
.getFirstArtwork();
if (artworkTag != null) {
byte[] artworkBinaryData = artworkTag.getBinaryData();
return BitmapFactory.decodeByteArray(artworkBinaryData, 0, artworkBinaryData.length);
}
return null;
} catch (Exception ignored) {
return null;
}
}
public static class ArtworkInfo {
public final int albumId;
final Bitmap artwork;
ArtworkInfo(int albumId, Bitmap artwork) {
this.albumId = albumId;
this.artwork = artwork;
}
}
}

View file

@ -0,0 +1,281 @@
package code.name.monkey.retromusic.ui.activities.tageditor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.AppBarLayout;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.SimpleTarget;
import org.jaudiotagger.tag.FieldKey;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.glide.palette.BitmapPaletteTranscoder;
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper;
import code.name.monkey.retromusic.loaders.AlbumLoader;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.rest.LastFMRestClient;
import code.name.monkey.retromusic.rest.model.LastFmAlbum;
import code.name.monkey.retromusic.util.ImageUtil;
import code.name.monkey.retromusic.util.LastFMUtil;
import code.name.monkey.retromusic.util.RetroColorUtil;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
public class AlbumTagEditorActivity extends AbsTagEditorActivity implements TextWatcher {
public static final String TAG = AlbumTagEditorActivity.class.getSimpleName();
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.app_bar)
AppBarLayout appBarLayout;
@BindView(R.id.title)
EditText albumTitle;
@BindView(R.id.album_artist)
EditText albumArtist;
@BindView(R.id.genre)
EditText genre;
@BindView(R.id.year)
EditText year;
@BindView(R.id.gradient_background)
View background;
private Bitmap albumArtBitmap;
private boolean deleteAlbumArt;
private LastFMRestClient lastFMRestClient;
private void setupToolbar() {
//toolbar.setBackgroundColor(ThemeStore.primaryColor(this));
toolbar.setNavigationOnClickListener(v -> onBackPressed());
setTitle(R.string.action_tag_editor);
setSupportActionBar(toolbar);
}
@OnClick(R.id.edit)
void edit() {
getShow();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ButterKnife.bind(this);
lastFMRestClient = new LastFMRestClient(this);
setUpViews();
setupToolbar();
}
@Override
protected int getContentViewLayout() {
return R.layout.activity_album_tag_editor;
}
private void setUpViews() {
fillViewsWithFileTags();
albumTitle.addTextChangedListener(this);
albumArtist.addTextChangedListener(this);
genre.addTextChangedListener(this);
year.addTextChangedListener(this);
}
private void fillViewsWithFileTags() {
albumTitle.setText(getAlbumTitle());
albumArtist.setText(getAlbumArtistName());
genre.setText(getGenreName());
year.setText(getSongYear());
}
@Override
protected void loadCurrentImage() {
Bitmap bitmap = getAlbumArt();
setImageBitmap(bitmap, RetroColorUtil.getColor(RetroColorUtil.generatePalette(bitmap),
ATHUtil.resolveColor(this, R.attr.defaultFooterColor)));
deleteAlbumArt = false;
}
@Override
protected void getImageFromLastFM() {
String albumTitleStr = albumTitle.getText().toString();
String albumArtistNameStr = albumArtist.getText().toString();
if (albumArtistNameStr.trim().equals("") || albumTitleStr.trim().equals("")) {
Toast.makeText(this, getResources().getString(R.string.album_or_artist_empty),
Toast.LENGTH_SHORT).show();
return;
}
lastFMRestClient.getApiService()
.getAlbumInfo(albumTitleStr, albumArtistNameStr, null)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.computation())
.subscribe(this::extractDetails);
}
private void extractDetails(@NonNull LastFmAlbum lastFmAlbum) {
if (lastFmAlbum.getAlbum() != null) {
String url = LastFMUtil.getLargestAlbumImageUrl(lastFmAlbum.getAlbum().getImage());
if (!TextUtils.isEmpty(url) && url.trim().length() > 0) {
Glide.with(this)
.load(url)
.asBitmap()
.transcode(new BitmapPaletteTranscoder(this), BitmapPaletteWrapper.class)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.error(R.drawable.default_album_art)
.into(new SimpleTarget<BitmapPaletteWrapper>() {
@Override
public void onLoadFailed(Exception e, Drawable errorDrawable) {
super.onLoadFailed(e, errorDrawable);
e.printStackTrace();
Toast.makeText(AlbumTagEditorActivity.this, e.toString(), Toast.LENGTH_LONG).show();
}
@Override
public void onResourceReady(BitmapPaletteWrapper resource,
GlideAnimation<? super BitmapPaletteWrapper> glideAnimation) {
albumArtBitmap = ImageUtil.resizeBitmap(resource.getBitmap(), 2048);
setImageBitmap(albumArtBitmap, RetroColorUtil.getColor(resource.getPalette(),
ContextCompat.getColor(AlbumTagEditorActivity.this, R.color.md_grey_500)));
deleteAlbumArt = false;
dataChanged();
setResult(RESULT_OK);
}
});
return;
}
if (lastFmAlbum.getAlbum().getTags().getTag().size() > 0) {
genre.setText(lastFmAlbum.getAlbum().getTags().getTag().get(0).getName());
}
}
toastLoadingFailed();
}
private void toastLoadingFailed() {
Toast.makeText(AlbumTagEditorActivity.this,
R.string.could_not_download_album_cover, Toast.LENGTH_SHORT).show();
}
@Override
protected void searchImageOnWeb() {
searchWebFor(albumTitle.getText().toString(), albumArtist.getText().toString());
}
@Override
protected void deleteImage() {
setImageBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.default_album_art),
ATHUtil.resolveColor(this, R.attr.defaultFooterColor));
deleteAlbumArt = true;
dataChanged();
}
@Override
protected void save() {
Map<FieldKey, String> fieldKeyValueMap = new EnumMap<>(FieldKey.class);
fieldKeyValueMap.put(FieldKey.ALBUM, albumTitle.getText().toString());
//android seems not to recognize album_artist field so we additionally write the normal artist field
fieldKeyValueMap.put(FieldKey.ARTIST, albumArtist.getText().toString());
fieldKeyValueMap.put(FieldKey.ALBUM_ARTIST, albumArtist.getText().toString());
fieldKeyValueMap.put(FieldKey.GENRE, genre.getText().toString());
fieldKeyValueMap.put(FieldKey.YEAR, year.getText().toString());
writeValuesToFiles(fieldKeyValueMap, deleteAlbumArt ? new ArtworkInfo(getId(), null)
: albumArtBitmap == null ? null : new ArtworkInfo(getId(), albumArtBitmap));
}
@NonNull
@Override
protected List<String> getSongPaths() {
ArrayList<Song> songs = AlbumLoader.getAlbum(this, getId()).blockingFirst().songs;
ArrayList<String> paths = new ArrayList<>(songs.size());
for (Song song : songs) {
paths.add(song.data);
}
return paths;
}
@Override
protected void loadImageFromFile(@NonNull final Uri selectedFileUri) {
Glide.with(AlbumTagEditorActivity.this)
.load(selectedFileUri)
.asBitmap()
.transcode(new BitmapPaletteTranscoder(AlbumTagEditorActivity.this),
BitmapPaletteWrapper.class)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(new SimpleTarget<BitmapPaletteWrapper>() {
@Override
public void onLoadFailed(Exception e, Drawable errorDrawable) {
super.onLoadFailed(e, errorDrawable);
e.printStackTrace();
Toast.makeText(AlbumTagEditorActivity.this, e.toString(), Toast.LENGTH_LONG).show();
}
@Override
public void onResourceReady(BitmapPaletteWrapper resource,
GlideAnimation<? super BitmapPaletteWrapper> glideAnimation) {
RetroColorUtil.getColor(resource.getPalette(), Color.TRANSPARENT);
albumArtBitmap = ImageUtil.resizeBitmap(resource.getBitmap(), 2048);
setImageBitmap(albumArtBitmap, RetroColorUtil.getColor(resource.getPalette(),
ATHUtil.resolveColor(AlbumTagEditorActivity.this, R.attr.defaultFooterColor)));
deleteAlbumArt = false;
dataChanged();
setResult(RESULT_OK);
}
});
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
dataChanged();
}
@Override
protected void setColors(int color) {
super.setColors(color);
background.setBackgroundColor(color);
toolbar.setBackgroundColor(color);
setStatusbarColor(ColorUtil.darkenColor(color));
setNavigationbarColor(ColorUtil.darkenColor(color));
setSupportActionBar(toolbar);
}
}

View file

@ -0,0 +1,167 @@
package code.name.monkey.retromusic.ui.activities.tageditor;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.AppBarLayout;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import org.jaudiotagger.tag.FieldKey;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.loaders.SongLoader;
public class SongTagEditorActivity extends AbsTagEditorActivity implements TextWatcher {
public static final String TAG = SongTagEditorActivity.class.getSimpleName();
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.app_bar)
AppBarLayout appBarLayout;
@BindView(R.id.title1)
EditText songTitle;
@BindView(R.id.title2)
EditText albumTitle;
@BindView(R.id.artist)
EditText artist;
@BindView(R.id.genre)
EditText genre;
@BindView(R.id.year)
EditText year;
@BindView(R.id.image_text)
EditText trackNumber;
@BindView(R.id.lyrics)
EditText lyrics;
@BindView(R.id.album_artist)
EditText albumArtist;
private void setupToolbar() {
appBarLayout.setBackgroundColor(ThemeStore.primaryColor(this));
toolbar.setBackgroundColor(ThemeStore.primaryColor(this));
toolbar.setNavigationOnClickListener(v -> onBackPressed());
setTitle(R.string.action_tag_editor);
setSupportActionBar(toolbar);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ButterKnife.bind(this);
setStatusbarColorAuto();
setNavigationbarColorAuto();
setNoImageMode();
setUpViews();
setupToolbar();
}
private void setUpViews() {
fillViewsWithFileTags();
albumArtist.addTextChangedListener(this);
songTitle.addTextChangedListener(this);
albumTitle.addTextChangedListener(this);
artist.addTextChangedListener(this);
genre.addTextChangedListener(this);
year.addTextChangedListener(this);
trackNumber.addTextChangedListener(this);
lyrics.addTextChangedListener(this);
}
private void fillViewsWithFileTags() {
songTitle.setText(getSongTitle());
albumArtist.setText(getAlbumArtist());
albumTitle.setText(getAlbumTitle());
artist.setText(getArtistName());
genre.setText(getGenreName());
year.setText(getSongYear());
trackNumber.setText(getTrackNumber());
lyrics.setText(getLyrics());
}
@Override
protected void loadCurrentImage() {
}
@Override
protected void getImageFromLastFM() {
}
@Override
protected void searchImageOnWeb() {
}
@Override
protected void deleteImage() {
}
@Override
protected void save() {
Map<FieldKey, String> fieldKeyValueMap = new EnumMap<>(FieldKey.class);
fieldKeyValueMap.put(FieldKey.TITLE, songTitle.getText().toString());
fieldKeyValueMap.put(FieldKey.ALBUM, albumTitle.getText().toString());
fieldKeyValueMap.put(FieldKey.ARTIST, artist.getText().toString());
fieldKeyValueMap.put(FieldKey.GENRE, genre.getText().toString());
fieldKeyValueMap.put(FieldKey.YEAR, year.getText().toString());
fieldKeyValueMap.put(FieldKey.TRACK, trackNumber.getText().toString());
fieldKeyValueMap.put(FieldKey.LYRICS, lyrics.getText().toString());
fieldKeyValueMap.put(FieldKey.ALBUM_ARTIST, albumArtist.getText().toString());
writeValuesToFiles(fieldKeyValueMap, null);
}
@Override
protected int getContentViewLayout() {
return R.layout.activity_song_tag_editor;
}
@NonNull
@Override
protected List<String> getSongPaths() {
ArrayList<String> paths = new ArrayList<>(1);
paths.add(SongLoader.getSong(this, getId()).blockingFirst().data);
return paths;
}
@Override
protected void loadImageFromFile(Uri imageFilePath) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
dataChanged();
}
@Override
protected void setColors(int color) {
super.setColors(color);
}
}

View file

@ -0,0 +1,163 @@
package code.name.monkey.retromusic.ui.activities.tageditor;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.media.MediaScannerConnection;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.misc.DialogAsyncTask;
import code.name.monkey.retromusic.misc.UpdateToastMediaScannerCompletionListener;
import code.name.monkey.retromusic.util.MusicUtil;
import com.afollestad.materialdialogs.MaterialDialog;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import org.jaudiotagger.audio.AudioFile;
import org.jaudiotagger.audio.AudioFileIO;
import org.jaudiotagger.audio.exceptions.CannotReadException;
import org.jaudiotagger.audio.exceptions.CannotWriteException;
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
import org.jaudiotagger.tag.FieldKey;
import org.jaudiotagger.tag.Tag;
import org.jaudiotagger.tag.TagException;
import org.jaudiotagger.tag.images.Artwork;
import org.jaudiotagger.tag.images.ArtworkFactory;
public class WriteTagsAsyncTask extends
DialogAsyncTask<WriteTagsAsyncTask.LoadingInfo, Integer, String[]> {
private Context applicationContext;
public WriteTagsAsyncTask(Context context) {
super(context);
applicationContext = context;
}
@Override
protected String[] doInBackground(LoadingInfo... params) {
try {
LoadingInfo info = params[0];
Artwork artwork = null;
File albumArtFile = null;
if (info.artworkInfo != null && info.artworkInfo.artwork != null) {
try {
albumArtFile = MusicUtil.createAlbumArtFile().getCanonicalFile();
info.artworkInfo.artwork
.compress(Bitmap.CompressFormat.PNG, 0, new FileOutputStream(albumArtFile));
artwork = ArtworkFactory.createArtworkFromFile(albumArtFile);
} catch (IOException e) {
e.printStackTrace();
}
}
int counter = 0;
boolean wroteArtwork = false;
boolean deletedArtwork = false;
for (String filePath : info.filePaths) {
publishProgress(++counter, info.filePaths.size());
try {
AudioFile audioFile = AudioFileIO.read(new File(filePath));
Tag tag = audioFile.getTagOrCreateAndSetDefault();
if (info.fieldKeyValueMap != null) {
for (Map.Entry<FieldKey, String> entry : info.fieldKeyValueMap.entrySet()) {
try {
tag.setField(entry.getKey(), entry.getValue());
} catch (Exception e) {
e.printStackTrace();
}
}
}
if (info.artworkInfo != null) {
if (info.artworkInfo.artwork == null) {
tag.deleteArtworkField();
deletedArtwork = true;
} else if (artwork != null) {
tag.deleteArtworkField();
tag.setField(artwork);
wroteArtwork = true;
}
}
audioFile.commit();
} catch (@NonNull CannotReadException | IOException | CannotWriteException | TagException | ReadOnlyFileException | InvalidAudioFrameException e) {
e.printStackTrace();
}
}
Context context = getContext();
if (context != null) {
if (wroteArtwork) {
MusicUtil.insertAlbumArt(context, info.artworkInfo.albumId, albumArtFile.getPath());
} else if (deletedArtwork) {
MusicUtil.deleteAlbumArt(context, info.artworkInfo.albumId);
}
}
return info.filePaths.toArray(new String[info.filePaths.size()]);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
protected void onPostExecute(String[] toBeScanned) {
super.onPostExecute(toBeScanned);
scan(toBeScanned);
}
@Override
protected void onCancelled(String[] toBeScanned) {
super.onCancelled(toBeScanned);
scan(toBeScanned);
}
private void scan(String[] toBeScanned) {
Context context = getContext();
MediaScannerConnection.scanFile(applicationContext, toBeScanned, null,
context instanceof Activity ? new UpdateToastMediaScannerCompletionListener(
(Activity) context, toBeScanned) : null);
}
@Override
protected Dialog createDialog(@NonNull Context context) {
return new MaterialDialog.Builder(context)
.title(R.string.saving_changes)
.cancelable(false)
.progress(false, 0)
.build();
}
@Override
protected void onProgressUpdate(@NonNull Dialog dialog, Integer... values) {
super.onProgressUpdate(dialog, values);
((MaterialDialog) dialog).setMaxProgress(values[1]);
((MaterialDialog) dialog).setProgress(values[0]);
}
public static class LoadingInfo {
final Collection<String> filePaths;
@Nullable
final Map<FieldKey, String> fieldKeyValueMap;
@Nullable
private AbsTagEditorActivity.ArtworkInfo artworkInfo;
public LoadingInfo(Collection<String> filePaths,
@Nullable Map<FieldKey, String> fieldKeyValueMap,
@Nullable AbsTagEditorActivity.ArtworkInfo artworkInfo) {
this.filePaths = filePaths;
this.fieldKeyValueMap = fieldKeyValueMap;
this.artworkInfo = artworkInfo;
}
}
}

View file

@ -0,0 +1,96 @@
package code.name.monkey.retromusic.ui.adapter;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import butterknife.BindViews;
import butterknife.ButterKnife;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.glide.SongGlideRequest;
import code.name.monkey.retromusic.model.Album;
import code.name.monkey.retromusic.ui.adapter.CollageSongAdapter.CollageSongViewHolder;
import code.name.monkey.retromusic.ui.adapter.base.MediaEntryViewHolder;
import code.name.monkey.retromusic.util.NavigationUtil;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
import java.util.List;
/**
* @author Hemanth S (h4h13).
*/
public class CollageSongAdapter extends RecyclerView.Adapter<CollageSongViewHolder> {
private AppCompatActivity activity;
private ArrayList<Album> dataSet;
private int itemLayoutRes;
public CollageSongAdapter(AppCompatActivity activity, ArrayList<Album> dataSet,
int itemLayoutRes) {
this.activity = activity;
this.dataSet = dataSet;
this.itemLayoutRes = itemLayoutRes;
}
@Override
public void onBindViewHolder(@NonNull CollageSongViewHolder holder, int position) {
ArrayList<Album> albums = dataSet;
holder.bindSongs(albums);
if (albums.size() > 9) {
for (int i = 0; i < albums.subList(0, 9).size(); i++) {
if (holder.imageViews != null) {
SongGlideRequest.Builder.from(Glide.with(activity), albums.get(i).safeGetFirstSong())
.checkIgnoreMediaStore(activity).build().into(holder.imageViews.get(i));
}
}
}
}
@Override
public int getItemCount() {
return 1;
}
@NonNull
@Override
public CollageSongViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new CollageSongViewHolder(
LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false));
}
class CollageSongViewHolder extends MediaEntryViewHolder {
@BindViews({R.id.image_1, R.id.image_2, R.id.image_3, R.id.image_4, R.id.image_5, R.id.image_6,
R.id.image_7, R.id.image_8, R.id.image_9})
@Nullable
List<ImageView> imageViews;
CollageSongViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
@Override
public void onClick(View v) {
super.onClick(v);
NavigationUtil.goToAlbum(activity, dataSet.get(getAdapterPosition() + 1).getId());
}
void bindSongs(ArrayList<Album> albums) {
if (imageViews != null) {
for (int i = 0; i < imageViews.size(); i++) {
final int startPosition = i;
ImageView imageView = imageViews.get(i);
imageView.setOnClickListener(
v -> NavigationUtil.goToAlbum(activity, albums.get(startPosition).getId()));
}
}
}
}
}

View file

@ -0,0 +1,93 @@
package code.name.monkey.retromusic.ui.adapter;
import android.app.Activity;
import android.graphics.PorterDuff;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.Locale;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.model.Genre;
import code.name.monkey.retromusic.ui.adapter.base.MediaEntryViewHolder;
import code.name.monkey.retromusic.util.NavigationUtil;
/**
* @author Hemanth S (h4h13).
*/
public class GenreAdapter extends RecyclerView.Adapter<GenreAdapter.ViewHolder> {
private ArrayList<Genre> mGenres = new ArrayList<>();
private Activity mActivity;
private int mItemLayoutRes;
public GenreAdapter(@NonNull Activity activity, ArrayList<Genre> dataSet, int itemLayoutRes) {
mActivity = activity;
mGenres = dataSet;
mItemLayoutRes = itemLayoutRes;
}
public ArrayList<Genre> getDataSet() {
return mGenres;
}
@Override
public GenreAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(mActivity).inflate(mItemLayoutRes, parent, false));
}
@Override
public void onBindViewHolder(GenreAdapter.ViewHolder holder, int position) {
Genre genre = mGenres.get(position);
if (holder.title != null) {
holder.title.setText(genre.name);
}
if (holder.text != null) {
holder.text.setText(String.format(Locale.getDefault(), "%d %s", genre.songCount, genre.songCount > 1 ?
mActivity.getString(R.string.songs) :
mActivity.getString(R.string.song)));
}
if (holder.image != null) {
holder.image.setImageResource(R.drawable.ic_recent_actors_white_24dp);
}
if (holder.shortSeparator != null) {
holder.shortSeparator.setVisibility(View.VISIBLE);
}
}
@Override
public int getItemCount() {
return mGenres.size();
}
public void swapDataSet(ArrayList<Genre> list) {
mGenres = list;
notifyDataSetChanged();
}
public class ViewHolder extends MediaEntryViewHolder {
public ViewHolder(View itemView) {
super(itemView);
if (menu != null) {
menu.setVisibility(View.GONE);
}
if (image != null) {
int iconPadding = mActivity.getResources().getDimensionPixelSize(R.dimen.list_item_image_icon_padding);
image.setPadding(iconPadding, iconPadding, iconPadding, iconPadding);
image.setColorFilter(ATHUtil.resolveColor(mActivity, R.attr.iconColor), PorterDuff.Mode.SRC_IN);
}
}
@Override
public void onClick(View v) {
super.onClick(v);
Genre genre = mGenres.get(getAdapterPosition());
NavigationUtil.goToGenre(mActivity, genre);
}
}
}

View file

@ -0,0 +1,163 @@
package code.name.monkey.retromusic.ui.adapter;
import android.support.annotation.NonNull;
import android.support.v4.util.Pair;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.bumptech.glide.Glide;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.model.Album;
import code.name.monkey.retromusic.model.Artist;
import code.name.monkey.retromusic.model.Song;
import java.util.ArrayList;
import java.util.List;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.glide.ArtistGlideRequest;
import code.name.monkey.retromusic.glide.SongGlideRequest;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.menu.SongMenuHelper;
import code.name.monkey.retromusic.ui.adapter.base.MediaEntryViewHolder;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.NavigationUtil;
public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.ViewHolder> {
private static final int HEADER = 0;
private static final int ALBUM = 1;
private static final int ARTIST = 2;
private static final int SONG = 3;
private final AppCompatActivity activity;
private List<Object> dataSet;
public SearchAdapter(@NonNull AppCompatActivity activity, @NonNull List<Object> dataSet) {
this.activity = activity;
this.dataSet = dataSet;
}
public void swapDataSet(@NonNull ArrayList<Object> dataSet) {
this.dataSet = dataSet;
notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
if (dataSet.get(position) instanceof Album) return ALBUM;
if (dataSet.get(position) instanceof Artist) return ARTIST;
if (dataSet.get(position) instanceof Song) return SONG;
return HEADER;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == HEADER)
return new ViewHolder(LayoutInflater.from(activity).inflate(R.layout.sub_header, parent, false), viewType);
return new ViewHolder(LayoutInflater.from(activity).inflate(R.layout.item_list, parent, false), viewType);
}
@SuppressWarnings("ConstantConditions")
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
switch (getItemViewType(position)) {
case ALBUM:
final Album album = (Album) dataSet.get(position);
holder.title.setText(album.getTitle());
holder.text.setText(album.getArtistName());
SongGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong())
.checkIgnoreMediaStore(activity).build()
.into(holder.image);
break;
case ARTIST:
final Artist artist = (Artist) dataSet.get(position);
holder.title.setText(artist.getName());
holder.text.setText(MusicUtil.getArtistInfoString(activity, artist));
ArtistGlideRequest.Builder.from(Glide.with(activity), artist)
.build().into(holder.image);
break;
case SONG:
final Song song = (Song) dataSet.get(position);
holder.title.setText(song.title);
holder.text.setText(song.albumName);
break;
default:
holder.title.setText(dataSet.get(position).toString());
holder.title.setTextColor(ThemeStore.accentColor(activity));
break;
}
}
@Override
public int getItemCount() {
return dataSet.size();
}
public class ViewHolder extends MediaEntryViewHolder {
public ViewHolder(@NonNull View itemView, int itemViewType) {
super(itemView);
itemView.setOnLongClickListener(null);
if (itemViewType != HEADER) {
if (separator != null) {
separator.setVisibility(View.GONE);
}
}
if (menu != null) {
if (itemViewType == SONG) {
menu.setVisibility(View.VISIBLE);
menu.setOnClickListener(new SongMenuHelper.OnClickSongMenu(activity) {
@Override
public Song getSong() {
return (Song) dataSet.get(getAdapterPosition());
}
});
} else {
menu.setVisibility(View.GONE);
}
}
switch (itemViewType) {
case ALBUM:
setImageTransitionName(activity.getString(R.string.transition_album_art));
break;
case ARTIST:
setImageTransitionName(activity.getString(R.string.transition_artist_image));
break;
default:
View container = itemView.findViewById(R.id.image_container);
if (container != null) {
container.setVisibility(View.GONE);
}
break;
}
}
@Override
public void onClick(View view) {
Object item = dataSet.get(getAdapterPosition());
switch (getItemViewType()) {
case ALBUM:
NavigationUtil.goToAlbum(activity,
((Album) item).getId(), Pair.create(image, activity.getResources().getString(R.string.transition_album_art)));
break;
case ARTIST:
NavigationUtil.goToArtist(activity,
((Artist) item).getId(), Pair.create(image, activity.getResources().getString(R.string.transition_artist_image)));
break;
case SONG:
ArrayList<Song> playList = new ArrayList<>();
playList.add((Song) item);
MusicPlayerRemote.openQueue(playList, 0, true);
break;
}
}
}
}

View file

@ -0,0 +1,214 @@
package code.name.monkey.retromusic.ui.adapter;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.signature.MediaStoreSignature;
import code.name.monkey.appthemehelper.util.ATHUtil;
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView;
import java.io.File;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.glide.audiocover.AudioFileCover;
import code.name.monkey.retromusic.interfaces.CabHolder;
import code.name.monkey.retromusic.ui.adapter.base.AbsMultiSelectAdapter;
import code.name.monkey.retromusic.ui.adapter.base.MediaEntryViewHolder;
import code.name.monkey.retromusic.util.RetroUtil;
public class SongFileAdapter extends AbsMultiSelectAdapter<SongFileAdapter.ViewHolder, File> implements FastScrollRecyclerView.SectionedAdapter {
private static final int FILE = 0;
private static final int FOLDER = 1;
private final AppCompatActivity activity;
private List<File> dataSet;
private final int itemLayoutRes;
@Nullable
private final Callbacks callbacks;
public SongFileAdapter(@NonNull AppCompatActivity activity, @NonNull List<File> songFiles, @LayoutRes int itemLayoutRes, @Nullable Callbacks callback, @Nullable CabHolder cabHolder) {
super(activity, cabHolder, R.menu.menu_media_selection);
this.activity = activity;
this.dataSet = songFiles;
this.itemLayoutRes = itemLayoutRes;
this.callbacks = callback;
setHasStableIds(true);
}
@Override
public int getItemViewType(int position) {
return dataSet.get(position).isDirectory() ? FOLDER : FILE;
}
@Override
public long getItemId(int position) {
return dataSet.get(position).hashCode();
}
public void swapDataSet(@NonNull List<File> songFiles) {
this.dataSet = songFiles;
notifyDataSetChanged();
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false));
}
@Override
public void onBindViewHolder(final ViewHolder holder, int index) {
final File file = dataSet.get(index);
holder.itemView.setActivated(isChecked(file));
if (holder.getAdapterPosition() == getItemCount() - 1) {
if (holder.shortSeparator != null) {
holder.shortSeparator.setVisibility(View.GONE);
}
} else {
if (holder.shortSeparator != null) {
holder.shortSeparator.setVisibility(View.VISIBLE);
}
}
if (holder.title != null) {
holder.title.setText(getFileTitle(file));
}
if (holder.text != null) {
if (holder.getItemViewType() == FILE) {
holder.text.setText(getFileText(file));
} else {
holder.text.setVisibility(View.GONE);
}
}
if (holder.image != null) {
loadFileImage(file, holder);
}
}
protected String getFileTitle(File file) {
return file.getName();
}
protected String getFileText(File file) {
return file.isDirectory() ? null : readableFileSize(file.length());
}
@SuppressWarnings("ConstantConditions")
protected void loadFileImage(File file, final ViewHolder holder) {
final int iconColor = ATHUtil.resolveColor(activity, R.attr.iconColor);
if (file.isDirectory()) {
holder.image.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN);
holder.image.setImageResource(R.drawable.ic_folder_white_24dp);
} else {
Drawable error = RetroUtil.getTintedVectorDrawable(activity, R.drawable.ic_file_music_white_24dp, iconColor);
Glide.with(activity)
.load(new AudioFileCover(file.getPath()))
.diskCacheStrategy(DiskCacheStrategy.NONE)
.error(error)
.placeholder(error)
.animate(android.R.anim.fade_in)
.signature(new MediaStoreSignature("", file.lastModified(), 0))
.into(holder.image);
}
}
public static String readableFileSize(long size) {
if (size <= 0) return size + " B";
final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};
int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
return new DecimalFormat("#,##0.##").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
}
@Override
public int getItemCount() {
return dataSet.size();
}
@Override
protected File getIdentifier(int position) {
return dataSet.get(position);
}
@Override
protected String getName(File object) {
return getFileTitle(object);
}
@Override
protected void onMultipleItemAction(MenuItem menuItem, ArrayList<File> selection) {
if (callbacks == null) return;
callbacks.onMultipleItemAction(menuItem, selection);
}
@NonNull
@Override
public String getSectionName(int position) {
return String.valueOf(dataSet.get(position).getName().charAt(0)).toUpperCase();
}
public class ViewHolder extends MediaEntryViewHolder {
public ViewHolder(View itemView) {
super(itemView);
if (menu != null && callbacks != null) {
menu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = getAdapterPosition();
if (isPositionInRange(position)) {
callbacks.onFileMenuClicked(dataSet.get(position), v);
}
}
});
}
}
@Override
public void onClick(View v) {
int position = getAdapterPosition();
if (isPositionInRange(position)) {
if (isInQuickSelectMode()) {
toggleChecked(position);
} else {
if (callbacks != null) {
callbacks.onFileSelected(dataSet.get(position));
}
}
}
}
@Override
public boolean onLongClick(View view) {
int position = getAdapterPosition();
return isPositionInRange(position) && toggleChecked(position);
}
private boolean isPositionInRange(int position) {
return position >= 0 && position < dataSet.size();
}
}
public interface Callbacks {
void onFileSelected(File file);
void onFileMenuClicked(File file, View view);
void onMultipleItemAction(MenuItem item, ArrayList<File> files);
}
}

View file

@ -0,0 +1,258 @@
package code.name.monkey.retromusic.ui.adapter.album;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.util.Pair;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import com.bumptech.glide.Glide;
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView;
import java.util.ArrayList;
import java.util.List;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget;
import code.name.monkey.retromusic.glide.SongGlideRequest;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.SortOrder;
import code.name.monkey.retromusic.helper.menu.SongsMenuHelper;
import code.name.monkey.retromusic.interfaces.CabHolder;
import code.name.monkey.retromusic.model.Album;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.ui.adapter.base.AbsMultiSelectAdapter;
import code.name.monkey.retromusic.ui.adapter.base.MediaEntryViewHolder;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.NavigationUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
public class AlbumAdapter extends AbsMultiSelectAdapter<AlbumAdapter.ViewHolder, Album> implements
FastScrollRecyclerView.SectionedAdapter {
public static final String TAG = AlbumAdapter.class.getSimpleName();
protected final AppCompatActivity activity;
protected ArrayList<Album> dataSet;
protected int itemLayoutRes;
protected boolean usePalette = false;
private int textColor;
public AlbumAdapter(@NonNull AppCompatActivity activity, ArrayList<Album> dataSet,
@LayoutRes int itemLayoutRes, boolean usePalette,
@Nullable CabHolder cabHolder) {
super(activity, cabHolder, R.menu.menu_media_selection);
this.activity = activity;
this.dataSet = dataSet;
this.itemLayoutRes = itemLayoutRes;
this.usePalette = usePalette;
setHasStableIds(true);
this.textColor = ThemeStore.textColorPrimary(activity);
Typeface mTypeface = Typeface
.createFromAsset(activity.getAssets(), activity.getString(R.string.sans_regular));
}
public void useItemLayout(int itemLayoutRes) {
this.itemLayoutRes = itemLayoutRes;
notifyDataSetChanged();
}
public void usePalette(boolean usePalette) {
this.usePalette = usePalette;
notifyDataSetChanged();
}
public void swapDataSet(ArrayList<Album> dataSet) {
this.dataSet = dataSet;
notifyDataSetChanged();
}
public ArrayList<Album> getDataSet() {
return dataSet;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false);
return createViewHolder(view, viewType);
}
protected ViewHolder createViewHolder(View view, int viewType) {
return new ViewHolder(view);
}
private String getAlbumTitle(Album album) {
return album.getTitle();
}
protected String getAlbumText(Album album) {
return album.getArtistName();
}
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
final Album album = dataSet.get(position);
final boolean isChecked = isChecked(album);
holder.itemView.setActivated(isChecked);
if (holder.getAdapterPosition() == getItemCount() - 1) {
if (holder.shortSeparator != null) {
holder.shortSeparator.setVisibility(View.GONE);
}
} else {
if (holder.shortSeparator != null) {
holder.shortSeparator.setVisibility(View.VISIBLE);
}
}
if (holder.title != null) {
holder.title.setText(getAlbumTitle(album));
holder.title.setTextColor(textColor);
}
if (holder.text != null) {
holder.text.setText(getAlbumText(album));
}
if (holder.playSongs != null) {
holder.playSongs.setOnClickListener(v -> MusicPlayerRemote.openQueue(album.songs, 0, true));
}
loadAlbumCover(album, holder);
}
protected void setColors(int color, ViewHolder holder) {
if (holder.paletteColorContainer != null) {
holder.paletteColorContainer.setBackgroundColor(color);
if (holder.title != null) {
holder.title.setTextColor(
MaterialValueHelper.getPrimaryTextColor(activity, ColorUtil.isColorLight(color)));
}
if (holder.text != null) {
holder.text.setTextColor(
MaterialValueHelper.getSecondaryTextColor(activity, ColorUtil.isColorLight(color)));
}
}
}
protected void loadAlbumCover(Album album, final ViewHolder holder) {
if (holder.image == null) {
return;
}
SongGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong())
.checkIgnoreMediaStore(activity)
.generatePalette(activity).build()
.into(new RetroMusicColoredTarget(holder.image) {
@Override
public void onLoadCleared(Drawable placeholder) {
super.onLoadCleared(placeholder);
setColors(getDefaultFooterColor(), holder);
}
@Override
public void onColorReady(int color) {
setColors(color, holder);
}
});
}
@Override
public int getItemCount() {
return dataSet.size();
}
@Override
public long getItemId(int position) {
return dataSet.get(position).getId();
}
@Override
protected Album getIdentifier(int position) {
return dataSet.get(position);
}
@Override
protected String getName(Album album) {
return album.getTitle();
}
@Override
protected void onMultipleItemAction(@NonNull MenuItem menuItem,
@NonNull ArrayList<Album> selection) {
SongsMenuHelper.handleMenuClick(activity, getSongList(selection), menuItem.getItemId());
}
@NonNull
private ArrayList<Song> getSongList(@NonNull List<Album> albums) {
final ArrayList<Song> songs = new ArrayList<>();
for (Album album : albums) {
songs.addAll(album.songs);
}
return songs;
}
@NonNull
@Override
public String getSectionName(int position) {
@Nullable String sectionName = null;
switch (PreferenceUtil.getInstance(activity).getAlbumSortOrder()) {
case SortOrder.AlbumSortOrder.ALBUM_A_Z:
case SortOrder.AlbumSortOrder.ALBUM_Z_A:
sectionName = dataSet.get(position).getTitle();
break;
case SortOrder.AlbumSortOrder.ALBUM_ARTIST:
sectionName = dataSet.get(position).getArtistName();
break;
case SortOrder.AlbumSortOrder.ALBUM_YEAR:
return MusicUtil.getYearString(dataSet.get(position).getYear());
}
return MusicUtil.getSectionName(sectionName);
}
public void setTextColor(int textColor) {
this.textColor = textColor;
notifyDataSetChanged();
}
public class ViewHolder extends MediaEntryViewHolder {
public ViewHolder(@NonNull final View itemView) {
super(itemView);
setImageTransitionName(activity.getString(R.string.transition_album_art));
if (menu != null) {
menu.setVisibility(View.GONE);
}
}
@Override
public void onClick(View v) {
if (isInQuickSelectMode()) {
toggleChecked(getAdapterPosition());
} else {
Pair[] albumPairs = new Pair[]{
Pair.create(image, activity.getResources().getString(R.string.transition_album_art))};
NavigationUtil.goToAlbum(activity, dataSet.get(getAdapterPosition()).getId(), albumPairs);
}
}
@Override
public boolean onLongClick(View view) {
toggleChecked(getAdapterPosition());
return true;
}
}
}

View file

@ -0,0 +1,208 @@
package code.name.monkey.retromusic.ui.adapter.album;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget;
import code.name.monkey.retromusic.glide.SongGlideRequest;
import code.name.monkey.retromusic.misc.CustomFragmentStatePagerAdapter;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.ui.activities.LyricsActivity;
import code.name.monkey.retromusic.ui.fragments.NowPlayingScreen;
import code.name.monkey.retromusic.util.PreferenceUtil;
public class AlbumCoverPagerAdapter extends CustomFragmentStatePagerAdapter {
public static final String TAG = AlbumCoverPagerAdapter.class.getSimpleName();
private ArrayList<Song> dataSet;
private AlbumCoverFragment.ColorReceiver currentColorReceiver;
private int currentColorReceiverPosition = -1;
public AlbumCoverPagerAdapter(FragmentManager fm, ArrayList<Song> dataSet) {
super(fm);
this.dataSet = dataSet;
}
@Override
public Fragment getItem(final int position) {
return AlbumCoverFragment.newInstance(dataSet.get(position));
}
@Override
public int getCount() {
return dataSet.size();
}
@NonNull
@Override
public Object instantiateItem(ViewGroup container, int position) {
Object o = super.instantiateItem(container, position);
if (currentColorReceiver != null && currentColorReceiverPosition == position) {
receiveColor(currentColorReceiver, currentColorReceiverPosition);
}
return o;
}
/**
* Only the latest passed {@link AlbumCoverFragment.ColorReceiver} is guaranteed to receive a
* response
*/
public void receiveColor(AlbumCoverFragment.ColorReceiver colorReceiver, int position) {
AlbumCoverFragment fragment = (AlbumCoverFragment) getFragment(position);
if (fragment != null) {
currentColorReceiver = null;
currentColorReceiverPosition = -1;
fragment.receiveColor(colorReceiver, position);
} else {
currentColorReceiver = colorReceiver;
currentColorReceiverPosition = position;
}
}
public static class AlbumCoverFragment extends Fragment {
private static final String SONG_ARG = "song";
@BindView(R.id.player_image)
ImageView albumCover;
private Unbinder unbinder;
private boolean isColorReady;
private int color;
private Song song;
private ColorReceiver colorReceiver;
private int request;
public static AlbumCoverFragment newInstance(final Song song) {
AlbumCoverFragment frag = new AlbumCoverFragment();
final Bundle args = new Bundle();
args.putParcelable(SONG_ARG, song);
frag.setArguments(args);
return frag;
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
song = getArguments().getParcelable(SONG_ARG);
}
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
int layout = getLayout();
View view = inflater.inflate(layout, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
private int getLayout() {
int layout;
//noinspection ConstantConditions
switch (PreferenceUtil.getInstance(getContext()).getNowPlayingScreen()) {
case BLUR_CARD:
layout = R.layout.fragment_album_card_cover;
break;
case MATERIAL:
layout = R.layout.fragment_album_material_cover;
break;
case PLAIN:
case FLAT:
layout = R.layout.fragment_album_flat_cover;
break;
case CARD:
case FULL:
case ADAPTIVE:
layout = R.layout.fragment_album_full_cover;
break;
default:
case NORMAL:
layout = R.layout.fragment_album_cover;
break;
}
if (PreferenceUtil.getInstance(getContext()).carouselEffect() &&
!(PreferenceUtil.getInstance(getContext()).getNowPlayingScreen()
== NowPlayingScreen.FULL)) {
layout = R.layout.fragment_carousal_album_cover;
}
if (PreferenceUtil.getInstance(getContext()).circularAlbumArt()) {
layout = R.layout.fragment_album_circle_cover;
}
return layout;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
loadAlbumCover();
}
@OnClick(R.id.player_image)
void showLyrics() {
startActivity(new Intent(getContext(), LyricsActivity.class));
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
colorReceiver = null;
}
private void loadAlbumCover() {
SongGlideRequest.Builder.from(Glide.with(this), song)
.checkIgnoreMediaStore(getActivity())
.generatePalette(getActivity()).build()
.into(new RetroMusicColoredTarget(albumCover) {
@Override
public void onColorReady(int color) {
setColor(color);
}
});
}
private void setColor(int color) {
this.color = color;
isColorReady = true;
if (colorReceiver != null) {
colorReceiver.onColorReady(color, request);
colorReceiver = null;
}
}
public void receiveColor(ColorReceiver colorReceiver, int request) {
if (isColorReady) {
colorReceiver.onColorReady(color, request);
} else {
this.colorReceiver = colorReceiver;
this.request = request;
}
}
public interface ColorReceiver {
void onColorReady(int color, int request);
}
}
}

View file

@ -0,0 +1,147 @@
/*
* Copyright (C) 2017. Alexander Bilchuk <a.bilchuk@sandrlab.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package code.name.monkey.retromusic.ui.adapter.album;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.support.annotation.NonNull;
import android.support.v4.util.Pair;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget;
import code.name.monkey.retromusic.glide.SongGlideRequest;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.model.Album;
import code.name.monkey.retromusic.util.NavigationUtil;
import code.name.monkey.retromusic.views.MetalRecyclerViewPager;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
import java.util.List;
public class AlbumFullWithAdapter extends
MetalRecyclerViewPager.MetalAdapter<AlbumFullWithAdapter.FullMetalViewHolder> {
private Activity activity;
private List<Album> dataSet = new ArrayList<>();
public AlbumFullWithAdapter(@NonNull Activity activity,
@NonNull DisplayMetrics metrics) {
super(metrics);
this.activity = activity;
}
public void swapData(ArrayList<Album> list) {
dataSet = list;
notifyDataSetChanged();
}
@Override
public FullMetalViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View viewItem = LayoutInflater.from(parent.getContext())
.inflate(R.layout.pager_item, parent, false);
return new FullMetalViewHolder(viewItem);
}
private Bitmap combineImageIntoOne(ArrayList<Bitmap> bitmap) {
int w = 0, h = 0;
for (int i = 0; i < bitmap.size(); i++) {
if (i < bitmap.size() - 1) {
h = bitmap.get(i).getWidth() > bitmap.get(i + 1).getWidth() ? bitmap.get(i).getWidth()
: bitmap.get(i + 1).getWidth();
}
w += bitmap.get(i).getHeight();
}
Bitmap temp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(temp);
int top = 0, left = 0;
for (int i = 0; i < bitmap.size(); i++) {
Log.d("HTML", "Combine: " + i + "/" + bitmap.size() + 1);
top = (i == 0 ? 0 : top + bitmap.get(i).getHeight());
left = (i == 0 ? 0 : top + bitmap.get(i).getWidth());
canvas.drawBitmap(bitmap.get(i), left, 0f, null);
}
return temp;
}
@Override
public void onBindViewHolder(FullMetalViewHolder holder, int position) {
// don't forget about calling supper.onBindViewHolder!
super.onBindViewHolder(holder, position);
final Album album = dataSet.get(position);
if (holder.title != null) {
holder.title.setText(getAlbumTitle(album));
}
if (holder.text != null) {
holder.text.setText(getAlbumText(album));
}
if (holder.playSongs != null) {
holder.playSongs.setOnClickListener(v -> MusicPlayerRemote.openQueue(album.songs, 0, true));
}
loadAlbumCover(album, holder);
}
private String getAlbumTitle(Album album) {
return album.getTitle();
}
private String getAlbumText(Album album) {
return album.getArtistName();
}
private void loadAlbumCover(Album album, FullMetalViewHolder holder) {
if (holder.image == null) {
return;
}
SongGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong())
.checkIgnoreMediaStore(activity)
.generatePalette(activity).build()
.into(new RetroMusicColoredTarget(holder.image) {
@Override
public void onColorReady(int color) {
}
});
}
@Override
public int getItemCount() {
return dataSet.size();
}
class FullMetalViewHolder extends MetalRecyclerViewPager.MetalViewHolder {
FullMetalViewHolder(View itemView) {
super(itemView);
}
@Override
public void onClick(View v) {
Pair[] albumPairs = new Pair[]{
Pair.create(image, activity.getResources().getString(R.string.transition_album_art))};
NavigationUtil.goToAlbum(activity, dataSet.get(getAdapterPosition()).getId(), albumPairs);
}
}
}

View file

@ -0,0 +1,83 @@
package code.name.monkey.retromusic.ui.adapter.album;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget;
import code.name.monkey.retromusic.glide.SongGlideRequest;
import code.name.monkey.retromusic.helper.HorizontalAdapterHelper;
import code.name.monkey.retromusic.interfaces.CabHolder;
import code.name.monkey.retromusic.model.Album;
import code.name.monkey.retromusic.util.MusicUtil;
public class HorizontalAlbumAdapter extends AlbumAdapter {
public static final String TAG = AlbumAdapter.class.getSimpleName();
public HorizontalAlbumAdapter(@NonNull AppCompatActivity activity, ArrayList<Album> dataSet, boolean usePalette, @Nullable CabHolder cabHolder) {
super(activity, dataSet, HorizontalAdapterHelper.LAYOUT_RES, usePalette, cabHolder);
}
@Override
protected ViewHolder createViewHolder(View view, int viewType) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
HorizontalAdapterHelper.applyMarginToLayoutParams(activity, params, viewType);
return new ViewHolder(view);
}
@Override
protected void setColors(int color, ViewHolder holder) {
if (holder.itemView != null) {
if (holder.title != null) {
holder.title.setTextColor(MaterialValueHelper.getPrimaryTextColor(activity, ColorUtil.isColorLight(color)));
}
if (holder.text != null) {
holder.text.setTextColor(MaterialValueHelper.getSecondaryTextColor(activity, ColorUtil.isColorLight(color)));
}
}
}
@Override
protected void loadAlbumCover(Album album, final ViewHolder holder) {
if (holder.image == null) return;
SongGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong())
.checkIgnoreMediaStore(activity)
.generatePalette(activity).build()
.into(new RetroMusicColoredTarget(holder.image) {
@Override
public void onLoadCleared(Drawable placeholder) {
super.onLoadCleared(placeholder);
setColors(getAlbumArtistFooterColor(), holder);
}
@Override
public void onColorReady(int color) {
if (usePalette)
setColors(color, holder);
else
setColors(getAlbumArtistFooterColor(), holder);
}
});
}
@Override
protected String getAlbumText(Album album) {
return MusicUtil.getYearString(album.getYear());
}
@Override
public int getItemViewType(int position) {
return HorizontalAdapterHelper.getItemViewtype(position, getItemCount());
}
}

View file

@ -0,0 +1,188 @@
package code.name.monkey.retromusic.ui.adapter.artist;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.util.Pair;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.glide.ArtistGlideRequest;
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget;
import code.name.monkey.retromusic.helper.menu.SongsMenuHelper;
import code.name.monkey.retromusic.interfaces.CabHolder;
import code.name.monkey.retromusic.model.Artist;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.ui.adapter.base.AbsMultiSelectAdapter;
import code.name.monkey.retromusic.ui.adapter.base.MediaEntryViewHolder;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.NavigationUtil;
import com.bumptech.glide.Glide;
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView;
import java.util.ArrayList;
import java.util.List;
public class ArtistAdapter extends
AbsMultiSelectAdapter<ArtistAdapter.ViewHolder, Artist> implements
FastScrollRecyclerView.SectionedAdapter {
protected final AppCompatActivity activity;
protected ArrayList<Artist> dataSet;
protected int itemLayoutRes;
protected boolean usePalette = false;
public ArtistAdapter(@NonNull AppCompatActivity activity, ArrayList<Artist> dataSet,
@LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) {
super(activity, cabHolder, R.menu.menu_media_selection);
this.activity = activity;
this.dataSet = dataSet;
this.itemLayoutRes = itemLayoutRes;
this.usePalette = usePalette;
//setHasStableIds(true);
}
public void swapDataSet(ArrayList<Artist> dataSet) {
this.dataSet = dataSet;
notifyDataSetChanged();
}
public ArrayList<Artist> getDataSet() {
return dataSet;
}
public void usePalette(boolean usePalette) {
this.usePalette = usePalette;
notifyDataSetChanged();
}
@Override
public long getItemId(int position) {
return dataSet.get(position).getId();
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false);
return createViewHolder(view);
}
protected ViewHolder createViewHolder(View view) {
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
final Artist artist = dataSet.get(position);
boolean isChecked = isChecked(artist);
holder.itemView.setActivated(isChecked);
if (holder.title != null) {
holder.title.setText(artist.getName());
}
if (holder.text != null) {
holder.text.setVisibility(View.GONE);
}
if (holder.shortSeparator != null) {
holder.shortSeparator.setVisibility(View.VISIBLE);
}
loadArtistImage(artist, holder);
}
protected void setColors(int color, ViewHolder holder) {
if (holder.paletteColorContainer != null) {
holder.paletteColorContainer.setBackgroundColor(color);
if (holder.title != null) {
holder.title.setTextColor(
MaterialValueHelper.getPrimaryTextColor(activity, ColorUtil.isColorLight(color)));
}
}
}
private void loadArtistImage(Artist artist, final ViewHolder holder) {
if (holder.image == null) {
return;
}
ArtistGlideRequest.Builder.from(Glide.with(activity), artist)
.generatePalette(activity).build()
.into(new RetroMusicColoredTarget(holder.image) {
@Override
public void onColorReady(int color) {
setColors(color, holder);
}
});
}
@Override
public int getItemCount() {
return dataSet.size();
}
@Override
protected Artist getIdentifier(int position) {
return dataSet.get(position);
}
@Override
protected String getName(Artist artist) {
return artist.getName();
}
@Override
protected void onMultipleItemAction(@NonNull MenuItem menuItem,
@NonNull ArrayList<Artist> selection) {
SongsMenuHelper.handleMenuClick(activity, getSongList(selection), menuItem.getItemId());
}
@NonNull
private ArrayList<Song> getSongList(@NonNull List<Artist> artists) {
final ArrayList<Song> songs = new ArrayList<>();
for (Artist artist : artists) {
songs.addAll(artist.getSongs()); // maybe async in future?
}
return songs;
}
@NonNull
@Override
public String getSectionName(int position) {
return MusicUtil.getSectionName(dataSet.get(position).getName());
}
public class ViewHolder extends MediaEntryViewHolder {
public ViewHolder(@NonNull View itemView) {
super(itemView);
setImageTransitionName(activity.getString(R.string.transition_artist_image));
if (menu != null) {
menu.setVisibility(View.GONE);
}
}
@Override
public void onClick(View v) {
if (isInQuickSelectMode()) {
toggleChecked(getAdapterPosition());
} else {
Pair[] artistPairs = new Pair[]{Pair.create(image,
activity.getResources().getString(R.string.transition_artist_image))};
NavigationUtil.goToArtist(activity, dataSet.get(getAdapterPosition()).getId(), artistPairs);
}
}
@Override
public boolean onLongClick(View view) {
toggleChecked(getAdapterPosition());
return true;
}
}
}

View file

@ -0,0 +1,121 @@
package code.name.monkey.retromusic.ui.adapter.base;
import android.content.Context;
import android.support.annotation.MenuRes;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.view.Menu;
import android.view.MenuItem;
import com.afollestad.materialcab.MaterialCab;
import java.util.ArrayList;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.interfaces.CabHolder;
public abstract class AbsMultiSelectAdapter<VH extends RecyclerView.ViewHolder, I> extends RecyclerView.Adapter<VH> implements MaterialCab.Callback {
@Nullable
private final CabHolder cabHolder;
private final Context context;
private MaterialCab cab;
private ArrayList<I> checked;
private int menuRes;
public AbsMultiSelectAdapter(Context context, @Nullable CabHolder cabHolder, @MenuRes int menuRes) {
this.cabHolder = cabHolder;
checked = new ArrayList<>();
this.menuRes = menuRes;
this.context = context;
}
protected void setMultiSelectMenuRes(@MenuRes int menuRes) {
this.menuRes = menuRes;
}
protected boolean toggleChecked(final int position) {
if (cabHolder != null) {
I identifier = getIdentifier(position);
if (identifier == null) return false;
if (!checked.remove(identifier)) checked.add(identifier);
notifyItemChanged(position);
updateCab();
return true;
}
return false;
}
protected void checkAll() {
if (cabHolder != null) {
checked.clear();
for (int i = 0; i < getItemCount(); i++) {
I identifier = getIdentifier(i);
if (identifier != null) {
checked.add(identifier);
}
}
notifyDataSetChanged();
updateCab();
}
}
private void updateCab() {
if (cabHolder != null) {
if (cab == null || !cab.isActive()) {
cab = cabHolder.openCab(menuRes, this);
}
final int size = checked.size();
if (size <= 0) cab.finish();
else if (size == 1) cab.setTitle(getName(checked.get(0)));
else cab.setTitle(context.getString(R.string.x_selected, size));
}
}
private void clearChecked() {
checked.clear();
notifyDataSetChanged();
}
protected boolean isChecked(I identifier) {
return checked.contains(identifier);
}
protected boolean isInQuickSelectMode() {
return cab != null && cab.isActive();
}
@Override
public boolean onCabCreated(MaterialCab materialCab, Menu menu) {
return true;
}
@Override
public boolean onCabItemClicked(MenuItem menuItem) {
if (menuItem.getItemId() == R.id.action_multi_select_adapter_check_all) {
checkAll();
} else {
onMultipleItemAction(menuItem, new ArrayList<>(checked));
cab.finish();
clearChecked();
}
return true;
}
@Override
public boolean onCabFinished(MaterialCab materialCab) {
clearChecked();
return true;
}
protected String getName(I object) {
return object.toString();
}
@Nullable
protected abstract I getIdentifier(int position);
protected abstract void onMultipleItemAction(MenuItem menuItem, ArrayList<I> selection);
}

View file

@ -0,0 +1,98 @@
package code.name.monkey.retromusic.ui.adapter.base;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.R;
public class MediaEntryViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener, View.OnLongClickListener {
@Nullable
@BindView(R.id.image)
public ImageView image;
@Nullable
@BindView(R.id.image_text)
public TextView imageText;
@Nullable
@BindView(R.id.title)
public TextView title;
@Nullable
@BindView(R.id.text)
public TextView text;
@Nullable
@BindView(R.id.image_container)
public ViewGroup imageContainer;
@Nullable
@BindView(R.id.image_container_card)
public CardView imageContainerCard;
@Nullable
@BindView(R.id.menu)
public View menu;
@Nullable
@BindView(R.id.separator)
public View separator;
@Nullable
@BindView(R.id.short_separator)
public View shortSeparator;
@Nullable
@BindView(R.id.drag_view)
public View dragView;
@Nullable
@BindView(R.id.palette_color_container)
public View paletteColorContainer;
@BindView(R.id.time)
@Nullable
public TextView time;
@BindView(R.id.recycler_view)
@Nullable
public RecyclerView recyclerView;
@BindView(R.id.play_songs)
@Nullable
public ImageButton playSongs;
@BindView(R.id.image_text_container)
@Nullable
public CardView imageTextContainer;
public MediaEntryViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
if (imageTextContainer != null) {
imageTextContainer.setCardBackgroundColor(ThemeStore.primaryColor(itemView.getContext()));
}
if (imageContainerCard != null) {
imageContainerCard.setCardBackgroundColor(ThemeStore.primaryColor(itemView.getContext()));
}
}
protected void setImageTransitionName(@NonNull String transitionName) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && image != null) {
image.setTransitionName(transitionName);
}
}
@Override
public boolean onLongClick(View v) {
return false;
}
@Override
public void onClick(View v) {
}
}

View file

@ -0,0 +1,169 @@
package code.name.monkey.retromusic.ui.adapter.home;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import butterknife.BindView;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.loaders.SongLoader;
import code.name.monkey.retromusic.model.Album;
import code.name.monkey.retromusic.model.Artist;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.model.smartplaylist.HistoryPlaylist;
import code.name.monkey.retromusic.model.smartplaylist.LastAddedPlaylist;
import code.name.monkey.retromusic.model.smartplaylist.MyTopTracksPlaylist;
import code.name.monkey.retromusic.ui.adapter.album.AlbumAdapter;
import code.name.monkey.retromusic.ui.adapter.artist.ArtistAdapter;
import code.name.monkey.retromusic.ui.adapter.base.MediaEntryViewHolder;
import code.name.monkey.retromusic.ui.adapter.song.SongAdapter;
import code.name.monkey.retromusic.util.NavigationUtil;
import java.util.ArrayList;
public class HomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int SUB_HEADER = 0;
private static final int ABS_PLAYLITS = 1;
private static final int DATA = 2;
private ArrayList<Object> dataSet = new ArrayList<>();
private AppCompatActivity activity;
public HomeAdapter(@NonNull AppCompatActivity activity) {
this.activity = activity;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
switch (i) {
case ABS_PLAYLITS:
return new ViewHolder(LayoutInflater.from(activity)
.inflate(R.layout.abs_playlists, viewGroup, false));
default:
case DATA:
return new ViewHolder(LayoutInflater.from(activity)
.inflate(R.layout.recycler_view_sec, viewGroup, false));
case SUB_HEADER:
return new ViewHolder(LayoutInflater.from(activity)
.inflate(R.layout.sub_header, viewGroup, false));
}
}
@Override
public int getItemViewType(int position) {
if (dataSet.get(position) instanceof String) {
return SUB_HEADER;
} else if (dataSet.get(position) instanceof Integer) {
return ABS_PLAYLITS;
} else if (dataSet.get(position) instanceof ArrayList) {
return DATA;
}
return super.getItemViewType(position);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int i) {
ViewHolder viewholder = (ViewHolder) holder;
switch (getItemViewType(i)) {
case ABS_PLAYLITS:
bindAbsActions(viewholder);
break;
case SUB_HEADER:
String title = (String) dataSet.get(i);
if (viewholder.title != null) {
viewholder.title.setText(title);
}
break;
case DATA:
parseAllSections(i, viewholder);
break;
}
}
private void bindAbsActions(ViewHolder viewholder) {
if (viewholder.shuffle != null) {
viewholder.shuffle.setOnClickListener(view -> MusicPlayerRemote
.openAndShuffleQueue(SongLoader.getAllSongs(activity).blockingFirst(), true));
}
/*if (viewholder.search != null) {
viewholder.search.setBackgroundTintList(ColorStateList.valueOf(ColorUtil.withAlpha(ThemeStore.textColorPrimary(activity), 0.2f)));
viewholder.search.setOnClickListener(view -> {
activity.startActivity(new Intent(activity, SearchActivity.class));
});
}*/
}
@SuppressWarnings("unchecked")
private void parseAllSections(int i, ViewHolder viewholder) {
if (viewholder.recyclerView != null) {
ArrayList arrayList = (ArrayList) dataSet.get(i);
if (arrayList.isEmpty()) {
return;
}
Object something = arrayList.get(0);
if (something instanceof Artist) {
layoutManager(viewholder);
viewholder.recyclerView.setAdapter(
new ArtistAdapter(activity, (ArrayList<Artist>) arrayList, R.layout.item_artist, false,
null));
} else if (something instanceof Album) {
layoutManager(viewholder);
viewholder.recyclerView.setItemAnimator(new DefaultItemAnimator());
viewholder.recyclerView.setAdapter(
new AlbumAdapter(activity, (ArrayList<Album>) arrayList, R.layout.item_image, false,
null));
} else if (something instanceof Song) {
GridLayoutManager layoutManager = new GridLayoutManager(activity, 1,
LinearLayoutManager.HORIZONTAL, false);
viewholder.recyclerView.setLayoutManager(layoutManager);
viewholder.recyclerView.setAdapter(
new SongAdapter(activity, (ArrayList<Song>) arrayList, R.layout.item_image, false,
null));
}
}
}
private void layoutManager(ViewHolder viewholder) {
if (viewholder.recyclerView != null) {
viewholder.recyclerView.setLayoutManager(
new GridLayoutManager(activity, 1, GridLayoutManager.HORIZONTAL, false));
viewholder.recyclerView.setItemAnimator(new DefaultItemAnimator());
}
}
@Override
public int getItemCount() {
return dataSet.size();
}
public void swapDataSet(@NonNull ArrayList<Object> data) {
dataSet = data;
notifyDataSetChanged();
}
public ArrayList<Object> getDataset() {
return dataSet;
}
public class ViewHolder extends MediaEntryViewHolder {
@BindView(R.id.action_shuffle)
@Nullable
View shuffle;
public ViewHolder(View itemView) {
super(itemView);
}
}
}

View file

@ -0,0 +1,300 @@
package code.name.monkey.retromusic.ui.adapter.playlist;
import android.graphics.Bitmap;
import android.graphics.PorterDuff;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.PopupMenu;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.ExecutionException;
import butterknife.ButterKnife;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.dialogs.ClearSmartPlaylistDialog;
import code.name.monkey.retromusic.dialogs.DeletePlaylistDialog;
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper;
import code.name.monkey.retromusic.helper.menu.SongsMenuHelper;
import code.name.monkey.retromusic.interfaces.CabHolder;
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader;
import code.name.monkey.retromusic.model.AbsCustomPlaylist;
import code.name.monkey.retromusic.model.Playlist;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.model.smartplaylist.AbsSmartPlaylist;
import code.name.monkey.retromusic.model.smartplaylist.LastAddedPlaylist;
import code.name.monkey.retromusic.ui.adapter.base.AbsMultiSelectAdapter;
import code.name.monkey.retromusic.ui.adapter.base.MediaEntryViewHolder;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.NavigationUtil;
import code.name.monkey.retromusic.util.RetroUtil;
import io.reactivex.Observable;
/**
* Created by BlackFootSanji on 9/19/2016.
*/
public class PlaylistAdapter extends AbsMultiSelectAdapter<PlaylistAdapter.ViewHolder, Playlist> {
public static final String TAG = PlaylistAdapter.class.getSimpleName();
private static final int SMART_PLAYLIST = 0;
private static final int DEFAULT_PLAYLIST = 1;
protected final AppCompatActivity activity;
protected ArrayList<Playlist> dataSet;
protected int itemLayoutRes;
private ArrayList<Song> mSongs = new ArrayList<>();
public PlaylistAdapter(AppCompatActivity activity, ArrayList<Playlist> dataSet,
@LayoutRes int itemLayoutRes, @Nullable CabHolder cabHolder) {
super(activity, cabHolder, R.menu.menu_playlists_selection);
this.activity = activity;
this.dataSet = dataSet;
this.itemLayoutRes = itemLayoutRes;
setHasStableIds(true);
}
public ArrayList<Playlist> getDataSet() {
return dataSet;
}
public void swapDataSet(ArrayList<Playlist> dataSet) {
this.dataSet = dataSet;
notifyDataSetChanged();
}
@Override
public long getItemId(int position) {
return dataSet.get(position).id;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(activity)
.inflate(itemLayoutRes, parent, false);
return createViewHolder(view, viewType);
}
protected ViewHolder createViewHolder(View view, int viewType) {
return new ViewHolder(view, viewType);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
/* if (getItemViewType(position) == SMART_PLAYLIST) {
if (holder.viewList != null) {
holder.viewList.get(0).setOnClickListener(
v -> NavigationUtil.goToPlaylistNew(activity, new HistoryPlaylist(activity)));
holder.viewList.get(1).setOnClickListener(
v -> NavigationUtil.goToPlaylistNew(activity, new LastAddedPlaylist(activity)));
holder.viewList.get(2).setOnClickListener(
v -> NavigationUtil.goToPlaylistNew(activity, new MyTopTracksPlaylist(activity)));
}
return;
}*/
final Playlist playlist = dataSet.get(position);
ArrayList<Song> songs = getSongs(playlist);
holder.itemView.setActivated(isChecked(playlist));
if (holder.title != null) {
holder.title.setText(playlist.name);
}
if (holder.text != null) {
holder.text.setText(String.format(Locale.getDefault(), "%d Songs", songs.size()));
}
if (holder.image != null) {
holder.image.setImageResource(getIconRes(playlist));
}
if (holder.getAdapterPosition() == getItemCount() - 1) {
if (holder.shortSeparator != null) {
holder.shortSeparator.setVisibility(View.GONE);
}
} else {
if (holder.shortSeparator != null && !(dataSet.get(position) instanceof AbsSmartPlaylist)) {
holder.shortSeparator.setVisibility(View.VISIBLE);
}
}
}
private int getIconRes(Playlist playlist) {
if (playlist instanceof AbsSmartPlaylist) {
return ((AbsSmartPlaylist) playlist).iconRes;
}
return MusicUtil.isFavoritePlaylist(activity, playlist) ? R.drawable.ic_favorite_white_24dp
: R.drawable.ic_playlist_play_white_24dp;
}
@Override
public int getItemViewType(int position) {
return dataSet.get(position) instanceof AbsSmartPlaylist ? SMART_PLAYLIST : DEFAULT_PLAYLIST;
}
@Override
public int getItemCount() {
return dataSet.size();
}
@Override
protected Playlist getIdentifier(int position) {
return dataSet.get(position);
}
@Override
protected String getName(Playlist playlist) {
return playlist.name;
}
@Override
protected void onMultipleItemAction(@NonNull MenuItem menuItem,
@NonNull ArrayList<Playlist> selection) {
switch (menuItem.getItemId()) {
case R.id.action_delete_playlist:
for (int i = 0; i < selection.size(); i++) {
Playlist playlist = selection.get(i);
if (playlist instanceof AbsSmartPlaylist) {
AbsSmartPlaylist absSmartPlaylist = (AbsSmartPlaylist) playlist;
ClearSmartPlaylistDialog.create(absSmartPlaylist)
.show(activity.getSupportFragmentManager(),
"CLEAR_PLAYLIST_" + absSmartPlaylist.name);
selection.remove(playlist);
i--;
}
}
if (selection.size() > 0) {
DeletePlaylistDialog.create(selection)
.show(activity.getSupportFragmentManager(), "DELETE_PLAYLIST");
}
break;
default:
SongsMenuHelper.handleMenuClick(activity, getSongList(selection), menuItem.getItemId());
break;
}
}
public ArrayList<Song> getSongs() {
return mSongs;
}
public void setSongs(ArrayList<Song> songs) {
mSongs = songs;
}
@NonNull
private ArrayList<Song> getSongList(@NonNull List<Playlist> playlists) {
final ArrayList<Song> songs = new ArrayList<>();
for (Playlist playlist : playlists) {
if (playlist instanceof AbsCustomPlaylist) {
songs.addAll(((AbsCustomPlaylist) playlist).getSongs(activity).blockingFirst());
//((AbsCustomPlaylist) playlist).getSongs(activity).subscribe(this::setSongs);
} else {
songs
.addAll(PlaylistSongsLoader.getPlaylistSongList(activity, playlist.id).blockingFirst());
}
}
return songs;
}
@Nullable
private ArrayList<Song> getSongs(@NonNull Playlist playlist) {
final ArrayList<Song> songs = new ArrayList<>();
if (playlist instanceof AbsSmartPlaylist) {
songs.addAll(((AbsSmartPlaylist) playlist).getSongs(activity).blockingFirst());
} else {
songs.addAll(PlaylistSongsLoader.getPlaylistSongList(activity, playlist.id).blockingFirst());
}
return songs;
}
private Observable<ArrayList<Bitmap>> loadBitmaps(@NonNull ArrayList<Song> songs) {
return Observable.create(e -> {
ArrayList<Bitmap> bitmaps = new ArrayList<Bitmap>();
for (Song song : songs) {
try {
Bitmap bitmap = Glide.with(activity)
.load(RetroUtil.getAlbumArtUri(song.albumId))
.asBitmap()
.into(500, 500)
.get();
if (bitmap != null) {
Log.i(TAG, "loadBitmaps: has");
bitmaps.add(bitmap);
}
if (bitmaps.size() == 4) {
break;
}
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace();
}
}
e.onNext(bitmaps);
e.onComplete();
});
}
public class ViewHolder extends MediaEntryViewHolder {
public ViewHolder(@NonNull View itemView, int itemViewType) {
super(itemView);
ButterKnife.bind(this, itemView);
if (image != null) {
int iconPadding = activity.getResources()
.getDimensionPixelSize(R.dimen.list_item_image_icon_padding);
image.setPadding(iconPadding, iconPadding, iconPadding, iconPadding);
image.setColorFilter(ATHUtil.resolveColor(activity, R.attr.iconColor),
PorterDuff.Mode.SRC_IN);
}
if (menu != null) {
menu.setOnClickListener(view -> {
final Playlist playlist = dataSet.get(getAdapterPosition());
final PopupMenu popupMenu = new PopupMenu(activity, view);
popupMenu.inflate(getItemViewType() == SMART_PLAYLIST ? R.menu.menu_item_smart_playlist
: R.menu.menu_item_playlist);
if (playlist instanceof LastAddedPlaylist) {
popupMenu.getMenu().findItem(R.id.action_clear_playlist).setVisible(false);
}
popupMenu.setOnMenuItemClickListener(item -> {
if (item.getItemId() == R.id.action_clear_playlist) {
if (playlist instanceof AbsSmartPlaylist) {
ClearSmartPlaylistDialog.create((AbsSmartPlaylist) playlist)
.show(activity.getSupportFragmentManager(),
"CLEAR_SMART_PLAYLIST_" + playlist.name);
return true;
}
}
return PlaylistMenuHelper.handleMenuClick(
activity, dataSet.get(getAdapterPosition()), item);
});
popupMenu.show();
});
}
}
@Override
public void onClick(View view) {
if (isInQuickSelectMode()) {
toggleChecked(getAdapterPosition());
} else {
Playlist playlist = dataSet.get(getAdapterPosition());
NavigationUtil.goToPlaylistNew(activity, playlist);
}
}
@Override
public boolean onLongClick(View view) {
toggleChecked(getAdapterPosition());
return true;
}
}
}

View file

@ -0,0 +1,110 @@
package code.name.monkey.retromusic.ui.adapter.song;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.interfaces.CabHolder;
import code.name.monkey.retromusic.model.Song;
public abstract class AbsOffsetSongAdapter extends SongAdapter {
protected static final int OFFSET_ITEM = 0;
protected static final int SONG = 1;
public AbsOffsetSongAdapter(AppCompatActivity activity, ArrayList<Song> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) {
super(activity, dataSet, itemLayoutRes, usePalette, cabHolder);
}
public AbsOffsetSongAdapter(AppCompatActivity activity, ArrayList<Song> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder, boolean showSectionName) {
super(activity, dataSet, itemLayoutRes, usePalette, cabHolder, showSectionName);
}
@NonNull
@Override
public SongAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == OFFSET_ITEM) {
View view = LayoutInflater.from(activity).inflate(R.layout.item_list_single_row, parent, false);
return createViewHolder(view);
}
return super.onCreateViewHolder(parent, viewType);
}
@Override
protected SongAdapter.ViewHolder createViewHolder(View view) {
return new AbsOffsetSongAdapter.ViewHolder(view);
}
@Override
public long getItemId(int position) {
position--;
if (position < 0) return -2;
return super.getItemId(position);
}
@Nullable
@Override
protected Song getIdentifier(int position) {
position--;
if (position < 0) return null;
return super.getIdentifier(position);
}
@Override
public int getItemCount() {
int superItemCount = super.getItemCount();
return superItemCount == 0 ? 0 : superItemCount + 1;
}
@Override
public int getItemViewType(int position) {
return position == 0 ? OFFSET_ITEM : SONG;
}
@NonNull
@Override
public String getSectionName(int position) {
position--;
if (position < 0) return "";
return super.getSectionName(position);
}
public class ViewHolder extends SongAdapter.ViewHolder {
public ViewHolder(@NonNull View itemView) {
super(itemView);
}
@Override
protected Song getSong() {
if (getItemViewType() == OFFSET_ITEM)
return Song.EMPTY_SONG; // could also return null, just to be safe return empty song
return dataSet.get(getAdapterPosition() - 1);
}
@Override
public void onClick(View v) {
if (isInQuickSelectMode() && getItemViewType() != OFFSET_ITEM) {
toggleChecked(getAdapterPosition());
} else {
MusicPlayerRemote.openQueue(dataSet, getAdapterPosition() - 1, true);
}
}
@Override
public boolean onLongClick(View view) {
if (getItemViewType() == OFFSET_ITEM) return false;
toggleChecked(getAdapterPosition());
return true;
}
}
}

View file

@ -0,0 +1,145 @@
package code.name.monkey.retromusic.ui.adapter.song;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import android.view.View;
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter;
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemViewHolder;
import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange;
import com.h6ah4i.android.widget.advrecyclerview.draggable.annotation.DraggableItemStateFlags;
import code.name.monkey.retromusic.model.PlaylistSong;
import code.name.monkey.retromusic.model.Song;
import java.util.ArrayList;
import java.util.List;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.dialogs.RemoveFromPlaylistDialog;
import code.name.monkey.retromusic.interfaces.CabHolder;
import code.name.monkey.retromusic.util.ViewUtil;
@SuppressWarnings("unchecked")
public class OrderablePlaylistSongAdapter extends PlaylistSongAdapter
implements DraggableItemAdapter<OrderablePlaylistSongAdapter.ViewHolder> {
public static final String TAG = OrderablePlaylistSongAdapter.class.getSimpleName();
private OnMoveItemListener onMoveItemListener;
public OrderablePlaylistSongAdapter(@NonNull AppCompatActivity activity,
@NonNull ArrayList<PlaylistSong> dataSet,
@LayoutRes int itemLayoutRes,
boolean usePalette,
@Nullable CabHolder cabHolder,
@Nullable OnMoveItemListener onMoveItemListener) {
super(activity, (ArrayList<Song>) (List) dataSet, itemLayoutRes, usePalette, cabHolder);
setMultiSelectMenuRes(R.menu.menu_playlists_songs_selection);
this.onMoveItemListener = onMoveItemListener;
}
@Override
protected SongAdapter.ViewHolder createViewHolder(View view) {
return new ViewHolder(view);
}
@Override
public long getItemId(int position) {
position--;
if (position < 0) return -2;
return ((ArrayList<PlaylistSong>) (List) dataSet).get(position).idInPlayList; // important!
}
@Override
protected void onMultipleItemAction(@NonNull MenuItem menuItem, @NonNull ArrayList<Song> selection) {
switch (menuItem.getItemId()) {
case R.id.action_remove_from_playlist:
RemoveFromPlaylistDialog.create((ArrayList<PlaylistSong>) (List) selection).show(activity.getSupportFragmentManager(), "ADD_PLAYLIST");
return;
}
super.onMultipleItemAction(menuItem, selection);
}
@Override
public boolean onCheckCanStartDrag(ViewHolder holder, int position, int x, int y) {
return onMoveItemListener != null && position > 0 &&
(ViewUtil.hitTest(holder.dragView, x, y) || ViewUtil.hitTest(holder.image, x, y));
}
@Override
public ItemDraggableRange onGetItemDraggableRange(ViewHolder holder, int position) {
return new ItemDraggableRange(1, dataSet.size());
}
@Override
public void onMoveItem(int fromPosition, int toPosition) {
if (onMoveItemListener != null && fromPosition != toPosition) {
onMoveItemListener.onMoveItem(fromPosition - 1, toPosition - 1);
}
}
@Override
public boolean onCheckCanDrop(int draggingPosition, int dropPosition) {
return dropPosition > 0;
}
@Override
public void onItemDragStarted(int position) {
notifyDataSetChanged();
}
@Override
public void onItemDragFinished(int fromPosition, int toPosition, boolean result) {
notifyDataSetChanged();
}
public interface OnMoveItemListener {
void onMoveItem(int fromPosition, int toPosition);
}
public class ViewHolder extends PlaylistSongAdapter.ViewHolder implements DraggableItemViewHolder {
@DraggableItemStateFlags
private int mDragStateFlags;
public ViewHolder(@NonNull View itemView) {
super(itemView);
if (dragView != null) {
if (onMoveItemListener != null) {
dragView.setVisibility(View.VISIBLE);
} else {
dragView.setVisibility(View.GONE);
}
}
}
@Override
protected int getSongMenuRes() {
return R.menu.menu_item_playlist_song;
}
@Override
protected boolean onSongMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_remove_from_playlist:
RemoveFromPlaylistDialog.create((PlaylistSong) getSong()).show(activity.getSupportFragmentManager(), "REMOVE_FROM_PLAYLIST");
return true;
}
return super.onSongMenuItemClick(item);
}
@Override
@DraggableItemStateFlags
public int getDragStateFlags() {
return mDragStateFlags;
}
@Override
public void setDragStateFlags(@DraggableItemStateFlags int flags) {
mDragStateFlags = flags;
}
}
}

View file

@ -0,0 +1,209 @@
package code.name.monkey.retromusic.ui.adapter.song;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter;
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemViewHolder;
import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange;
import com.h6ah4i.android.widget.advrecyclerview.draggable.annotation.DraggableItemStateFlags;
import java.util.ArrayList;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.interfaces.CabHolder;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.ViewUtil;
public class PlayingQueueAdapter extends SongAdapter implements
DraggableItemAdapter<PlayingQueueAdapter.ViewHolder> {
private static final int HISTORY = 0;
private static final int CURRENT = 1;
private static final int UP_NEXT = 2;
private int current;
public PlayingQueueAdapter(AppCompatActivity activity, ArrayList<Song> dataSet, int current,
@LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) {
super(activity, dataSet, itemLayoutRes, usePalette, cabHolder);
this.current = current;
}
@Override
protected SongAdapter.ViewHolder createViewHolder(View view) {
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull SongAdapter.ViewHolder holder, int position) {
super.onBindViewHolder(holder, position);
if (holder.imageText != null) {
holder.imageText.setText(String.valueOf(position - current));
}
if (holder.time != null) {
holder.time.setText(MusicUtil.getReadableDurationString(getDataSet().get(position).duration));
}
if (holder.getItemViewType() == HISTORY || holder.getItemViewType() == CURRENT) {
setAlpha(holder, 0.5f);
}
if (usePalette) {
setColor(holder, Color.WHITE);
}
}
private void setColor(SongAdapter.ViewHolder holder, int white) {
if (holder.title != null) {
holder.title.setTextColor(white);
}
if (holder.text != null) {
holder.text.setTextColor(white);
}
if (holder.time != null) {
holder.time.setTextColor(white);
}
if (holder.imageText != null) {
holder.imageText.setTextColor(white);
}
if (holder.menu != null) {
((ImageView) holder.menu).setColorFilter(white, PorterDuff.Mode.SRC_IN);
}
}
@Override
public void usePalette(boolean color) {
super.usePalette(color);
usePalette = color;
notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
if (position < current) {
return HISTORY;
} else if (position > current) {
return UP_NEXT;
}
return CURRENT;
}
@Override
protected void loadAlbumCover(Song song, SongAdapter.ViewHolder holder) {
// We don't want to load it in this adapter
}
public void swapDataSet(ArrayList<Song> dataSet, int position) {
this.dataSet = dataSet;
current = position;
notifyDataSetChanged();
}
public void setCurrent(int current) {
this.current = current;
notifyDataSetChanged();
}
private void setAlpha(SongAdapter.ViewHolder holder, float alpha) {
if (holder.image != null) {
holder.image.setAlpha(alpha);
}
if (holder.title != null) {
holder.title.setAlpha(alpha);
}
if (holder.text != null) {
holder.text.setAlpha(alpha);
}
if (holder.imageText != null) {
holder.imageText.setAlpha(alpha);
}
if (holder.paletteColorContainer != null) {
holder.paletteColorContainer.setAlpha(alpha);
}
}
@Override
public boolean onCheckCanStartDrag(ViewHolder holder, int position, int x, int y) {
return ViewUtil.hitTest(holder.imageText, x, y) || (ViewUtil.hitTest(holder.dragView, x, y));
}
@Override
public ItemDraggableRange onGetItemDraggableRange(ViewHolder holder, int position) {
return null;
}
@Override
public void onMoveItem(int fromPosition, int toPosition) {
MusicPlayerRemote.moveSong(fromPosition, toPosition);
}
@Override
public boolean onCheckCanDrop(int draggingPosition, int dropPosition) {
return true;
}
@Override
public void onItemDragStarted(int position) {
notifyDataSetChanged();
}
@Override
public void onItemDragFinished(int fromPosition, int toPosition, boolean result) {
notifyDataSetChanged();
}
public class ViewHolder extends SongAdapter.ViewHolder implements DraggableItemViewHolder {
@DraggableItemStateFlags
private int mDragStateFlags;
public ViewHolder(@NonNull View itemView) {
super(itemView);
if (imageText != null) {
imageText.setVisibility(View.VISIBLE);
}
if (image != null) {
image.setVisibility(View.GONE);
}
if (dragView != null) {
dragView.setVisibility(View.VISIBLE);
}
}
@Override
protected int getSongMenuRes() {
return R.menu.menu_item_playing_queue_song;
}
@Override
protected boolean onSongMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_remove_from_playing_queue:
MusicPlayerRemote.removeFromQueue(getAdapterPosition());
return true;
}
return super.onSongMenuItemClick(item);
}
@Override
@DraggableItemStateFlags
public int getDragStateFlags() {
return mDragStateFlags;
}
@Override
public void setDragStateFlags(@DraggableItemStateFlags int flags) {
mDragStateFlags = flags;
}
}
}

View file

@ -0,0 +1,93 @@
package code.name.monkey.retromusic.ui.adapter.song;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.util.Pair;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import android.view.View;
import java.util.ArrayList;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.interfaces.CabHolder;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.NavigationUtil;
public class PlaylistSongAdapter extends AbsOffsetSongAdapter {
public static final String TAG = PlaylistSongAdapter.class.getSimpleName();
public PlaylistSongAdapter(AppCompatActivity activity, @NonNull ArrayList<Song> dataSet, @LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) {
super(activity, dataSet, itemLayoutRes, usePalette, cabHolder, false);
setMultiSelectMenuRes(R.menu.menu_cannot_delete_single_songs_playlist_songs_selection);
}
@Override
protected SongAdapter.ViewHolder createViewHolder(View view) {
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final SongAdapter.ViewHolder holder, int position) {
if (holder.getItemViewType() == OFFSET_ITEM) {
int textColor = ThemeStore.textColorSecondary(activity);
if (holder.title != null) {
holder.title.setText(MusicUtil.getPlaylistInfoString(activity, dataSet));
holder.title.setTextColor(textColor);
}
if (holder.text != null) {
holder.text.setVisibility(View.GONE);
}
if (holder.menu != null) {
holder.menu.setVisibility(View.GONE);
}
if (holder.image != null) {
final int padding = activity.getResources().getDimensionPixelSize(R.dimen.default_item_margin) / 2;
holder.image.setPadding(padding, padding, padding, padding);
holder.image.setColorFilter(textColor);
holder.image.setImageResource(R.drawable.ic_timer_white_24dp);
}
if (holder.dragView != null) {
holder.dragView.setVisibility(View.GONE);
}
if (holder.separator != null) {
holder.separator.setVisibility(View.VISIBLE);
}
if (holder.shortSeparator != null) {
holder.shortSeparator.setVisibility(View.GONE);
}
} else {
super.onBindViewHolder(holder, position - 1);
}
}
public class ViewHolder extends AbsOffsetSongAdapter.ViewHolder {
public ViewHolder(@NonNull View itemView) {
super(itemView);
}
@Override
protected int getSongMenuRes() {
return R.menu.menu_item_cannot_delete_single_songs_playlist_song;
}
@Override
protected boolean onSongMenuItemClick(MenuItem item) {
if (item.getItemId() == R.id.action_go_to_album) {
Pair[] albumPairs = new Pair[]{
Pair.create(image, activity.getString(R.string.transition_album_art))};
NavigationUtil.goToAlbum(activity, dataSet.get(getAdapterPosition() - 1).albumId, albumPairs);
return true;
}
return super.onSongMenuItemClick(item);
}
}
}

View file

@ -0,0 +1,78 @@
package code.name.monkey.retromusic.ui.adapter.song;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.interfaces.CabHolder;
import code.name.monkey.retromusic.model.Song;
import java.util.ArrayList;
public class ShuffleButtonSongAdapter extends AbsOffsetSongAdapter {
public ShuffleButtonSongAdapter(AppCompatActivity activity, ArrayList<Song> dataSet,
@LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) {
super(activity, dataSet, itemLayoutRes, usePalette, cabHolder);
}
@Override
protected SongAdapter.ViewHolder createViewHolder(View view) {
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final SongAdapter.ViewHolder holder, int position) {
if (holder.getItemViewType() == OFFSET_ITEM) {
int accentColor = ThemeStore.accentColor(activity);
if (holder.title != null) {
holder.title.setText(activity.getResources().getString(R.string.action_shuffle_all));
holder.title.setTextColor(accentColor);
/*((GradientTextView) holder.title).setLinearGradient(ThemeStore.accentColor(activity),
PhonographColorUtil.getMatColor(activity, "A400"), GradientTextView.LG_VERTICAL);
*/
}
if (holder.text != null) {
holder.text.setVisibility(View.GONE);
}
if (holder.menu != null) {
holder.menu.setVisibility(View.GONE);
}
if (holder.image != null) {
final int padding =
activity.getResources().getDimensionPixelSize(R.dimen.default_item_margin) / 2;
holder.image.setPadding(padding, padding, padding, padding);
holder.image.setColorFilter(accentColor);
holder.image.setImageResource(R.drawable.ic_shuffle_white_24dp);
}
if (holder.separator != null) {
holder.separator.setVisibility(View.VISIBLE);
}
if (holder.shortSeparator != null) {
holder.shortSeparator.setVisibility(View.GONE);
}
} else {
super.onBindViewHolder(holder, position - 1);
}
}
public class ViewHolder extends AbsOffsetSongAdapter.ViewHolder {
public ViewHolder(@NonNull View itemView) {
super(itemView);
}
@Override
public void onClick(View v) {
if (getItemViewType() == OFFSET_ITEM) {
MusicPlayerRemote.openAndShuffleQueue(dataSet, true);
return;
}
super.onClick(v);
}
}
}

View file

@ -0,0 +1,69 @@
package code.name.monkey.retromusic.ui.adapter.song;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import java.util.ArrayList;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.util.MusicUtil;
/**
* Created by Monkey D Luffy on 3/31/2016.
*/
public class SimpleSongAdapter extends SongAdapter {
private int textColor;
public SimpleSongAdapter(AppCompatActivity context, ArrayList<Song> songs, @LayoutRes int i) {
super(context, songs, i, false, null);
textColor = ThemeStore.textColorPrimary(context);
}
public void swapDataSet(ArrayList<Song> arrayList) {
this.dataSet.clear();
this.dataSet = arrayList;
notifyDataSetChanged();
}
@NonNull
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false));
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
super.onBindViewHolder(holder, position);
int fixedTrackNumber = MusicUtil.getFixedTrackNumber(dataSet.get(position).trackNumber);
if (holder.imageText != null) {
holder.imageText.setText(fixedTrackNumber > 0 ? String.valueOf(fixedTrackNumber) : "-");
holder.imageText.setTextColor(textColor);
}
if (holder.time != null) {
holder.time.setText(MusicUtil.getReadableDurationString(dataSet.get(position).duration));
holder.time.setTextColor(textColor);
}
if (holder.title != null) {
holder.title.setTextColor(textColor);
}
if (holder.menu != null) {
TintHelper.setTintAuto(holder.menu, textColor, false);
}
}
public int getItemCount() {
return dataSet.size();
}
public void setTextColor(int textColor) {
this.textColor = textColor;
notifyDataSetChanged();
}
}

View file

@ -0,0 +1,294 @@
package code.name.monkey.retromusic.ui.adapter.song;
import android.graphics.drawable.Drawable;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.util.Pair;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import com.afollestad.materialcab.MaterialCab;
import com.bumptech.glide.Glide;
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView;
import java.util.ArrayList;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget;
import code.name.monkey.retromusic.glide.SongGlideRequest;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.SortOrder;
import code.name.monkey.retromusic.helper.menu.SongMenuHelper;
import code.name.monkey.retromusic.helper.menu.SongsMenuHelper;
import code.name.monkey.retromusic.interfaces.CabHolder;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.ui.adapter.base.AbsMultiSelectAdapter;
import code.name.monkey.retromusic.ui.adapter.base.MediaEntryViewHolder;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.NavigationUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
/**
* Created by hemanths on 13/08/17.
*/
public class SongAdapter extends AbsMultiSelectAdapter<SongAdapter.ViewHolder, Song>
implements MaterialCab.Callback, FastScrollRecyclerView.SectionedAdapter {
public static final String TAG = SongAdapter.class.getSimpleName();
protected final AppCompatActivity activity;
protected ArrayList<Song> dataSet;
protected int itemLayoutRes;
protected boolean usePalette = false;
private boolean showSectionName = true;
public SongAdapter(AppCompatActivity activity, ArrayList<Song> dataSet,
@LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder) {
this(activity, dataSet, itemLayoutRes, usePalette, cabHolder, true);
}
public SongAdapter(AppCompatActivity activity, ArrayList<Song> dataSet,
@LayoutRes int itemLayoutRes, boolean usePalette, @Nullable CabHolder cabHolder,
boolean showSectionName) {
super(activity, cabHolder, R.menu.menu_media_selection);
this.activity = activity;
this.dataSet = dataSet;
this.itemLayoutRes = itemLayoutRes;
this.usePalette = usePalette;
this.showSectionName = showSectionName;
setHasStableIds(true);
}
public void swapDataSet(ArrayList<Song> dataSet) {
this.dataSet = dataSet;
notifyDataSetChanged();
}
public void usePalette(boolean usePalette) {
this.usePalette = usePalette;
notifyDataSetChanged();
}
public ArrayList<Song> getDataSet() {
return dataSet;
}
@Override
public long getItemId(int position) {
return dataSet.get(position).id;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(activity).inflate(itemLayoutRes, parent, false);
return createViewHolder(view);
}
protected ViewHolder createViewHolder(View view) {
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
final Song song = dataSet.get(position);
boolean isChecked = isChecked(song);
holder.itemView.setActivated(isChecked);
if (holder.getAdapterPosition() == getItemCount() - 1) {
if (holder.shortSeparator != null) {
holder.shortSeparator.setVisibility(View.GONE);
}
} else {
if (holder.shortSeparator != null) {
holder.shortSeparator.setVisibility(View.VISIBLE);
}
}
if (holder.title != null) {
holder.title.setText(getSongTitle(song));
}
if (holder.text != null) {
holder.text.setText(getSongText(song));
}
loadAlbumCover(song, holder);
}
private void setColors(int color, ViewHolder holder) {
if (holder.paletteColorContainer != null) {
holder.paletteColorContainer.setBackgroundColor(color);
if (holder.title != null) {
holder.title.setTextColor(
MaterialValueHelper.getPrimaryTextColor(activity, ColorUtil.isColorLight(color)));
}
if (holder.text != null) {
holder.text.setTextColor(
MaterialValueHelper.getSecondaryTextColor(activity, ColorUtil.isColorLight(color)));
}
}
}
protected void loadAlbumCover(Song song, final ViewHolder holder) {
if (holder.image == null) {
return;
}
SongGlideRequest.Builder.from(Glide.with(activity), song)
.checkIgnoreMediaStore(activity)
.generatePalette(activity).build()
.into(new RetroMusicColoredTarget(holder.image) {
@Override
public void onLoadCleared(Drawable placeholder) {
super.onLoadCleared(placeholder);
setColors(getDefaultFooterColor(), holder);
}
@Override
public void onColorReady(int color) {
setColors(color, holder);
}
});
}
private String getSongTitle(Song song) {
return song.title;
}
private String getSongText(Song song) {
return song.artistName;
}
@Override
public int getItemCount() {
return dataSet.size();
}
@Override
protected Song getIdentifier(int position) {
return dataSet.get(position);
}
@Override
protected String getName(Song song) {
return song.title;
}
@Override
protected void onMultipleItemAction(@NonNull MenuItem menuItem,
@NonNull ArrayList<Song> selection) {
SongsMenuHelper.handleMenuClick(activity, selection, menuItem.getItemId());
}
@NonNull
@Override
public String getSectionName(int position) {
if (!showSectionName) {
return "";
}
@Nullable String sectionName = null;
switch (PreferenceUtil.getInstance(activity).getSongSortOrder()) {
case SortOrder.SongSortOrder.SONG_A_Z:
case SortOrder.SongSortOrder.SONG_Z_A:
sectionName = dataSet.get(position).title;
break;
case SortOrder.SongSortOrder.SONG_ALBUM:
sectionName = dataSet.get(position).albumName;
break;
case SortOrder.SongSortOrder.SONG_ARTIST:
sectionName = dataSet.get(position).artistName;
break;
case SortOrder.SongSortOrder.SONG_YEAR:
return MusicUtil.getYearString(dataSet.get(position).year);
}
return MusicUtil.getSectionName(sectionName);
}
public class ViewHolder extends MediaEntryViewHolder {
int DEFAULT_MENU_RES = SongMenuHelper.MENU_RES;
public ViewHolder(@NonNull View itemView) {
super(itemView);
setImageTransitionName(activity.getString(R.string.transition_album_art));
/*if (mItemView != null) {
mItemView.setOnMenuItemClickListener(new ListItemView.OnMenuItemClickListener() {
@Override
public void onActionMenuItemSelected(MenuItem item) {
SongMenuHelper.handleMenuClick(activity, dataSet.get(getAdapterPosition()), item.getItemId());
}
});
}*/
if (menu == null) {
return;
}
menu.setOnClickListener(new SongMenuHelper.OnClickSongMenu(activity) {
@Override
public Song getSong() {
return ViewHolder.this.getSong();
}
@Override
public int getMenuRes() {
return getSongMenuRes();
}
@Override
public boolean onMenuItemClick(MenuItem item) {
return onSongMenuItemClick(item) || super.onMenuItemClick(item);
}
});
}
protected Song getSong() {
return dataSet.get(getAdapterPosition());
}
protected int getSongMenuRes() {
return DEFAULT_MENU_RES;
}
protected boolean onSongMenuItemClick(MenuItem item) {
if (image != null && image.getVisibility() == View.VISIBLE) {
switch (item.getItemId()) {
case R.id.action_go_to_album:
Pair[] albumPairs = new Pair[]{
Pair.create(imageContainer,
activity.getResources().getString(R.string.transition_album_art))
};
NavigationUtil.goToAlbum(activity, getSong().albumId, albumPairs);
return true;
}
}
return false;
}
@Override
public void onClick(View v) {
if (isInQuickSelectMode()) {
toggleChecked(getAdapterPosition());
} else {
MusicPlayerRemote.openQueue(dataSet, getAdapterPosition(), true);
}
}
@Override
public boolean onLongClick(View view) {
return toggleChecked(getAdapterPosition());
}
}
}

View file

@ -0,0 +1,176 @@
package code.name.monkey.retromusic.ui.fragments;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper;
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler;
import code.name.monkey.retromusic.ui.fragments.base.AbsMusicServiceFragment;
import code.name.monkey.retromusic.views.PlayPauseDrawable;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
public class MiniPlayerFragment extends AbsMusicServiceFragment implements
MusicProgressViewUpdateHelper.Callback {
@BindView(R.id.mini_player_title)
TextView miniPlayerTitle;
@BindView(R.id.mini_player_play_pause_button)
ImageView miniPlayerPlayPauseButton;
@BindView(R.id.progress_bar)
MaterialProgressBar progressBar;
private Unbinder unbinder;
private PlayPauseDrawable miniPlayerPlayPauseDrawable;
private MusicProgressViewUpdateHelper progressViewUpdateHelper;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressViewUpdateHelper = new MusicProgressViewUpdateHelper(this);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.fragment_mini_player, container, false);
unbinder = ButterKnife.bind(this, layout);
return layout;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.setBackgroundColor(ThemeStore.primaryColor(getContext()));
view.setOnTouchListener(new FlingPlayBackController(getActivity()));
setUpMiniPlayer();
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@SuppressWarnings({"ConstantConditions"})
private void setUpMiniPlayer() {
setUpPlayPauseButton();
progressBar.setProgressTintList(ColorStateList.valueOf(ThemeStore.accentColor(getActivity())));
}
private void setUpPlayPauseButton() {
//noinspection ConstantConditions
miniPlayerPlayPauseDrawable = new PlayPauseDrawable(getActivity());
miniPlayerPlayPauseButton.setImageDrawable(miniPlayerPlayPauseDrawable);
miniPlayerPlayPauseButton.setColorFilter(ATHUtil.resolveColor(getActivity(),
R.attr.iconColor,
ThemeStore.textColorSecondary(getActivity())), PorterDuff.Mode.SRC_IN);
miniPlayerPlayPauseButton.setOnClickListener(new PlayPauseButtonOnClickHandler());
}
private void updateSongTitle() {
miniPlayerTitle.setText(MusicPlayerRemote.getCurrentSong().title);
}
@Override
public void onServiceConnected() {
updateSongTitle();
updatePlayPauseDrawableState(false);
}
@Override
public void onPlayingMetaChanged() {
updateSongTitle();
}
@Override
public void onPlayStateChanged() {
updatePlayPauseDrawableState(true);
}
@Override
public void onUpdateProgressViews(int progress, int total) {
progressBar.setMax(total);
ObjectAnimator animator = ObjectAnimator.ofInt(progressBar, "progress", progress);
animator.setDuration(1000);
animator.setInterpolator(new DecelerateInterpolator());
animator.start();
}
@Override
public void onResume() {
super.onResume();
progressViewUpdateHelper.start();
}
@Override
public void onPause() {
super.onPause();
progressViewUpdateHelper.stop();
}
protected void updatePlayPauseDrawableState(boolean animate) {
if (MusicPlayerRemote.isPlaying()) {
miniPlayerPlayPauseDrawable.setPause(animate);
} else {
miniPlayerPlayPauseDrawable.setPlay(animate);
}
}
public void setColor(int playerFragmentColor) {
//noinspection ConstantConditions
getView().setBackgroundColor(playerFragmentColor);
}
public static class FlingPlayBackController implements View.OnTouchListener {
GestureDetector flingPlayBackController;
public FlingPlayBackController(Context context) {
flingPlayBackController = new GestureDetector(context,
new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
if (Math.abs(velocityX) > Math.abs(velocityY)) {
if (velocityX < 0) {
MusicPlayerRemote.playNextSong();
return true;
} else if (velocityX > 0) {
MusicPlayerRemote.playPreviousSong();
return true;
}
}
return false;
}
});
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
return flingPlayBackController.onTouchEvent(event);
}
}
}

View file

@ -0,0 +1,34 @@
package code.name.monkey.retromusic.ui.fragments;
import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
import code.name.monkey.retromusic.R;
public enum NowPlayingScreen {
NORMAL(R.string.normal, R.drawable.np_normal, 0),
FLAT(R.string.flat, R.drawable.np_flat, 1),
FULL(R.string.full, R.drawable.np_full, 2),
PLAIN(R.string.plain, R.drawable.np_plain, 3),
BLUR(R.string.blur, R.drawable.np_blur, 4),
COLOR(R.string.color, R.drawable.np_color, 5),
CARD(R.string.card, R.drawable.np_card, 6),
TINY(R.string.tiny, R.drawable.np_tiny, 7),
SIMPLE(R.string.simple, R.drawable.np_simple, 8),
BLUR_CARD(R.string.blur_card, R.drawable.np_blur_card, 9),
ADAPTIVE(R.string.adaptive, R.drawable.np_adaptive, 10),
MATERIAL(R.string.material, R.drawable.np_normal, 11);
@StringRes
public final int titleRes;
@DrawableRes
public final int drawableResId;
public final int id;
NowPlayingScreen(@StringRes int titleRes, @DrawableRes int drawableResId, int id) {
this.titleRes = titleRes;
this.drawableResId = drawableResId;
this.id = id;
}
}

View file

@ -0,0 +1,143 @@
package code.name.monkey.retromusic.ui.fragments;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.ui.adapter.song.PlayingQueueAdapter;
import code.name.monkey.retromusic.ui.fragments.base.AbsMusicServiceFragment;
import com.h6ah4i.android.widget.advrecyclerview.animator.GeneralItemAnimator;
import com.h6ah4i.android.widget.advrecyclerview.animator.RefactoredDefaultItemAnimator;
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager;
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils;
public class PlayingQueueFragment extends AbsMusicServiceFragment {
@BindView(R.id.recycler_view)
RecyclerView mRecyclerView;
Unbinder unbinder;
private RecyclerView.Adapter mWrappedAdapter;
private RecyclerViewDragDropManager mRecyclerViewDragDropManager;
private PlayingQueueAdapter mPlayingQueueAdapter;
private LinearLayoutManager mLayoutManager;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main_activity_recycler_view, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setUpRecyclerView();
}
private void setUpRecyclerView() {
mRecyclerViewDragDropManager = new RecyclerViewDragDropManager();
final GeneralItemAnimator animator = new RefactoredDefaultItemAnimator();
mPlayingQueueAdapter = new PlayingQueueAdapter(
(AppCompatActivity) getActivity(),
MusicPlayerRemote.getPlayingQueue(),
MusicPlayerRemote.getPosition(),
R.layout.item_list,
false,
null);
mWrappedAdapter = mRecyclerViewDragDropManager.createWrappedAdapter(mPlayingQueueAdapter);
mLayoutManager = new LinearLayoutManager(getContext());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mWrappedAdapter);
mRecyclerView.setItemAnimator(animator);
mRecyclerViewDragDropManager.attachRecyclerView(mRecyclerView);
mLayoutManager.scrollToPositionWithOffset(MusicPlayerRemote.getPosition() + 1, 0);
}
@Override
public void onQueueChanged() {
updateQueue();
updateCurrentSong();
}
@Override
public void onMediaStoreChanged() {
updateQueue();
updateCurrentSong();
}
@SuppressWarnings("ConstantConditions")
private void updateCurrentSong() {
}
@Override
public void onPlayingMetaChanged() {
//updateCurrentSong();
//updateIsFavorite();
updateQueuePosition();
//updateLyrics();
}
private void updateQueuePosition() {
mPlayingQueueAdapter.setCurrent(MusicPlayerRemote.getPosition());
// if (slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) {
resetToCurrentPosition();
//}
}
private void updateQueue() {
mPlayingQueueAdapter
.swapDataSet(MusicPlayerRemote.getPlayingQueue(), MusicPlayerRemote.getPosition());
resetToCurrentPosition();
}
private void resetToCurrentPosition() {
mRecyclerView.stopScroll();
mLayoutManager.scrollToPositionWithOffset(MusicPlayerRemote.getPosition() + 1, 0);
}
@Override
public void onPause() {
if (mRecyclerViewDragDropManager != null) {
mRecyclerViewDragDropManager.cancelDrag();
}
super.onPause();
}
@Override
public void onDestroyView() {
if (mRecyclerViewDragDropManager != null) {
mRecyclerViewDragDropManager.release();
mRecyclerViewDragDropManager = null;
}
if (mRecyclerView != null) {
mRecyclerView.setItemAnimator(null);
mRecyclerView.setAdapter(null);
mRecyclerView = null;
}
if (mWrappedAdapter != null) {
WrapperAdapterUtils.releaseAll(mWrappedAdapter);
mWrappedAdapter = null;
}
mPlayingQueueAdapter = null;
mLayoutManager = null;
super.onDestroyView();
unbinder.unbind();
}
}

View file

@ -0,0 +1,158 @@
package code.name.monkey.retromusic.ui.fragments;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.media.AudioManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.SeekBar;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.volume.AudioVolumeObserver;
import code.name.monkey.retromusic.volume.OnAudioVolumeChangedListener;
public class VolumeFragment extends Fragment implements SeekBar.OnSeekBarChangeListener,
OnAudioVolumeChangedListener {
@BindView(R.id.volume_seekbar)
SeekBar volumeSeekbar;
@BindView(R.id.volume_down)
ImageView volumeDown;
@BindView(R.id.container)
ViewGroup viewGroup;
@BindView(R.id.volume_up)
ImageView volumeUp;
private Unbinder unbinder;
private AudioVolumeObserver mAudioVolumeObserver;
public static VolumeFragment newInstance() {
return new VolumeFragment();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_volume, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//noinspection ConstantConditions
setColor(ThemeStore.textColorSecondary(getContext()));
}
@Override
public void onResume() {
super.onResume();
if (mAudioVolumeObserver == null) {
//noinspection ConstantConditions
mAudioVolumeObserver = new AudioVolumeObserver(getActivity());
}
mAudioVolumeObserver.register(AudioManager.STREAM_MUSIC, this);
AudioManager audioManager = getAudioManager();
if (audioManager != null) {
volumeSeekbar.setMax(audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
volumeSeekbar.setProgress(audioManager.getStreamVolume(AudioManager.STREAM_MUSIC));
}
volumeSeekbar.setOnSeekBarChangeListener(this);
}
@Override
public void onAudioVolumeChanged(int currentVolume, int maxVolume) {
if (volumeSeekbar == null) {
return;
}
volumeSeekbar.setMax(maxVolume);
volumeSeekbar.setProgress(currentVolume);
volumeDown.setImageResource(currentVolume == 0 ? R.drawable.ic_volume_off_white_24dp : R.drawable.ic_volume_down_white_24dp);
}
private AudioManager getAudioManager() {
//noinspection ConstantConditions
return (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
if (mAudioVolumeObserver != null) {
mAudioVolumeObserver.unregister();
}
}
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
AudioManager audioManager = getAudioManager();
if (audioManager != null) {
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, i, 0);
}
volumeDown.setImageResource(
i == 0 ? R.drawable.ic_volume_off_white_24dp : R.drawable.ic_volume_down_white_24dp);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
@OnClick({R.id.volume_down, R.id.volume_up})
public void onViewClicked(View view) {
AudioManager audioManager = getAudioManager();
switch (view.getId()) {
case R.id.volume_down:
if (audioManager != null) {
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, 0);
}
break;
case R.id.volume_up:
if (audioManager != null) {
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, 0);
}
break;
}
}
public void setColor(int color) {
volumeSeekbar.setProgressTintList(ColorStateList.valueOf(color));
}
public void tintWhiteColor() {
setProgressBarColor(Color.WHITE);
}
public void setProgressBarColor(int newColor) {
TintHelper.setTintAuto(volumeSeekbar, newColor, false);
volumeDown.setColorFilter(newColor, PorterDuff.Mode.SRC_IN);
volumeUp.setColorFilter(newColor, PorterDuff.Mode.SRC_IN);
}
public void setTintable(int color) {
setProgressBarColor(color);
}
}

View file

@ -0,0 +1,20 @@
package code.name.monkey.retromusic.ui.fragments.base;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import code.name.monkey.retromusic.ui.fragments.mainactivity.LibraryFragment;
public class AbsLibraryPagerFragment extends AbsMusicServiceFragment {
public LibraryFragment getLibraryFragment() {
return (LibraryFragment) getParentFragment();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
}
}

View file

@ -0,0 +1,169 @@
package code.name.monkey.retromusic.ui.fragments.base;
import android.os.Bundle;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.util.RetroUtil;
public abstract class AbsLibraryPagerRecyclerViewCustomGridSizeFragment<A extends RecyclerView.Adapter, LM extends RecyclerView.LayoutManager> extends
AbsLibraryPagerRecyclerViewFragment<A, LM> {
private int gridSize;
private String sortOrder;
private boolean usePaletteInitialized;
private boolean usePalette;
private int currentLayoutRes;
public final int getGridSize() {
if (gridSize == 0) {
if (isLandscape()) {
gridSize = loadGridSizeLand();
} else {
gridSize = loadGridSize();
}
}
return gridSize;
}
protected abstract void setGridSize(int gridSize);
public final String getSortOrder() {
if (sortOrder == null) {
sortOrder = loadSortOrder();
}
return sortOrder;
}
protected abstract void setSortOrder(String sortOrder);
public void setAndSaveSortOrder(final String sortOrder) {
this.sortOrder = sortOrder;
saveSortOrder(sortOrder);
setSortOrder(sortOrder);
}
public int getMaxGridSize() {
if (isLandscape()) {
return getResources().getInteger(R.integer.max_columns_land);
} else {
return getResources().getInteger(R.integer.max_columns);
}
}
/**
* @return whether the palette should be used at all or not
*/
public final boolean usePalette() {
if (!usePaletteInitialized) {
usePalette = loadUsePalette();
usePaletteInitialized = true;
}
return usePalette;
}
public void setAndSaveGridSize(final int gridSize) {
int oldLayoutRes = getItemLayoutRes();
this.gridSize = gridSize;
if (isLandscape()) {
saveGridSizeLand(gridSize);
} else {
saveGridSize(gridSize);
}
// only recreate the adapter and layout manager if the layout currentLayoutRes has changed
if (oldLayoutRes != getItemLayoutRes()) {
invalidateLayoutManager();
invalidateAdapter();
} else {
setGridSize(gridSize);
}
}
public void setAndSaveUsePalette(final boolean usePalette) {
this.usePalette = usePalette;
saveUsePalette(usePalette);
setUsePalette(usePalette);
}
/**
* @return whether the palette option should be available for the current item layout or not
*/
public boolean canUsePalette() {
return getItemLayoutRes() == R.layout.item_color;
}
/**
* Override to customize which item layout currentLayoutRes should be used. You might also want to
* override {@link #canUsePalette()} then.
*
* @see #getGridSize()
*/
@LayoutRes
protected int getItemLayoutRes() {
if (getGridSize() > getMaxGridSizeForList()) {
return R.layout.item_grid;
}
return R.layout.item_list;
}
protected final void notifyLayoutResChanged(@LayoutRes int res) {
this.currentLayoutRes = res;
RecyclerView recyclerView = getRecyclerView();
if (recyclerView != null) {
applyRecyclerViewPaddingForLayoutRes(recyclerView, currentLayoutRes);
}
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
applyRecyclerViewPaddingForLayoutRes(getRecyclerView(), currentLayoutRes);
}
protected void applyRecyclerViewPaddingForLayoutRes(@NonNull RecyclerView recyclerView,
@LayoutRes int res) {
int padding;
if (res == R.layout.item_grid) {
padding = (int) (getResources().getDisplayMetrics().density * 2);
} else {
padding = 0;
}
recyclerView.setPadding(padding, padding, padding, padding);
}
protected abstract String loadSortOrder();
protected abstract void saveSortOrder(String sortOrder);
protected abstract int loadGridSize();
protected abstract void saveGridSize(int gridColumns);
protected abstract int loadGridSizeLand();
protected abstract void saveGridSizeLand(int gridColumns);
protected abstract void saveUsePalette(boolean usePalette);
protected abstract boolean loadUsePalette();
protected abstract void setUsePalette(boolean usePalette);
protected int getMaxGridSizeForList() {
if (isLandscape()) {
return getActivity().getResources().getInteger(R.integer.default_list_columns_land);
}
return getActivity().getResources().getInteger(R.integer.default_list_columns);
}
protected final boolean isLandscape() {
return RetroUtil.isLandscape(getResources());
}
}

View file

@ -0,0 +1,162 @@
package code.name.monkey.retromusic.ui.fragments.base;
import android.os.Bundle;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.AppBarLayout.OnOffsetChangedListener;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.util.ViewUtil;
public abstract class AbsLibraryPagerRecyclerViewFragment<A extends RecyclerView.Adapter, LM extends RecyclerView.LayoutManager> extends
AbsLibraryPagerFragment implements OnOffsetChangedListener {
public static final String TAG = AbsLibraryPagerRecyclerViewFragment.class.getSimpleName();
@BindView(R.id.container)
ViewGroup container;
@BindView(R.id.recycler_view)
RecyclerView recyclerView;
@BindView(android.R.id.empty)
TextView empty;
private Unbinder unbinder;
private A adapter;
private LM layoutManager;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(getLayoutRes(), container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getLibraryFragment().addOnAppBarOffsetChangedListener(this);
initLayoutManager();
initAdapter();
setUpRecyclerView();
}
private void setUpRecyclerView() {
if (recyclerView instanceof FastScrollRecyclerView) {
//noinspection ConstantConditions
ViewUtil.setUpFastScrollRecyclerViewColor(getActivity(),
((FastScrollRecyclerView) recyclerView), ThemeStore.accentColor(getActivity()));
}
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
}
@Override
public void onQueueChanged() {
super.onQueueChanged();
checkForPadding();
}
@Override
public void onServiceConnected() {
super.onServiceConnected();
checkForPadding();
}
private void checkForPadding() {
int height = (MusicPlayerRemote.getPlayingQueue().isEmpty() ? getResources().getDimensionPixelSize(R.dimen.mini_player_height) : 0);
recyclerView.setPadding(0, 0, 0, height);
}
protected void invalidateLayoutManager() {
initLayoutManager();
recyclerView.setLayoutManager(layoutManager);
}
protected void invalidateAdapter() {
initAdapter();
checkIsEmpty();
recyclerView.setAdapter(adapter);
}
private void initAdapter() {
adapter = createAdapter();
adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
super.onChanged();
checkIsEmpty();
checkForPadding();
}
});
}
private void initLayoutManager() {
layoutManager = createLayoutManager();
}
protected A getAdapter() {
return adapter;
}
protected LM getLayoutManager() {
return layoutManager;
}
protected RecyclerView getRecyclerView() {
return recyclerView;
}
public ViewGroup getContainer() {
return container;
}
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int i) {
container.setPadding(container.getPaddingLeft(), container.getPaddingTop(),
container.getPaddingRight(), getLibraryFragment().getTotalAppBarScrollingRange() + i);
}
private void checkIsEmpty() {
empty.setText(getEmptyMessage());
empty.setVisibility(adapter == null || adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
}
@StringRes
protected int getEmptyMessage() {
return R.string.empty;
}
@LayoutRes
protected int getLayoutRes() {
return R.layout.fragment_main_activity_recycler_view;
}
protected abstract LM createLayoutManager();
@NonNull
protected abstract A createAdapter();
@Override
public void onDestroyView() {
super.onDestroyView();
getLibraryFragment().removeOnAppBarOffsetChangedListener(this);
unbinder.unbind();
}
}

View file

@ -0,0 +1,52 @@
package code.name.monkey.retromusic.ui.fragments.base;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.ui.activities.MainActivity;
import code.name.monkey.retromusic.util.RetroUtil;
public abstract class AbsMainActivityFragment extends AbsMusicServiceFragment {
public MainActivity getMainActivity() {
return (MainActivity) getActivity();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
getMainActivity().setNavigationbarColorAuto();
getMainActivity().setLightNavigationBar(true);
getMainActivity().setTaskDescriptionColorAuto();
getMainActivity().hideStatusBar();
}
// WORKAROUND
public void setStatusbarColor(View view, int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
final View statusBar = view.findViewById(R.id.status_bar);
if (statusBar != null) {
RetroUtil.statusBarHeight(statusBar);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
statusBar.setBackgroundColor(ColorUtil.darkenColor(color));
getMainActivity().setLightStatusbarAuto(color);
} else {
statusBar.setBackgroundColor(color);
}
}
}
}
public void setStatusbarColorAuto(View view) {
// we don't want to use statusbar color because we are doing the color darkening on our own to support KitKat
setStatusbarColor(view, ThemeStore.primaryColor(getContext()));
}
}

View file

@ -0,0 +1,89 @@
package code.name.monkey.retromusic.ui.fragments.base;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.view.View;
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener;
import code.name.monkey.retromusic.ui.activities.base.AbsMusicServiceActivity;
/**
* Created by hemanths on 18/08/17.
*/
public class AbsMusicServiceFragment extends Fragment implements MusicServiceEventListener {
private AbsMusicServiceActivity activity;
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
activity = (AbsMusicServiceActivity) context;
} catch (ClassCastException e) {
throw new RuntimeException(context.getClass().getSimpleName() + " must be an instance of " + AbsMusicServiceActivity.class.getSimpleName());
}
}
@Override
public void onDetach() {
super.onDetach();
activity = null;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
activity.addMusicServiceEventListener(this);
}
@Override
public void onDestroyView() {
super.onDestroyView();
activity.removeMusicServiceEventListener(this);
}
@Override
public void onPlayingMetaChanged() {
}
@Override
public void onServiceConnected() {
}
@Override
public void onServiceDisconnected() {
}
@Override
public void onQueueChanged() {
}
@Override
public void onPlayStateChanged() {
}
@Override
public void onRepeatModeChanged() {
}
@Override
public void onShuffleModeChanged() {
}
@Override
public void onMediaStoreChanged() {
}
}

View file

@ -0,0 +1,23 @@
package code.name.monkey.retromusic.ui.fragments.base;
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper;
/**
* Created by hemanths on 24/09/17.
*/
public abstract class AbsPlayerControlsFragment extends AbsMusicServiceFragment
implements MusicProgressViewUpdateHelper.Callback {
protected abstract void show();
protected abstract void hide();
protected abstract void updateShuffleState();
protected abstract void updateRepeatState();
protected abstract void setUpProgressSlider();
public abstract void setDark(int color);
}

View file

@ -0,0 +1,282 @@
package code.name.monkey.retromusic.ui.fragments.base;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog;
import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog;
import code.name.monkey.retromusic.dialogs.DeleteSongsDialog;
import code.name.monkey.retromusic.dialogs.SleepTimerDialog;
import code.name.monkey.retromusic.dialogs.SongDetailDialog;
import code.name.monkey.retromusic.dialogs.SongShareDialog;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.interfaces.PaletteColorHolder;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.ui.activities.tageditor.AbsTagEditorActivity;
import code.name.monkey.retromusic.ui.activities.tageditor.SongTagEditorActivity;
import code.name.monkey.retromusic.ui.fragments.player.PlayerAlbumCoverFragment;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.NavigationUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.util.RetroUtil;
public abstract class AbsPlayerFragment extends AbsMusicServiceFragment implements
Toolbar.OnMenuItemClickListener, PaletteColorHolder {
public static final String TAG = AbsPlayerFragment.class.getSimpleName();
private boolean isToolbarShown = true;
private Callbacks callbacks;
private AsyncTask updateIsFavoriteTask;
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
callbacks = (Callbacks) context;
} catch (ClassCastException e) {
throw new RuntimeException(
context.getClass().getSimpleName() + " must implement " + Callbacks.class
.getSimpleName());
}
}
@Override
public void onDetach() {
super.onDetach();
callbacks = null;
}
@SuppressWarnings("ConstantConditions")
@Override
public boolean onMenuItemClick(MenuItem item) {
final Song song = MusicPlayerRemote.getCurrentSong();
switch (item.getItemId()) {
case R.id.action_toggle_favorite:
toggleFavorite(song);
return true;
case R.id.action_share:
if (getFragmentManager() != null) {
SongShareDialog.create(song).show(getFragmentManager(), "SHARE_SONG");
}
return true;
case R.id.action_delete_from_device:
DeleteSongsDialog.create(song)
.show(getActivity().getSupportFragmentManager(), "DELETE_SONGS");
return true;
case R.id.action_add_to_playlist:
if (getFragmentManager() != null) {
AddToPlaylistDialog.create(song).show(getFragmentManager(), "ADD_PLAYLIST");
}
return true;
case R.id.action_clear_playing_queue:
MusicPlayerRemote.clearQueue();
return true;
case R.id.action_save_playing_queue:
CreatePlaylistDialog.create(MusicPlayerRemote.getPlayingQueue())
.show(getActivity().getSupportFragmentManager(), "ADD_TO_PLAYLIST");
return true;
case R.id.action_tag_editor:
Intent intent = new Intent(getActivity(), SongTagEditorActivity.class);
intent.putExtra(AbsTagEditorActivity.EXTRA_ID, song.id);
startActivity(intent);
return true;
case R.id.action_details:
if (getFragmentManager() != null) {
SongDetailDialog.create(song).show(getFragmentManager(), "SONG_DETAIL");
}
return true;
case R.id.action_go_to_album:
NavigationUtil.goToAlbum(getActivity(), song.albumId);
return true;
case R.id.action_go_to_artist:
NavigationUtil.goToArtist(getActivity(), song.artistId);
return true;
case R.id.now_playing:
NavigationUtil.goToPlayingQueue(getActivity());
return true;
case R.id.action_show_lyrics:
NavigationUtil.goToLyrics(getActivity());
return true;
case R.id.action_equalizer:
NavigationUtil.openEqualizer(getActivity());
return true;
case R.id.action_sleep_timer:
new SleepTimerDialog().show(getFragmentManager(), TAG);
return true;
case R.id.action_set_as_ringtone:
MusicUtil.setRingtone(getActivity(), song.id);
return true;
case R.id.action_go_to_genre:
/*MediaMetadataRetriever retriever = new MediaMetadataRetriever();
Uri trackUri = ContentUris
.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, song.id);
retriever.setDataSource(getActivity(), trackUri);
String genre = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE);
if (genre == null) {
genre = "Not Specified";
}*/
Toast.makeText(getContext(), "Soon", Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
protected void toggleFavorite(Song song) {
MusicUtil.toggleFavorite(getActivity(), song);
}
protected boolean isToolbarShown() {
return isToolbarShown;
}
protected void setToolbarShown(boolean toolbarShown) {
isToolbarShown = toolbarShown;
}
protected void showToolbar(@Nullable final View toolbar) {
if (toolbar == null) {
return;
}
setToolbarShown(true);
toolbar.setVisibility(View.VISIBLE);
toolbar.animate().alpha(1f).setDuration(PlayerAlbumCoverFragment.VISIBILITY_ANIM_DURATION);
}
protected void hideToolbar(@Nullable final View toolbar) {
if (toolbar == null) {
return;
}
setToolbarShown(false);
toolbar.animate().alpha(0f).setDuration(PlayerAlbumCoverFragment.VISIBILITY_ANIM_DURATION)
.withEndAction(new Runnable() {
@Override
public void run() {
toolbar.setVisibility(View.GONE);
}
});
}
protected void toggleToolbar(@Nullable final View toolbar) {
if (isToolbarShown()) {
hideToolbar(toolbar);
} else {
showToolbar(toolbar);
}
}
protected void checkToggleToolbar(@Nullable final View toolbar) {
if (toolbar != null && !isToolbarShown() && toolbar.getVisibility() != View.GONE) {
hideToolbar(toolbar);
} else if (toolbar != null && isToolbarShown() && toolbar.getVisibility() != View.VISIBLE) {
showToolbar(toolbar);
}
}
public abstract void onShow();
public abstract void onHide();
public abstract boolean onBackPressed();
public abstract Toolbar getToolbar();
public abstract int toolbarIconColor();
@Override
public void onServiceConnected() {
updateIsFavorite();
//updateLyrics();
}
@Override
public void onPlayingMetaChanged() {
updateIsFavorite();
//updateLyrics();
}
@Override
public void onDestroyView() {
if (updateIsFavoriteTask != null && !updateIsFavoriteTask.isCancelled()) {
updateIsFavoriteTask.cancel(true);
}
super.onDestroyView();
}
@SuppressLint("StaticFieldLeak")
public void updateIsFavorite() {
if (updateIsFavoriteTask != null) {
updateIsFavoriteTask.cancel(false);
}
updateIsFavoriteTask = new AsyncTask<Song, Void, Boolean>() {
@Override
protected Boolean doInBackground(Song... params) {
Activity activity = getActivity();
if (activity != null) {
return MusicUtil.isFavorite(getActivity(), params[0]);
} else {
cancel(false);
return null;
}
}
@Override
protected void onPostExecute(Boolean isFavorite) {
Activity activity = getActivity();
if (activity != null) {
int res = isFavorite ? R.drawable.ic_favorite_white_24dp
: R.drawable.ic_favorite_border_white_24dp;
Drawable drawable = RetroUtil.getTintedVectorDrawable(activity, res, toolbarIconColor());
getToolbar().getMenu().findItem(R.id.action_toggle_favorite)
.setIcon(drawable)
.setTitle(isFavorite ? getString(R.string.action_remove_from_favorites)
: getString(R.string.action_add_to_favorites));
}
}
}.execute(MusicPlayerRemote.getCurrentSong());
}
public Callbacks getCallbacks() {
return callbacks;
}
protected void toggleStatusBar(ViewGroup viewGroup) {
if (!PreferenceUtil.getInstance(getContext()).getFullScreenMode()) {
RetroUtil.statusBarHeight(viewGroup);
}
}
protected void toggleStatusBar(View viewGroup) {
if (!PreferenceUtil.getInstance(getContext()).getFullScreenMode()) {
RetroUtil.statusBarHeight(viewGroup);
}
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.setBackgroundColor(ThemeStore.primaryColor(getActivity()));
}
public interface Callbacks {
void onPaletteColorChanged();
}
}

View file

@ -0,0 +1,275 @@
package code.name.monkey.retromusic.ui.fragments.intro;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore.Images.Media;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
import com.afollestad.materialdialogs.MaterialDialog.Builder;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.util.Compressor;
import code.name.monkey.retromusic.util.ImageUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.views.CircularImageView;
import code.name.monkey.retromusic.views.IconImageView;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
import static android.app.Activity.RESULT_OK;
import static code.name.monkey.retromusic.Constants.USER_BANNER;
import static code.name.monkey.retromusic.Constants.USER_PROFILE;
public class NameFragment extends Fragment {
private static final int PICK_IMAGE_REQUEST = 9002;
private static final int PICK_BANNER_REQUEST = 9003;
private static final int PROFILE_ICON_SIZE = 400;
@BindView(R.id.name)
EditText name;
@BindView(R.id.user_image)
CircularImageView userImage;
@BindView(R.id.image)
ImageView image;
@BindView(R.id.banner_select)
IconImageView imageView;
private Unbinder unbinder;
private CompositeDisposable disposable;
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
Bundle savedInstanceState) {
View view = LayoutInflater.from(getActivity())
.inflate(R.layout.fragment_name, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//noinspection ConstantConditions
name.setText(PreferenceUtil.getInstance(getActivity()).getUserName());
if (!PreferenceUtil.getInstance(getActivity()).getProfileImage().isEmpty()) {
loadImageFromStorage(PreferenceUtil.getInstance(getActivity()).getProfileImage());
}
if (!PreferenceUtil.getInstance(getActivity()).getBannerImage().isEmpty()) {
loadBannerFromStorage(PreferenceUtil.getInstance(getActivity()).getBannerImage());
imageView.setImageResource(R.drawable.ic_close_white_24dp);
}
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
disposable = new CompositeDisposable();
}
@OnClick({R.id.next, R.id.banner_select})
void next(View view) {
switch (view.getId()) {
case R.id.banner_select:
showBannerOptions();
break;
case R.id.next:
String nameString = name.getText().toString().trim();
if (TextUtils.isEmpty(nameString)) {
Toast.makeText(getActivity(), "Umm name is empty", Toast.LENGTH_SHORT).show();
return;
}
//noinspection ConstantConditions
PreferenceUtil.getInstance(getActivity()).setUserName(nameString);
getActivity().setResult(RESULT_OK);
//((UserInfoActivity) getActivity()).setFragment(new ChooseThemeFragment(), true);
getActivity().finish();
break;
}
}
private void showBannerOptions() {
//noinspection ConstantConditions
new Builder(getContext())
.title(R.string.select_banner_photo)
.items(Arrays.asList(getString(R.string.new_banner_photo),
getString(R.string.remove_banner_photo)))
.itemsCallback((dialog, itemView, position, text) -> {
switch (position) {
case 0:
selectBannerImage();
break;
case 1:
PreferenceUtil.getInstance(getContext()).setBannerImagePath("");
break;
}
}).show();
}
private void selectBannerImage() {
//noinspection ConstantConditions
if (PreferenceUtil.getInstance(getActivity()).getBannerImage().isEmpty()) {
Intent pickImageIntent = new Intent(Intent.ACTION_PICK,
Media.EXTERNAL_CONTENT_URI);
pickImageIntent.setType("image/*");
pickImageIntent.putExtra("crop", "true");
pickImageIntent.putExtra("outputX", 1290);
pickImageIntent.putExtra("outputY", 720);
pickImageIntent.putExtra("aspectX", 16);
pickImageIntent.putExtra("aspectY", 9);
pickImageIntent.putExtra("scale", true);
//intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(pickImageIntent,
"Select Picture"), PICK_BANNER_REQUEST);
} else {
PreferenceUtil.getInstance(getContext()).setBannerImagePath("");
image.setImageResource(android.R.color.transparent);
imageView.setImageResource(R.drawable.ic_edit_white_24dp);
}
}
@OnClick(R.id.image)
public void onViewClicked() {
//noinspection ConstantConditions
new Builder(getContext())
.title("Set a profile photo")
.items(Arrays.asList(getString(R.string.new_profile_photo),
getString(R.string.remove_profile_photo)))
.itemsCallback((dialog, itemView, position, text) -> {
switch (position) {
case 0:
pickNewPhoto();
break;
case 1:
PreferenceUtil.getInstance(getContext()).saveProfileImage("");
break;
}
}).show();
}
private void pickNewPhoto() {
Intent pickImageIntent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
pickImageIntent.setType("image/*");
pickImageIntent.putExtra("crop", "true");
pickImageIntent.putExtra("outputX", 512);
pickImageIntent.putExtra("outputY", 512);
pickImageIntent.putExtra("aspectX", 1);
pickImageIntent.putExtra("aspectY", 1);
pickImageIntent.putExtra("scale", true);
startActivityForResult(Intent.createChooser(pickImageIntent, "Select Picture"),
PICK_IMAGE_REQUEST);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null &&
data.getData() != null) {
Uri uri = data.getData();
try {
Bitmap bitmap = ImageUtil.getResizedBitmap(Media.getBitmap(getActivity()
.getContentResolver(), uri), PROFILE_ICON_SIZE);
String profileImagePath = saveToInternalStorage(bitmap, USER_PROFILE);
PreferenceUtil.getInstance(getActivity()).saveProfileImage(profileImagePath);
loadImageFromStorage(profileImagePath);
} catch (IOException e) {
e.printStackTrace();
}
}
if (requestCode == PICK_BANNER_REQUEST && resultCode == RESULT_OK && data != null &&
data.getData() != null) {
Uri uri = data.getData();
try {
Bitmap bitmap = Media.getBitmap(getActivity().getContentResolver(), uri);
String profileImagePath = saveToInternalStorage(bitmap, USER_BANNER);
PreferenceUtil.getInstance(getActivity()).setBannerImagePath(profileImagePath);
loadBannerFromStorage(profileImagePath);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void loadBannerFromStorage(String profileImagePath) {
disposable.add(new Compressor(getActivity())
.setQuality(100)
.setCompressFormat(Bitmap.CompressFormat.WEBP)
.compressToBitmapAsFlowable(new File(profileImagePath, USER_BANNER))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(bitmap -> {
image.setImageBitmap(bitmap);
}));
}
private void loadImageFromStorage(String path) {
disposable.add(new Compressor(getActivity())
.setMaxHeight(300)
.setMaxWidth(300)
.setQuality(75)
.setCompressFormat(Bitmap.CompressFormat.WEBP)
.compressToBitmapAsFlowable(new File(path, USER_PROFILE))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(bitmap -> {
userImage.setImageBitmap(bitmap);
}));
}
private String saveToInternalStorage(Bitmap bitmapImage, String userBanner) {
ContextWrapper cw = new ContextWrapper(getActivity());
// path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
// Create imageDir
File mypath = new File(directory, userBanner);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.WEBP, 100, fos);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return directory.getAbsolutePath();
}
}

View file

@ -0,0 +1,168 @@
package code.name.monkey.retromusic.ui.fragments.mainactivity;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.GridLayoutManager;
import java.util.ArrayList;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.model.Album;
import code.name.monkey.retromusic.mvp.contract.AlbumContract;
import code.name.monkey.retromusic.mvp.presenter.AlbumPresenter;
import code.name.monkey.retromusic.ui.adapter.album.AlbumAdapter;
import code.name.monkey.retromusic.ui.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment;
import code.name.monkey.retromusic.util.PreferenceUtil;
public class AlbumsFragment extends
AbsLibraryPagerRecyclerViewCustomGridSizeFragment<AlbumAdapter, GridLayoutManager> implements
AlbumContract.AlbumView {
public static final String TAG = AlbumsFragment.class.getSimpleName();
private AlbumPresenter presenter;
public static AlbumsFragment newInstance() {
Bundle args = new Bundle();
AlbumsFragment fragment = new AlbumsFragment();
fragment.setArguments(args);
return fragment;
}
@Override
protected GridLayoutManager createLayoutManager() {
return new GridLayoutManager(getActivity(), getGridSize());
}
@NonNull
@Override
protected AlbumAdapter createAdapter() {
int itemLayoutRes = getItemLayoutRes();
notifyLayoutResChanged(itemLayoutRes);
if (itemLayoutRes != R.layout.item_list) {
itemLayoutRes = PreferenceUtil.getInstance(getContext()).getAlbumGridStyle(getContext());
}
ArrayList<Album> dataSet =
getAdapter() == null ? new ArrayList<>() : getAdapter().getDataSet();
return new AlbumAdapter(getLibraryFragment().getMainActivity(), dataSet, itemLayoutRes,
loadUsePalette(), getLibraryFragment());
}
@Override
protected int getEmptyMessage() {
return R.string.no_albums;
}
@Override
public boolean loadUsePalette() {
return PreferenceUtil.getInstance(getActivity()).albumColoredFooters();
}
@Override
protected void setUsePalette(boolean usePalette) {
getAdapter().usePalette(usePalette);
}
@Override
protected void setGridSize(int gridSize) {
getLayoutManager().setSpanCount(gridSize);
getAdapter().notifyDataSetChanged();
}
@Override
protected void setSortOrder(String sortOrder) {
presenter.loadAlbums();
}
@Override
protected String loadSortOrder() {
return PreferenceUtil.getInstance(getActivity()).getAlbumSortOrder();
}
@Override
protected void saveSortOrder(String sortOrder) {
PreferenceUtil.getInstance(getActivity()).setAlbumSortOrder(sortOrder);
}
@Override
protected int loadGridSize() {
return PreferenceUtil.getInstance(getActivity()).getAlbumGridSize(getActivity());
}
@Override
protected void saveGridSize(int gridSize) {
PreferenceUtil.getInstance(getActivity()).setAlbumGridSize(gridSize);
}
@Override
protected int loadGridSizeLand() {
return PreferenceUtil.getInstance(getActivity()).getAlbumGridSizeLand(getActivity());
}
@Override
protected void saveGridSizeLand(int gridSize) {
PreferenceUtil.getInstance(getActivity()).setAlbumGridSizeLand(gridSize);
}
@Override
protected void saveUsePalette(boolean usePalette) {
PreferenceUtil.getInstance(getActivity()).setAlbumColoredFooters(usePalette);
}
@Override
public void onMediaStoreChanged() {
presenter.loadAlbums();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
presenter = new AlbumPresenter(this);
}
@Override
public void setMenuVisibility(boolean menuVisible) {
super.setMenuVisibility(menuVisible);
if (menuVisible) {
getLibraryFragment().getToolbar().setTitle(
PreferenceUtil.getInstance(getContext()).tabTitles() ? R.string.library
: R.string.albums);
}
}
@Override
public void onResume() {
super.onResume();
getLibraryFragment().getToolbar().setTitle(
PreferenceUtil.getInstance(getContext()).tabTitles() ? R.string.library : R.string.albums);
if (getAdapter().getDataSet().isEmpty()) {
presenter.subscribe();
}
}
@Override
public void onDestroy() {
super.onDestroy();
presenter.unsubscribe();
}
@Override
public void loading() {
}
@Override
public void showEmptyView() {
getAdapter().swapDataSet(new ArrayList<>());
}
@Override
public void completed() {
}
@Override
public void showData(ArrayList<Album> albums) {
getAdapter().swapDataSet(albums);
}
}

View file

@ -0,0 +1,173 @@
package code.name.monkey.retromusic.ui.fragments.mainactivity;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.GridLayoutManager;
import java.util.ArrayList;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.model.Artist;
import code.name.monkey.retromusic.mvp.contract.ArtistContract;
import code.name.monkey.retromusic.mvp.presenter.ArtistPresenter;
import code.name.monkey.retromusic.ui.adapter.artist.ArtistAdapter;
import code.name.monkey.retromusic.ui.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment;
import code.name.monkey.retromusic.util.PreferenceUtil;
public class ArtistsFragment extends
AbsLibraryPagerRecyclerViewCustomGridSizeFragment<ArtistAdapter, GridLayoutManager> implements
ArtistContract.ArtistView {
public static final String TAG = ArtistsFragment.class.getSimpleName();
private ArtistPresenter presenter;
public static ArtistsFragment newInstance() {
Bundle args = new Bundle();
ArtistsFragment fragment = new ArtistsFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
presenter = new ArtistPresenter(this);
}
@NonNull
@Override
protected GridLayoutManager createLayoutManager() {
return new GridLayoutManager(getActivity(), getGridSize());
}
@NonNull
@Override
protected ArtistAdapter createAdapter() {
int itemLayoutRes = getItemLayoutRes();
notifyLayoutResChanged(itemLayoutRes);
if (itemLayoutRes != R.layout.item_list) {
itemLayoutRes = PreferenceUtil.getInstance(getContext()).getArtistGridStyle(getContext());
}
ArrayList<Artist> dataSet =
getAdapter() == null ? new ArrayList<>() : getAdapter().getDataSet();
return new ArtistAdapter(getLibraryFragment().getMainActivity(), dataSet, itemLayoutRes,
loadUsePalette(), getLibraryFragment());
}
@Override
protected int getEmptyMessage() {
return R.string.no_artists;
}
@Override
public void onMediaStoreChanged() {
presenter.loadArtists();
}
@Override
protected int loadGridSize() {
return PreferenceUtil.getInstance(getActivity()).getArtistGridSize(getActivity());
}
@Override
protected void saveGridSize(int gridSize) {
PreferenceUtil.getInstance(getActivity()).setArtistGridSize(gridSize);
}
@Override
protected int loadGridSizeLand() {
return PreferenceUtil.getInstance(getActivity()).getArtistGridSizeLand(getActivity());
}
@Override
protected void saveGridSizeLand(int gridSize) {
PreferenceUtil.getInstance(getActivity()).setArtistGridSizeLand(gridSize);
}
@Override
protected void saveUsePalette(boolean usePalette) {
PreferenceUtil.getInstance(getActivity()).setArtistColoredFooters(usePalette);
}
@Override
public boolean loadUsePalette() {
return PreferenceUtil.getInstance(getActivity()).artistColoredFooters();
}
@Override
protected void setUsePalette(boolean usePalette) {
getAdapter().usePalette(usePalette);
}
@Override
protected void setGridSize(int gridSize) {
getLayoutManager().setSpanCount(gridSize);
getAdapter().notifyDataSetChanged();
}
@Override
protected String loadSortOrder() {
return PreferenceUtil.getInstance(getActivity()).getArtistSortOrder();
}
@Override
protected void saveSortOrder(String sortOrder) {
PreferenceUtil.getInstance(getActivity()).setArtistSortOrder(sortOrder);
}
@Override
protected void setSortOrder(String sortOrder) {
presenter.loadArtists();
}
@Override
public void setMenuVisibility(boolean menuVisible) {
super.setMenuVisibility(menuVisible);
if (menuVisible) {
getLibraryFragment().getToolbar().setTitle(
PreferenceUtil.getInstance(getContext()).tabTitles() ? R.string.library
: R.string.artists);
}
}
@Override
public void onResume() {
super.onResume();
getLibraryFragment().getToolbar().setTitle(
PreferenceUtil.getInstance(getContext()).tabTitles() ? R.string.library : R.string.artists);
if (getAdapter().getDataSet().isEmpty()) {
presenter.subscribe();
}
}
@Override
public void onDestroy() {
super.onDestroy();
presenter.unsubscribe();
}
@Override
public void loading() {
}
@Override
public void showEmptyView() {
getAdapter().swapDataSet(new ArrayList<>());
}
@Override
public void completed() {
}
@Override
public void showData(ArrayList<Artist> artists) {
getAdapter().swapDataSet(artists);
}
}

View file

@ -0,0 +1,112 @@
package code.name.monkey.retromusic.ui.fragments.mainactivity;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.LinearLayoutManager;
import android.view.Menu;
import android.view.MenuInflater;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.model.Genre;
import code.name.monkey.retromusic.mvp.contract.GenreContract;
import code.name.monkey.retromusic.mvp.presenter.GenrePresenter;
import code.name.monkey.retromusic.ui.adapter.GenreAdapter;
import code.name.monkey.retromusic.ui.fragments.base.AbsLibraryPagerRecyclerViewFragment;
import code.name.monkey.retromusic.util.PreferenceUtil;
import java.util.ArrayList;
public class GenreFragment extends
AbsLibraryPagerRecyclerViewFragment<GenreAdapter, LinearLayoutManager> implements
GenreContract.GenreView {
private GenrePresenter mPresenter;
public static GenreFragment newInstance() {
Bundle args = new Bundle();
GenreFragment fragment = new GenreFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
mPresenter = new GenrePresenter(this);
}
@Override
public void setMenuVisibility(boolean menuVisible) {
super.setMenuVisibility(menuVisible);
if (menuVisible) {
getLibraryFragment().getToolbar().setTitle(
PreferenceUtil.getInstance(getContext()).tabTitles() ? R.string.library
: R.string.genres);
}
}
@Override
public void onResume() {
super.onResume();
getLibraryFragment().getToolbar().setTitle(
PreferenceUtil.getInstance(getContext()).tabTitles() ? R.string.library : R.string.genres);
if (getAdapter().getDataSet().isEmpty()) {
mPresenter.subscribe();
}
}
@Override
public void onDestroy() {
super.onDestroy();
mPresenter.unsubscribe();
}
@NonNull
@Override
protected LinearLayoutManager createLayoutManager() {
return new LinearLayoutManager(getActivity());
}
@NonNull
@Override
protected GenreAdapter createAdapter() {
ArrayList<Genre> dataSet =
getAdapter() == null ? new ArrayList<Genre>() : getAdapter().getDataSet();
return new GenreAdapter(getLibraryFragment().getMainActivity(), dataSet, R.layout.item_list);
}
@Override
public void loading() {
}
@Override
public void showData(ArrayList<Genre> songs) {
getAdapter().swapDataSet(songs);
}
@Override
public void showEmptyView() {
getAdapter().swapDataSet(new ArrayList<Genre>());
}
@Override
public void completed() {
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.removeItem(R.id.action_sort_order);
menu.removeItem(R.id.action_grid_size);
menu.removeItem(R.id.action_new_playlist);
}
@Override
protected int getEmptyMessage() {
return R.string.no_genres;
}
}

View file

@ -0,0 +1,458 @@
package code.name.monkey.retromusic.ui.fragments.mainactivity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.AppBarLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup;
import com.afollestad.materialcab.MaterialCab;
import java.util.Objects;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.common.ATHToolbarActivity;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.dialogs.CreatePlaylistDialog;
import code.name.monkey.retromusic.dialogs.SleepTimerDialog;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.SortOrder;
import code.name.monkey.retromusic.interfaces.CabHolder;
import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks;
import code.name.monkey.retromusic.loaders.SongLoader;
import code.name.monkey.retromusic.ui.activities.SearchActivity;
import code.name.monkey.retromusic.ui.activities.SettingsActivity;
import code.name.monkey.retromusic.ui.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment;
import code.name.monkey.retromusic.ui.fragments.base.AbsMainActivityFragment;
import code.name.monkey.retromusic.util.NavigationUtil;
import code.name.monkey.retromusic.util.RetroColorUtil;
import code.name.monkey.retromusic.util.RetroUtil;
import code.name.monkey.retromusic.views.SansFontCollapsingToolbarLayout;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
public class LibraryFragment extends AbsMainActivityFragment implements CabHolder,
MainActivityFragmentCallbacks {
private static final String TAG = "LibraryFragment";
private static final String CURRENT_TAB_ID = "current_tab_id";
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.appbar)
AppBarLayout appbar;
@BindView(R.id.collapsing_toolbar)
SansFontCollapsingToolbarLayout collapsingToolbar;
private Unbinder unBinder;
private MaterialCab cab;
private FragmentManager fragmentManager;
public static Fragment newInstance(int tab) {
Bundle args = new Bundle();
args.putInt(CURRENT_TAB_ID, tab);
LibraryFragment fragment = new LibraryFragment();
fragment.setArguments(args);
return fragment;
}
public SansFontCollapsingToolbarLayout getToolbar() {
return collapsingToolbar;
}
public void addOnAppBarOffsetChangedListener(
AppBarLayout.OnOffsetChangedListener onOffsetChangedListener) {
appbar.addOnOffsetChangedListener(onOffsetChangedListener);
}
public void removeOnAppBarOffsetChangedListener(
AppBarLayout.OnOffsetChangedListener onOffsetChangedListener) {
appbar.removeOnOffsetChangedListener(onOffsetChangedListener);
}
public int getTotalAppBarScrollingRange() {
return appbar.getTotalScrollRange();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_library, container, false);
unBinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setStatusbarColorAuto(view);
getMainActivity().setBottomBarVisibility(View.VISIBLE);
setupToolbar();
if (getArguments() == null) {
selectedFragment(SongsFragment.newInstance());
return;
}
switch (getArguments().getInt(CURRENT_TAB_ID)) {
default:
case R.id.action_song:
selectedFragment(SongsFragment.newInstance());
break;
case R.id.action_album:
selectedFragment(AlbumsFragment.newInstance());
break;
case R.id.action_artist:
selectedFragment(ArtistsFragment.newInstance());
break;
case R.id.action_playlist:
selectedFragment(PlaylistsFragment.newInstance());
break;
}
}
private void setupToolbar() {
//noinspection ConstantConditions
int primaryColor = ThemeStore.primaryColor(getContext());
appbar.setBackgroundColor(primaryColor);
toolbar.setBackgroundColor(primaryColor);
toolbar.setTitle(R.string.library);
appbar.addOnOffsetChangedListener((appBarLayout, verticalOffset) ->
getMainActivity().setLightStatusbar(!ATHUtil.isWindowBackgroundDark(getContext())));
Objects.requireNonNull(getActivity()).setTitle(R.string.app_name);
getMainActivity().setSupportActionBar(toolbar);
}
public Fragment getCurrentFragment() {
if (fragmentManager == null) {
return SongsFragment.newInstance();
}
return fragmentManager.findFragmentByTag(LibraryFragment.TAG);
}
@Override
public void onDestroyView() {
super.onDestroyView();
unBinder.unbind();
}
@Override
public boolean handleBackPress() {
if (cab != null && cab.isActive()) {
cab.finish();
return true;
}
return false;
}
public void selectedFragment(Fragment fragment) {
fragmentManager = getChildFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction
.replace(R.id.fragment_container, fragment, TAG)
.commit();
}
@NonNull
@Override
public MaterialCab openCab(int menuRes, MaterialCab.Callback callback) {
if (cab != null && cab.isActive()) {
cab.finish();
}
//noinspection ConstantConditions
cab = new MaterialCab(getMainActivity(), R.id.cab_stub)
.setMenu(menuRes)
.setCloseDrawableRes(R.drawable.ic_close_white_24dp)
.setBackgroundColor(
RetroColorUtil.shiftBackgroundColorForLightText(ThemeStore.primaryColor(getActivity())))
.start(callback);
return cab;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_main, menu);
Fragment currentFragment = getCurrentFragment();
if (currentFragment instanceof AbsLibraryPagerRecyclerViewCustomGridSizeFragment
&& currentFragment.isAdded()) {
AbsLibraryPagerRecyclerViewCustomGridSizeFragment fragment = (AbsLibraryPagerRecyclerViewCustomGridSizeFragment) currentFragment;
MenuItem gridSizeItem = menu.findItem(R.id.action_grid_size);
if (RetroUtil.isLandscape(getResources())) {
gridSizeItem.setTitle(R.string.action_grid_size_land);
}
setUpGridSizeMenu(fragment, gridSizeItem.getSubMenu());
setUpSortOrderMenu(fragment, menu.findItem(R.id.action_sort_order).getSubMenu());
} else {
menu.add(0, R.id.action_new_playlist, 0, R.string.new_playlist_title);
menu.removeItem(R.id.action_grid_size);
}
Activity activity = getActivity();
if (activity == null) {
return;
}
ToolbarContentTintHelper.handleOnCreateOptionsMenu(getActivity(), toolbar, menu,
ATHToolbarActivity.getToolbarBackgroundColor(toolbar));
}
private void setUpSortOrderMenu(
@NonNull AbsLibraryPagerRecyclerViewCustomGridSizeFragment fragment,
@NonNull SubMenu sortOrderMenu) {
String currentSortOrder = fragment.getSortOrder();
sortOrderMenu.clear();
if (fragment instanceof AlbumsFragment) {
sortOrderMenu.add(0, R.id.action_album_sort_order_asc, 0, R.string.sort_order_a_z)
.setChecked(currentSortOrder.equals(SortOrder.AlbumSortOrder.ALBUM_A_Z));
sortOrderMenu.add(0, R.id.action_album_sort_order_desc, 1, R.string.sort_order_z_a)
.setChecked(currentSortOrder.equals(SortOrder.AlbumSortOrder.ALBUM_Z_A));
sortOrderMenu.add(0, R.id.action_album_sort_order_artist, 2, R.string.sort_order_artist)
.setChecked(currentSortOrder.equals(SortOrder.AlbumSortOrder.ALBUM_ARTIST));
sortOrderMenu.add(0, R.id.action_album_sort_order_year, 3, R.string.sort_order_year)
.setChecked(currentSortOrder.equals(SortOrder.AlbumSortOrder.ALBUM_YEAR));
} else if (fragment instanceof ArtistsFragment) {
sortOrderMenu.add(0, R.id.action_artist_sort_order_asc, 0, R.string.sort_order_a_z)
.setChecked(currentSortOrder.equals(SortOrder.ArtistSortOrder.ARTIST_A_Z));
sortOrderMenu.add(0, R.id.action_artist_sort_order_desc, 1, R.string.sort_order_z_a)
.setChecked(currentSortOrder.equals(SortOrder.ArtistSortOrder.ARTIST_Z_A));
} else if (fragment instanceof SongsFragment) {
sortOrderMenu.add(0, R.id.action_song_sort_order_asc, 0, R.string.sort_order_a_z)
.setChecked(currentSortOrder.equals(SortOrder.SongSortOrder.SONG_A_Z));
sortOrderMenu.add(0, R.id.action_song_sort_order_desc, 1, R.string.sort_order_z_a)
.setChecked(currentSortOrder.equals(SortOrder.SongSortOrder.SONG_Z_A));
sortOrderMenu.add(0, R.id.action_song_sort_order_artist, 2, R.string.sort_order_artist)
.setChecked(currentSortOrder.equals(SortOrder.SongSortOrder.SONG_ARTIST));
sortOrderMenu.add(0, R.id.action_song_sort_order_album, 3, R.string.sort_order_album)
.setChecked(currentSortOrder.equals(SortOrder.SongSortOrder.SONG_ALBUM));
sortOrderMenu.add(0, R.id.action_song_sort_order_year, 4, R.string.sort_order_year)
.setChecked(currentSortOrder.equals(SortOrder.SongSortOrder.SONG_YEAR));
sortOrderMenu.add(0, R.id.action_song_sort_order_date, 4, R.string.sort_order_date)
.setChecked(currentSortOrder.equals(SortOrder.SongSortOrder.SONG_DATE));
}
sortOrderMenu.setGroupCheckable(0, true, true);
}
private boolean handleSortOrderMenuItem(
@NonNull AbsLibraryPagerRecyclerViewCustomGridSizeFragment fragment, @NonNull MenuItem item) {
String sortOrder = null;
if (fragment instanceof AlbumsFragment) {
switch (item.getItemId()) {
case R.id.action_album_sort_order_asc:
sortOrder = SortOrder.AlbumSortOrder.ALBUM_A_Z;
break;
case R.id.action_album_sort_order_desc:
sortOrder = SortOrder.AlbumSortOrder.ALBUM_Z_A;
break;
case R.id.action_album_sort_order_artist:
sortOrder = SortOrder.AlbumSortOrder.ALBUM_ARTIST;
break;
case R.id.action_album_sort_order_year:
sortOrder = SortOrder.AlbumSortOrder.ALBUM_YEAR;
break;
}
} else if (fragment instanceof ArtistsFragment) {
switch (item.getItemId()) {
case R.id.action_artist_sort_order_asc:
sortOrder = SortOrder.ArtistSortOrder.ARTIST_A_Z;
break;
case R.id.action_artist_sort_order_desc:
sortOrder = SortOrder.ArtistSortOrder.ARTIST_Z_A;
break;
}
} else if (fragment instanceof SongsFragment) {
switch (item.getItemId()) {
case R.id.action_song_sort_order_asc:
sortOrder = SortOrder.SongSortOrder.SONG_A_Z;
break;
case R.id.action_song_sort_order_desc:
sortOrder = SortOrder.SongSortOrder.SONG_Z_A;
break;
case R.id.action_song_sort_order_artist:
sortOrder = SortOrder.SongSortOrder.SONG_ARTIST;
break;
case R.id.action_song_sort_order_album:
sortOrder = SortOrder.SongSortOrder.SONG_ALBUM;
break;
case R.id.action_song_sort_order_year:
sortOrder = SortOrder.SongSortOrder.SONG_YEAR;
break;
case R.id.action_song_sort_order_date:
sortOrder = SortOrder.SongSortOrder.SONG_DATE;
break;
}
}
if (sortOrder != null) {
item.setChecked(true);
fragment.setAndSaveSortOrder(sortOrder);
return true;
}
return false;
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
Activity activity = getActivity();
if (activity == null) {
return;
}
ToolbarContentTintHelper.handleOnPrepareOptionsMenu(activity, toolbar);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
//if (pager == null) return false;
Fragment currentFragment = getCurrentFragment();
if (currentFragment instanceof AbsLibraryPagerRecyclerViewCustomGridSizeFragment) {
AbsLibraryPagerRecyclerViewCustomGridSizeFragment fragment = (AbsLibraryPagerRecyclerViewCustomGridSizeFragment) currentFragment;
if (handleGridSizeMenuItem(fragment, item)) {
return true;
}
if (handleSortOrderMenuItem(fragment, item)) {
return true;
}
}
int id = item.getItemId();
switch (id) {
case R.id.action_new_playlist:
CreatePlaylistDialog.create().show(getChildFragmentManager(), "CREATE_PLAYLIST");
return true;
case R.id.action_shuffle_all:
//noinspection ConstantConditions
SongLoader.getAllSongs(getContext()).subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(songs -> MusicPlayerRemote.openAndShuffleQueue(songs, true));
return true;
case R.id.action_search:
startActivity(new Intent(getActivity(), SearchActivity.class));
return true;
case R.id.action_equalizer:
//noinspection ConstantConditions
NavigationUtil.openEqualizer(getActivity());
return true;
case R.id.action_sleep_timer:
if (getFragmentManager() != null) {
new SleepTimerDialog().show(getFragmentManager(), TAG);
}
return true;
case R.id.action_settings:
startActivity(new Intent(getContext(), SettingsActivity.class));
break;
}
return super.onOptionsItemSelected(item);
}
private void setUpGridSizeMenu(
@NonNull AbsLibraryPagerRecyclerViewCustomGridSizeFragment fragment,
@NonNull SubMenu gridSizeMenu) {
switch (fragment.getGridSize()) {
case 1:
gridSizeMenu.findItem(R.id.action_grid_size_1).setChecked(true);
break;
case 2:
gridSizeMenu.findItem(R.id.action_grid_size_2).setChecked(true);
break;
case 3:
gridSizeMenu.findItem(R.id.action_grid_size_3).setChecked(true);
break;
case 4:
gridSizeMenu.findItem(R.id.action_grid_size_4).setChecked(true);
break;
case 5:
gridSizeMenu.findItem(R.id.action_grid_size_5).setChecked(true);
break;
case 6:
gridSizeMenu.findItem(R.id.action_grid_size_6).setChecked(true);
break;
case 7:
gridSizeMenu.findItem(R.id.action_grid_size_7).setChecked(true);
break;
case 8:
gridSizeMenu.findItem(R.id.action_grid_size_8).setChecked(true);
break;
}
int maxGridSize = fragment.getMaxGridSize();
if (maxGridSize < 8) {
gridSizeMenu.findItem(R.id.action_grid_size_8).setVisible(false);
}
if (maxGridSize < 7) {
gridSizeMenu.findItem(R.id.action_grid_size_7).setVisible(false);
}
if (maxGridSize < 6) {
gridSizeMenu.findItem(R.id.action_grid_size_6).setVisible(false);
}
if (maxGridSize < 5) {
gridSizeMenu.findItem(R.id.action_grid_size_5).setVisible(false);
}
if (maxGridSize < 4) {
gridSizeMenu.findItem(R.id.action_grid_size_4).setVisible(false);
}
if (maxGridSize < 3) {
gridSizeMenu.findItem(R.id.action_grid_size_3).setVisible(false);
}
}
private boolean handleGridSizeMenuItem(
@NonNull AbsLibraryPagerRecyclerViewCustomGridSizeFragment fragment, @NonNull MenuItem item) {
int gridSize = 0;
switch (item.getItemId()) {
case R.id.action_grid_size_1:
gridSize = 1;
break;
case R.id.action_grid_size_2:
gridSize = 2;
break;
case R.id.action_grid_size_3:
gridSize = 3;
break;
case R.id.action_grid_size_4:
gridSize = 4;
break;
case R.id.action_grid_size_5:
gridSize = 5;
break;
case R.id.action_grid_size_6:
gridSize = 6;
break;
case R.id.action_grid_size_7:
gridSize = 7;
break;
case R.id.action_grid_size_8:
gridSize = 8;
break;
}
if (gridSize > 0) {
item.setChecked(true);
fragment.setAndSaveGridSize(gridSize);
return true;
}
return false;
}
}

View file

@ -0,0 +1,120 @@
package code.name.monkey.retromusic.ui.fragments.mainactivity;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.LinearLayoutManager;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import java.util.ArrayList;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.model.Playlist;
import code.name.monkey.retromusic.mvp.contract.PlaylistContract;
import code.name.monkey.retromusic.mvp.presenter.PlaylistPresenter;
import code.name.monkey.retromusic.ui.adapter.playlist.PlaylistAdapter;
import code.name.monkey.retromusic.ui.fragments.base.AbsLibraryPagerRecyclerViewFragment;
import code.name.monkey.retromusic.util.PreferenceUtil;
public class PlaylistsFragment extends AbsLibraryPagerRecyclerViewFragment<PlaylistAdapter, LinearLayoutManager> implements
PlaylistContract.PlaylistView {
private PlaylistPresenter presenter;
public static PlaylistsFragment newInstance() {
Bundle args = new Bundle();
PlaylistsFragment fragment = new PlaylistsFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
presenter = new PlaylistPresenter(this);
}
@Override
protected LinearLayoutManager createLayoutManager() {
return new LinearLayoutManager(getActivity());
}
@NonNull
@Override
protected PlaylistAdapter createAdapter() {
return new PlaylistAdapter(getLibraryFragment().getMainActivity(), new ArrayList<>(),
R.layout.item_list, getLibraryFragment());
}
@Override
public void setMenuVisibility(boolean menuVisible) {
super.setMenuVisibility(menuVisible);
if (menuVisible) {
getLibraryFragment().getToolbar().setTitle(PreferenceUtil.getInstance(getContext()).tabTitles() ? R.string.library : R.string.playlists);
}
}
@Override
public void onResume() {
super.onResume();
getLibraryFragment().getToolbar().setTitle(PreferenceUtil.getInstance(getContext()).tabTitles() ? R.string.library : R.string.playlists);
if (getAdapter().getDataSet().isEmpty()) {
presenter.subscribe();
}
}
@Override
public void onDestroy() {
presenter.unsubscribe();
super.onDestroy();
}
@Override
public void onMediaStoreChanged() {
super.onMediaStoreChanged();
presenter.loadPlaylists();
}
@Override
public void loading() {
}
@Override
public void showEmptyView() {
getAdapter().swapDataSet(new ArrayList<>());
}
@Override
public void completed() {
}
@Override
public void showData(ArrayList<Playlist> playlists) {
getAdapter().swapDataSet(playlists);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.removeItem(R.id.action_shuffle_all);
menu.removeItem(R.id.action_sort_order);
menu.removeItem(R.id.action_grid_size);
}
@Override
protected int getEmptyMessage() {
return R.string.no_playlists;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
}

View file

@ -0,0 +1,178 @@
package code.name.monkey.retromusic.ui.fragments.mainactivity;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.GridLayoutManager;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.mvp.contract.SongContract;
import code.name.monkey.retromusic.mvp.presenter.SongPresenter;
import code.name.monkey.retromusic.ui.adapter.song.ShuffleButtonSongAdapter;
import code.name.monkey.retromusic.ui.adapter.song.SongAdapter;
import code.name.monkey.retromusic.ui.fragments.base.AbsLibraryPagerRecyclerViewCustomGridSizeFragment;
import code.name.monkey.retromusic.util.PreferenceUtil;
import java.util.ArrayList;
@SuppressWarnings("ConstantConditions")
public class SongsFragment extends
AbsLibraryPagerRecyclerViewCustomGridSizeFragment<SongAdapter, GridLayoutManager> implements
SongContract.SongView {
private static final String TAG = "Songs";
private SongPresenter presenter;
public SongsFragment() {
// Required empty public constructor
}
public static SongsFragment newInstance() {
Bundle args = new Bundle();
SongsFragment fragment = new SongsFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
presenter = new SongPresenter(this);
}
@NonNull
@Override
protected GridLayoutManager createLayoutManager() {
return new GridLayoutManager(getActivity(), getGridSize());
}
@Override
protected int getEmptyMessage() {
return R.string.no_songs;
}
@NonNull
@Override
protected SongAdapter createAdapter() {
int itemLayoutRes = getItemLayoutRes();
notifyLayoutResChanged(itemLayoutRes);
boolean usePalette = loadUsePalette();
ArrayList<Song> dataSet =
getAdapter() == null ? new ArrayList<Song>() : getAdapter().getDataSet();
if (getGridSize() <= getMaxGridSizeForList()) {
return new ShuffleButtonSongAdapter(getLibraryFragment().getMainActivity(), dataSet,
itemLayoutRes, usePalette, getLibraryFragment());
}
return new SongAdapter(getLibraryFragment().getMainActivity(), dataSet, itemLayoutRes,
usePalette, getLibraryFragment());
}
@Override
public void onMediaStoreChanged() {
presenter.loadSongs();
}
@Override
protected int loadGridSize() {
return PreferenceUtil.getInstance(getActivity()).getSongGridSize(getActivity());
}
@Override
protected void saveGridSize(int gridSize) {
PreferenceUtil.getInstance(getActivity()).setSongGridSize(gridSize);
}
@Override
protected int loadGridSizeLand() {
return PreferenceUtil.getInstance(getActivity()).getSongGridSizeLand(getActivity());
}
@Override
protected void saveGridSizeLand(int gridSize) {
PreferenceUtil.getInstance(getActivity()).setSongGridSizeLand(gridSize);
}
@Override
public void saveUsePalette(boolean usePalette) {
PreferenceUtil.getInstance(getActivity()).setSongColoredFooters(usePalette);
}
@Override
public boolean loadUsePalette() {
return PreferenceUtil.getInstance(getActivity()).songColoredFooters();
}
@Override
public void setUsePalette(boolean usePalette) {
getAdapter().usePalette(usePalette);
}
@Override
protected void setGridSize(int gridSize) {
getLayoutManager().setSpanCount(gridSize);
getAdapter().notifyDataSetChanged();
}
@Override
public void onResume() {
super.onResume();
getLibraryFragment().getToolbar().setTitle(
PreferenceUtil.getInstance(getContext()).tabTitles() ? R.string.library : R.string.songs);
if (getAdapter().getDataSet().isEmpty()) {
presenter.subscribe();
}
}
@Override
public void setMenuVisibility(boolean menuVisible) {
super.setMenuVisibility(menuVisible);
if (menuVisible) {
getLibraryFragment().getToolbar().setTitle(
PreferenceUtil.getInstance(getContext()).tabTitles() ? R.string.library
: R.string.songs);
}
}
@Override
public void onDestroy() {
presenter.unsubscribe();
super.onDestroy();
}
@Override
public void loading() {
}
@Override
public void showData(ArrayList<Song> songs) {
getAdapter().swapDataSet(songs);
}
@Override
public void showEmptyView() {
getAdapter().swapDataSet(new ArrayList<Song>());
}
@Override
public void completed() {
}
@Override
protected String loadSortOrder() {
return PreferenceUtil.getInstance(getActivity()).getSongSortOrder();
}
@Override
protected void saveSortOrder(String sortOrder) {
PreferenceUtil.getInstance(getActivity()).setSongSortOrder(sortOrder);
}
@Override
protected void setSortOrder(String sortOrder) {
presenter.loadSongs();
}
}

View file

@ -0,0 +1,697 @@
package code.name.monkey.retromusic.ui.fragments.mainactivity.folders;
import android.app.Dialog;
import android.content.Context;
import android.media.MediaScannerConnection;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.MimeTypeMap;
import android.widget.PopupMenu;
import android.widget.Toast;
import com.afollestad.materialcab.MaterialCab;
import com.afollestad.materialdialogs.MaterialDialog;
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.common.ATHToolbarActivity;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.menu.SongMenuHelper;
import code.name.monkey.retromusic.helper.menu.SongsMenuHelper;
import code.name.monkey.retromusic.interfaces.CabHolder;
import code.name.monkey.retromusic.interfaces.LoaderIds;
import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks;
import code.name.monkey.retromusic.misc.DialogAsyncTask;
import code.name.monkey.retromusic.misc.UpdateToastMediaScannerCompletionListener;
import code.name.monkey.retromusic.misc.WrappedAsyncTaskLoader;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.ui.adapter.SongFileAdapter;
import code.name.monkey.retromusic.ui.fragments.base.AbsMainActivityFragment;
import code.name.monkey.retromusic.util.FileUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.util.RetroColorUtil;
import code.name.monkey.retromusic.util.ViewUtil;
import code.name.monkey.retromusic.views.BreadCrumbLayout;
public class FoldersFragment extends AbsMainActivityFragment implements
MainActivityFragmentCallbacks,
CabHolder, BreadCrumbLayout.SelectionCallback, SongFileAdapter.Callbacks,
AppBarLayout.OnOffsetChangedListener, LoaderManager.LoaderCallbacks<List<File>> {
public static final String TAG = FoldersFragment.class.getSimpleName();
public static final FileFilter AUDIO_FILE_FILTER = file -> !file.isHidden() && (file.isDirectory() ||
FileUtil.fileIsMimeType(file, "audio/*", MimeTypeMap.getSingleton()) ||
FileUtil.fileIsMimeType(file, "application/opus", MimeTypeMap.getSingleton()) ||
FileUtil.fileIsMimeType(file, "application/ogg", MimeTypeMap.getSingleton()));
protected static final String PATH = "path";
protected static final String CRUMBS = "crumbs";
private static final int LOADER_ID = LoaderIds.FOLDERS_FRAGMENT;
@BindView(R.id.coordinator_layout)
CoordinatorLayout coordinatorLayout;
@BindView(R.id.container)
View container;
@BindView(android.R.id.empty)
View empty;
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.bread_crumbs)
BreadCrumbLayout breadCrumbs;
@BindView(R.id.appbar)
AppBarLayout appbar;
@BindView(R.id.status_bar)
View statusBar;
@BindView(R.id.recycler_view)
FastScrollRecyclerView recyclerView;
Comparator<File> fileComparator = (lhs, rhs) -> {
if (lhs.isDirectory() && !rhs.isDirectory()) {
return -1;
} else if (!lhs.isDirectory() && rhs.isDirectory()) {
return 1;
} else {
return lhs.getName().compareToIgnoreCase
(rhs.getName());
}
};
private Unbinder unbinder;
private SongFileAdapter adapter;
private MaterialCab cab;
public FoldersFragment() {
}
public static FoldersFragment newInstance(Context context) {
return newInstance(PreferenceUtil.getInstance(context).getStartDirectory());
}
public static FoldersFragment newInstance(File directory) {
FoldersFragment frag = new FoldersFragment();
Bundle b = new Bundle();
b.putSerializable(PATH, directory);
frag.setArguments(b);
return frag;
}
public static File getDefaultStartDirectory() {
File musicDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);
File startFolder;
if (musicDir.exists() && musicDir.isDirectory()) {
startFolder = musicDir;
} else {
File externalStorage = Environment.getExternalStorageDirectory();
if (externalStorage.exists() && externalStorage.isDirectory()) {
startFolder = externalStorage;
} else {
startFolder = new File("/"); // root
}
}
return startFolder;
}
private static File tryGetCanonicalFile(File file) {
try {
return file.getCanonicalFile();
} catch (IOException e) {
e.printStackTrace();
return file;
}
}
public void setCrumb(BreadCrumbLayout.Crumb crumb, boolean addToHistory) {
if (crumb == null) {
return;
}
saveScrollPosition();
breadCrumbs.setActiveOrAdd(crumb, false);
if (addToHistory) {
breadCrumbs.addHistory(crumb);
}
getLoaderManager().restartLoader(LOADER_ID, null, this);
}
private void saveScrollPosition() {
BreadCrumbLayout.Crumb crumb = getActiveCrumb();
if (crumb != null) {
crumb.setScrollPosition(
((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition());
}
}
@Nullable
private BreadCrumbLayout.Crumb getActiveCrumb() {
return breadCrumbs != null && breadCrumbs.size() > 0 ? breadCrumbs
.getCrumb(breadCrumbs.getActiveIndex()) : null;
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(CRUMBS, breadCrumbs.getStateWrapper());
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState == null) {
//noinspection ConstantConditions
setCrumb(new BreadCrumbLayout.Crumb(
FileUtil.safeGetCanonicalFile((File) getArguments().getSerializable(PATH))), true);
} else {
breadCrumbs.restoreFromStateWrapper(savedInstanceState.getParcelable(CRUMBS));
getLoaderManager().initLoader(LOADER_ID, null, this);
}
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_folder, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
setStatusbarColorAuto(view);
getMainActivity().getSlidingUpPanelLayout().setShadowHeight(0);
getMainActivity().setBottomBarVisibility(View.GONE);
setUpAppbarColor();
setUpToolbar();
setUpBreadCrumbs();
setUpRecyclerView();
setUpAdapter();
ViewUtil.setStatusBarHeight(getContext(), statusBar);
}
private void setUpAppbarColor() {
//noinspection ConstantConditions
int primaryColor = ThemeStore.primaryColor(getActivity());
appbar.setBackgroundColor(primaryColor);
toolbar.setBackgroundColor(primaryColor);
//breadCrumbs.setBackgroundColor(primaryColor);
breadCrumbs.setActivatedContentColor(ToolbarContentTintHelper.toolbarTitleColor(getActivity(), primaryColor));
breadCrumbs.setDeactivatedContentColor(ToolbarContentTintHelper.toolbarSubtitleColor(getActivity(), primaryColor));
appbar.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> getMainActivity().setLightStatusbar(!ATHUtil.isWindowBackgroundDark(getContext())));
}
private void setUpToolbar() {
toolbar.setNavigationIcon(R.drawable.ic_keyboard_backspace_black_24dp);
//noinspection ConstantConditions
getActivity().setTitle(R.string.folders);
getMainActivity().setSupportActionBar(toolbar);
}
private void setUpBreadCrumbs() {
breadCrumbs.setCallback(this);
}
private void setUpRecyclerView() {
//noinspection ConstantConditions
ViewUtil.setUpFastScrollRecyclerViewColor(getActivity(), recyclerView, ThemeStore.accentColor(getActivity()));
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
appbar.addOnOffsetChangedListener(this);
}
private void setUpAdapter() {
adapter = new SongFileAdapter(getMainActivity(), new LinkedList<File>(), R.layout.item_list, this, this);
adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
super.onChanged();
checkIsEmpty();
}
});
recyclerView.setAdapter(adapter);
checkIsEmpty();
}
@Override
public void onPause() {
super.onPause();
saveScrollPosition();
}
@Override
public void onDestroyView() {
appbar.removeOnOffsetChangedListener(this);
unbinder.unbind();
super.onDestroyView();
}
@Override
public boolean handleBackPress() {
if (cab != null && cab.isActive()) {
cab.finish();
return true;
}
if (breadCrumbs != null && breadCrumbs.popHistory()) {
setCrumb(breadCrumbs.lastHistory(), false);
return true;
}
return false;
}
@NonNull
@Override
public MaterialCab openCab(int menuRes, MaterialCab.Callback callback) {
if (cab != null && cab.isActive()) cab.finish();
cab = new MaterialCab(getMainActivity(), R.id.cab_stub)
.setMenu(menuRes)
.setCloseDrawableRes(R.drawable.ic_close_white_24dp)
.setBackgroundColor(RetroColorUtil.shiftBackgroundColorForLightText(ThemeStore.primaryColor
(getActivity())))
.start(callback);
return cab;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_folders, menu);
ToolbarContentTintHelper.handleOnCreateOptionsMenu(getActivity(), toolbar, menu, ATHToolbarActivity.getToolbarBackgroundColor(toolbar));
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
ToolbarContentTintHelper.handleOnPrepareOptionsMenu(getActivity(), toolbar);
}
@Override
public void onCrumbSelection(BreadCrumbLayout.Crumb crumb, int index) {
setCrumb(crumb, true);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
//noinspection ConstantConditions
getActivity().onBackPressed();
break;
case R.id.action_go_to_start_directory:
setCrumb(new BreadCrumbLayout.Crumb(tryGetCanonicalFile(PreferenceUtil.getInstance(getActivity()).getStartDirectory())), true);
return true;
case R.id.action_scan:
BreadCrumbLayout.Crumb crumb = getActiveCrumb();
if (crumb != null) {
//noinspection Convert2MethodRef
new ListPathsAsyncTask(getActivity(), paths -> scanPaths(paths)).execute(new ListPathsAsyncTask.LoadingInfo(crumb.getFile(), AUDIO_FILE_FILTER));
}
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onFileSelected(File file) {
file = tryGetCanonicalFile(file); // important as we compare the path value later
if (file.isDirectory()) {
setCrumb(new BreadCrumbLayout.Crumb(file), true);
} else {
FileFilter fileFilter = pathname -> !pathname.isDirectory() && AUDIO_FILE_FILTER.accept(pathname);
new ListSongsAsyncTask(getActivity(), file, (songs, extra) -> {
File file1 = (File) extra;
int startIndex = -1;
for (int i = 0; i < songs.size(); i++) {
if (file1.getPath().equals(songs.get(i).data)) { // path is already canonical here
startIndex = i;
break;
}
}
if (startIndex > -1) {
MusicPlayerRemote.openQueue(songs, startIndex, true);
} else {
final File finalFile = file1;
Snackbar.make(coordinatorLayout, Html.fromHtml(String.format(getString(R.string.not_listed_in_media_store), file1.getName())), Snackbar.LENGTH_LONG)
.setAction(R.string.action_scan, v -> new ListPathsAsyncTask(getActivity(), paths -> scanPaths(paths)).execute(new ListPathsAsyncTask.LoadingInfo(finalFile, AUDIO_FILE_FILTER)))
.setActionTextColor(ThemeStore.accentColor(getActivity()))
.show();
}
}).execute(new ListSongsAsyncTask.LoadingInfo(toList(file.getParentFile()), fileFilter, getFileComparator()));
}
}
@Override
public void onMultipleItemAction(MenuItem item, ArrayList<File> files) {
final int itemId = item.getItemId();
new ListSongsAsyncTask(getActivity(), null, (songs, extra) -> SongsMenuHelper.handleMenuClick(getActivity(), songs, itemId)).execute(new ListSongsAsyncTask.LoadingInfo(files, AUDIO_FILE_FILTER, getFileComparator()));
}
private ArrayList<File> toList(File file) {
ArrayList<File> files = new ArrayList<>(1);
files.add(file);
return files;
}
private Comparator<File> getFileComparator() {
return fileComparator;
}
@Override
public void onFileMenuClicked(final File file, View view) {
PopupMenu popupMenu = new PopupMenu(getActivity(), view);
if (file.isDirectory()) {
popupMenu.inflate(R.menu.menu_item_directory);
popupMenu.setOnMenuItemClickListener(item -> {
final int itemId = item.getItemId();
switch (itemId) {
case R.id.action_play_next:
case R.id.action_add_to_current_playing:
case R.id.action_add_to_playlist:
case R.id.action_delete_from_device:
new ListSongsAsyncTask(getActivity(), null, (songs, extra) -> SongsMenuHelper.handleMenuClick(getActivity(), songs, itemId)).execute(new ListSongsAsyncTask.LoadingInfo(toList(file), AUDIO_FILE_FILTER, getFileComparator()));
return true;
case R.id.action_set_as_start_directory:
PreferenceUtil.getInstance(getActivity()).setStartDirectory(file);
Toast.makeText(getActivity(), String.format(getString(R.string.new_start_directory), file.getPath()), Toast.LENGTH_SHORT).show();
return true;
case R.id.action_scan:
new ListPathsAsyncTask(getActivity(), paths -> scanPaths(paths)).execute(new ListPathsAsyncTask.LoadingInfo(file, AUDIO_FILE_FILTER));
return true;
}
return false;
});
} else {
popupMenu.inflate(R.menu.menu_item_file);
popupMenu.setOnMenuItemClickListener(item -> {
final int itemId = item.getItemId();
switch (itemId) {
case R.id.action_play_next:
case R.id.action_add_to_current_playing:
case R.id.action_add_to_playlist:
case R.id.action_go_to_album:
case R.id.action_go_to_artist:
case R.id.action_share:
case R.id.action_tag_editor:
case R.id.action_details:
case R.id.action_set_as_ringtone:
case R.id.action_delete_from_device:
new ListSongsAsyncTask(getActivity(), null, (songs, extra) -> SongMenuHelper.handleMenuClick(getActivity(), songs.get(0), itemId)).execute(new ListSongsAsyncTask.LoadingInfo(toList(file), AUDIO_FILE_FILTER, getFileComparator()));
return true;
case R.id.action_scan:
new ListPathsAsyncTask(getActivity(), paths -> scanPaths(paths)).execute(new ListPathsAsyncTask.LoadingInfo(file, AUDIO_FILE_FILTER));
return true;
}
return false;
});
}
popupMenu.show();
}
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
container.setPadding(container.getPaddingLeft(), container.getPaddingTop(), container.getPaddingRight(), appbar.getTotalScrollRange() + verticalOffset);
}
private void checkIsEmpty() {
if (empty != null) {
empty.setVisibility(adapter == null || adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
}
}
private void scanPaths(@Nullable String[] toBeScanned) {
if (getActivity() == null) return;
if (toBeScanned == null || toBeScanned.length < 1) {
Toast.makeText(getActivity(), R.string.nothing_to_scan, Toast.LENGTH_SHORT).show();
} else {
MediaScannerConnection.scanFile(getActivity().getApplicationContext(), toBeScanned, null, new UpdateToastMediaScannerCompletionListener(getActivity(), toBeScanned));
}
}
private void updateAdapter(@NonNull List<File> files) {
adapter.swapDataSet(files);
BreadCrumbLayout.Crumb crumb = getActiveCrumb();
if (crumb != null && recyclerView != null) {
((LinearLayoutManager) recyclerView.getLayoutManager())
.scrollToPositionWithOffset(crumb.getScrollPosition(), 0);
}
}
@NonNull
@Override
public Loader<List<File>> onCreateLoader(int id, Bundle args) {
return new AsyncFileLoader(this);
}
@Override
public void onLoadFinished(@NonNull Loader<List<File>> loader, List<File> data) {
updateAdapter(data);
}
@Override
public void onLoaderReset(@NonNull Loader<List<File>> loader) {
updateAdapter(new LinkedList<File>());
}
private static class AsyncFileLoader extends WrappedAsyncTaskLoader<List<File>> {
private WeakReference<FoldersFragment> fragmentWeakReference;
public AsyncFileLoader(FoldersFragment foldersFragment) {
super(foldersFragment.getActivity());
fragmentWeakReference = new WeakReference<>(foldersFragment);
}
@Override
public List<File> loadInBackground() {
FoldersFragment foldersFragment = fragmentWeakReference.get();
File directory = null;
if (foldersFragment != null) {
BreadCrumbLayout.Crumb crumb = foldersFragment.getActiveCrumb();
if (crumb != null) {
directory = crumb.getFile();
}
}
if (directory != null) {
List<File> files = FileUtil.listFiles(directory, AUDIO_FILE_FILTER);
Collections.sort(files, foldersFragment.getFileComparator());
return files;
} else {
return new LinkedList<>();
}
}
}
private static class ListSongsAsyncTask extends ListingFilesDialogAsyncTask<ListSongsAsyncTask.LoadingInfo, Void, ArrayList<Song>> {
private final Object extra;
private WeakReference<Context> contextWeakReference;
private WeakReference<OnSongsListedCallback> callbackWeakReference;
public ListSongsAsyncTask(Context context, Object extra, OnSongsListedCallback callback) {
super(context);
this.extra = extra;
contextWeakReference = new WeakReference<>(context);
callbackWeakReference = new WeakReference<>(callback);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
checkCallbackReference();
checkContextReference();
}
@Override
protected ArrayList<Song> doInBackground(LoadingInfo... params) {
try {
LoadingInfo info = params[0];
List<File> files = FileUtil.listFilesDeep(info.files, info.fileFilter);
if (isCancelled() || checkContextReference() == null || checkCallbackReference() == null)
return null;
Collections.sort(files, info.fileComparator);
Context context = checkContextReference();
if (isCancelled() || context == null || checkCallbackReference() == null)
return null;
return FileUtil.matchFilesWithMediaStore(context, files).blockingFirst();
} catch (Exception e) {
e.printStackTrace();
cancel(false);
return null;
}
}
@Override
protected void onPostExecute(ArrayList<Song> songs) {
super.onPostExecute(songs);
OnSongsListedCallback callback = checkCallbackReference();
if (songs != null && callback != null)
callback.onSongsListed(songs, extra);
}
private Context checkContextReference() {
Context context = contextWeakReference.get();
if (context == null) {
cancel(false);
}
return context;
}
private OnSongsListedCallback checkCallbackReference() {
OnSongsListedCallback callback = callbackWeakReference.get();
if (callback == null) {
cancel(false);
}
return callback;
}
public interface OnSongsListedCallback {
void onSongsListed(@NonNull ArrayList<Song> songs, Object extra);
}
public static class LoadingInfo {
public final Comparator<File> fileComparator;
public final FileFilter fileFilter;
public final List<File> files;
public LoadingInfo(@NonNull List<File> files, @NonNull FileFilter fileFilter, @NonNull Comparator<File> fileComparator) {
this.fileComparator = fileComparator;
this.fileFilter = fileFilter;
this.files = files;
}
}
}
public static class ListPathsAsyncTask extends ListingFilesDialogAsyncTask<ListPathsAsyncTask.LoadingInfo, String, String[]> {
private WeakReference<OnPathsListedCallback> onPathsListedCallbackWeakReference;
public ListPathsAsyncTask(Context context, OnPathsListedCallback callback) {
super(context);
onPathsListedCallbackWeakReference = new WeakReference<>(callback);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
checkCallbackReference();
}
@Override
protected String[] doInBackground(LoadingInfo... params) {
try {
if (isCancelled() || checkCallbackReference() == null) return null;
LoadingInfo info = params[0];
final String[] paths;
if (info.file.isDirectory()) {
List<File> files = FileUtil.listFilesDeep(info.file, info.fileFilter);
if (isCancelled() || checkCallbackReference() == null) return null;
paths = new String[files.size()];
for (int i = 0; i < files.size(); i++) {
File f = files.get(i);
paths[i] = FileUtil.safeGetCanonicalPath(f);
if (isCancelled() || checkCallbackReference() == null) return null;
}
} else {
paths = new String[1];
paths[0] = info.file.getPath();
}
return paths;
} catch (Exception e) {
e.printStackTrace();
cancel(false);
return null;
}
}
@Override
protected void onPostExecute(String[] paths) {
super.onPostExecute(paths);
OnPathsListedCallback callback = checkCallbackReference();
if (callback != null && paths != null) {
callback.onPathsListed(paths);
}
}
private OnPathsListedCallback checkCallbackReference() {
OnPathsListedCallback callback = onPathsListedCallbackWeakReference.get();
if (callback == null) {
cancel(false);
}
return callback;
}
public interface OnPathsListedCallback {
void onPathsListed(@NonNull String[] paths);
}
public static class LoadingInfo {
public final File file;
public final FileFilter fileFilter;
public LoadingInfo(File file, FileFilter fileFilter) {
this.file = file;
this.fileFilter = fileFilter;
}
}
}
private static abstract class ListingFilesDialogAsyncTask<Params, Progress, Result> extends DialogAsyncTask<Params, Progress, Result> {
public ListingFilesDialogAsyncTask(Context context) {
super(context);
}
public ListingFilesDialogAsyncTask(Context context, int showDelay) {
super(context, showDelay);
}
@Override
protected Dialog createDialog(@NonNull Context context) {
return new MaterialDialog.Builder(context)
.title(R.string.listing_files)
.progress(true, 0)
.progressIndeterminateStyle(true)
.cancelListener(dialog -> cancel(false))
.dismissListener(dialog -> cancel(false))
.negativeText(android.R.string.cancel)
.onNegative((dialog, which) -> cancel(false))
.show();
}
}
}

View file

@ -0,0 +1,413 @@
package code.name.monkey.retromusic.ui.fragments.mainactivity.home;
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Random;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.dialogs.HomeOptionDialog;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks;
import code.name.monkey.retromusic.loaders.SongLoader;
import code.name.monkey.retromusic.misc.AppBarStateChangeListener;
import code.name.monkey.retromusic.model.Album;
import code.name.monkey.retromusic.model.Artist;
import code.name.monkey.retromusic.model.Genre;
import code.name.monkey.retromusic.model.Playlist;
import code.name.monkey.retromusic.model.smartplaylist.HistoryPlaylist;
import code.name.monkey.retromusic.model.smartplaylist.LastAddedPlaylist;
import code.name.monkey.retromusic.model.smartplaylist.MyTopTracksPlaylist;
import code.name.monkey.retromusic.mvp.contract.HomeContract;
import code.name.monkey.retromusic.mvp.presenter.HomePresenter;
import code.name.monkey.retromusic.ui.adapter.GenreAdapter;
import code.name.monkey.retromusic.ui.adapter.album.AlbumFullWithAdapter;
import code.name.monkey.retromusic.ui.adapter.artist.ArtistAdapter;
import code.name.monkey.retromusic.ui.fragments.base.AbsMainActivityFragment;
import code.name.monkey.retromusic.util.Compressor;
import code.name.monkey.retromusic.util.NavigationUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.util.RetroUtil;
import code.name.monkey.retromusic.views.CircularImageView;
import code.name.monkey.retromusic.views.MetalRecyclerViewPager;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
import static code.name.monkey.retromusic.Constants.USER_BANNER;
import static code.name.monkey.retromusic.Constants.USER_PROFILE;
public class HomeFragment extends AbsMainActivityFragment implements MainActivityFragmentCallbacks,
HomeContract.HomeView {
private static final String TAG = "HomeFragment";
Unbinder unbinder;
@BindView(R.id.home_toolbar)
Toolbar toolbar;
@BindView(R.id.appbar)
AppBarLayout appbar;
@BindView(R.id.image)
ImageView imageView;
@BindView(R.id.user_image)
CircularImageView userImage;
@BindView(R.id.collapsing_toolbar)
CollapsingToolbarLayout toolbarLayout;
@BindView(R.id.recycler_view)
RecyclerView recentArtistRV;
@BindView(R.id.recent_album)
RecyclerView recentAlbumRV;
@BindView(R.id.top_artist)
RecyclerView topArtistRV;
@BindView(R.id.top_album)
MetalRecyclerViewPager topAlbumRV;
@BindView(R.id.recent_artist_container)
View recentArtistContainer;
@BindView(R.id.recent_albums_container)
View recentAlbumsContainer;
@BindView(R.id.top_artist_container)
View topArtistContainer;
@BindView(R.id.top_albums_container)
View topAlbumContainer;
@BindView(R.id.genres)
RecyclerView genresRecyclerView;
@BindView(R.id.genre_container)
LinearLayout genreContainer;
@BindView(R.id.container)
View container;
@BindView(R.id.title)
TextView title;
@BindView(R.id.search)
ImageView search;
private HomePresenter homePresenter;
private CompositeDisposable disposable;
public static HomeFragment newInstance() {
Bundle args = new Bundle();
HomeFragment fragment = new HomeFragment();
fragment.setArguments(args);
return fragment;
}
private void getTimeOfTheDay() {
Calendar c = Calendar.getInstance();
int timeOfDay = c.get(Calendar.HOUR_OF_DAY);
String[] images = new String[]{};
if (timeOfDay >= 0 && timeOfDay < 6) {
images = getResources().getStringArray(R.array.night);
} else if (timeOfDay >= 6 && timeOfDay < 12) {
images = getResources().getStringArray(R.array.morning);
} else if (timeOfDay >= 12 && timeOfDay < 16) {
images = getResources().getStringArray(R.array.after_noon);
} else if (timeOfDay >= 16 && timeOfDay < 20) {
images = getResources().getStringArray(R.array.evening);
} else if (timeOfDay >= 20 && timeOfDay < 24) {
images = getResources().getStringArray(R.array.night);
}
String day = images[new Random().nextInt(images.length)];
loadTimeImage(day);
}
private void loadTimeImage(String day) {
//noinspection ConstantConditions
if (PreferenceUtil.getInstance(getActivity()).getBannerImage().isEmpty()) {
if (imageView != null) {
Glide.with(getActivity()).load(day)
.asBitmap()
.placeholder(R.drawable.material_design_default)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.into(imageView);
}
} else {
loadBannerFromStorage();
}
}
private void loadBannerFromStorage() {
//noinspection ConstantConditions
disposable.add(new Compressor(getContext())
.setQuality(100)
.setCompressFormat(Bitmap.CompressFormat.WEBP)
.compressToBitmapAsFlowable(
new File(PreferenceUtil.getInstance(getContext()).getBannerImage(), USER_BANNER))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(imageView::setImageBitmap));
}
private void loadImageFromStorage(ImageView imageView) {
//noinspection ConstantConditions
disposable.add(new Compressor(getContext())
.setMaxHeight(300)
.setMaxWidth(300)
.setQuality(75)
.setCompressFormat(Bitmap.CompressFormat.WEBP)
.compressToBitmapAsFlowable(
new File(PreferenceUtil.getInstance(getContext()).getProfileImage(), USER_PROFILE))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(imageView::setImageBitmap,
throwable -> imageView.setImageDrawable(ContextCompat
.getDrawable(getContext(), R.drawable.ic_person_flat))));
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
disposable = new CompositeDisposable();
//noinspection ConstantConditions
homePresenter = new HomePresenter(this);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getMainActivity().getSlidingUpPanelLayout().setShadowHeight(8);
getMainActivity().setBottomBarVisibility(View.VISIBLE);
setupToolbar();
loadImageFromStorage(userImage);
homePresenter.subscribe();
checkPadding();
getTimeOfTheDay();
}
@SuppressWarnings("ConstantConditions")
private void setupToolbar() {
if (!PreferenceUtil.getInstance(getContext()).getFullScreenMode()) {
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) toolbar
.getLayoutParams();
params.topMargin = RetroUtil.getStatusBarHeight(getContext());
toolbar.setLayoutParams(params);
}
appbar.addOnOffsetChangedListener(new AppBarStateChangeListener() {
@Override
public void onStateChanged(AppBarLayout appBarLayout, State state) {
int color;
switch (state) {
case COLLAPSED:
getMainActivity().setLightStatusbar(!ATHUtil.isWindowBackgroundDark(getContext()));
color = ThemeStore.textColorPrimary(getContext());
break;
default:
case EXPANDED:
case IDLE:
getMainActivity().setLightStatusbar(false);
color = ContextCompat.getColor(getContext(), R.color.md_white_1000);
break;
}
TintHelper.setTintAuto(search, color, false);
title.setTextColor(color);
}
});
int primaryColor = ThemeStore.primaryColor(getContext());
TintHelper.setTintAuto(container, primaryColor, true);
toolbarLayout.setStatusBarScrimColor(primaryColor);
toolbarLayout.setContentScrimColor(primaryColor);
toolbar.setTitle(R.string.home);
getMainActivity().setSupportActionBar(toolbar);
}
@Override
public boolean handleBackPress() {
return false;
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
disposable.clear();
homePresenter.unsubscribe();
}
@Override
public void loading() {
}
@Override
public void showEmptyView() {
}
@Override
public void completed() {
}
@Override
public void showData(ArrayList<Object> homes) {
//homeAdapter.swapDataSet(homes);
}
@Override
public void onMediaStoreChanged() {
super.onMediaStoreChanged();
homePresenter.subscribe();
}
@Override
public void onServiceConnected() {
super.onServiceConnected();
checkPadding();
}
@Override
public void onQueueChanged() {
super.onQueueChanged();
checkPadding();
}
private void checkPadding() {
int height = getResources().getDimensionPixelSize(R.dimen.mini_player_height);
container.setPadding(0, 0, 0, MusicPlayerRemote.getPlayingQueue().isEmpty() ? height * 2 : 0);
}
@Override
public void recentArtist(ArrayList<Artist> artists) {
recentArtistContainer.setVisibility(View.VISIBLE);
recentArtistRV.setLayoutManager(new GridLayoutManager(getMainActivity(),
1, GridLayoutManager.HORIZONTAL, false));
ArtistAdapter artistAdapter = new ArtistAdapter(getMainActivity(), artists,
R.layout.item_artist, false, null);
recentArtistRV.setAdapter(artistAdapter);
}
@Override
public void recentAlbum(ArrayList<Album> albums) {
recentAlbumsContainer.setVisibility(View.VISIBLE);
AlbumFullWithAdapter artistAdapter = new AlbumFullWithAdapter(getMainActivity(),
getDisplayMetrics());
artistAdapter.swapData(albums);
recentAlbumRV.setAdapter(artistAdapter);
}
@Override
public void topArtists(ArrayList<Artist> artists) {
topArtistContainer.setVisibility(View.VISIBLE);
topArtistRV.setLayoutManager(new GridLayoutManager(getMainActivity(),
1, GridLayoutManager.HORIZONTAL, false));
ArtistAdapter artistAdapter = new ArtistAdapter(getMainActivity(), artists,
R.layout.item_artist, false, null);
topArtistRV.setAdapter(artistAdapter);
}
@Override
public void topAlbums(ArrayList<Album> albums) {
topAlbumContainer.setVisibility(View.VISIBLE);
AlbumFullWithAdapter artistAdapter = new AlbumFullWithAdapter(getMainActivity(),
getDisplayMetrics());
artistAdapter.swapData(albums);
topAlbumRV.setAdapter(artistAdapter);
}
private DisplayMetrics getDisplayMetrics() {
Display display = getMainActivity().getWindowManager().getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
return metrics;
}
@Override
public void suggestions(ArrayList<Playlist> playlists) {
}
@Override
public void geners(ArrayList<Genre> genres) {
genreContainer.setVisibility(View.VISIBLE);
genresRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
//noinspection ConstantConditions
GenreAdapter genreAdapter = new GenreAdapter(getActivity(), genres, R.layout.item_list);
genresRecyclerView.setAdapter(genreAdapter);
}
@OnClick({R.id.last_added, R.id.top_played, R.id.action_shuffle, R.id.history,
R.id.user_image, R.id.search})
void startUserInfo(View view) {
Activity activity = getActivity();
if (activity != null) {
switch (view.getId()) {
case R.id.action_shuffle:
MusicPlayerRemote
.openAndShuffleQueue(SongLoader.getAllSongs(activity).blockingFirst(), true);
break;
case R.id.last_added:
NavigationUtil.goToPlaylistNew(activity, new LastAddedPlaylist(activity));
break;
case R.id.top_played:
NavigationUtil.goToPlaylistNew(activity, new MyTopTracksPlaylist(activity));
break;
case R.id.history:
NavigationUtil.goToPlaylistNew(activity, new HistoryPlaylist(activity));
break;
case R.id.search:
NavigationUtil.goToSearch(activity);
break;
case R.id.user_image:
new HomeOptionDialog().show(getFragmentManager(), TAG);
break;
}
}
}
@Override
public void onPlayingMetaChanged() {
super.onPlayingMetaChanged();
homePresenter.loadRecentArtists();
homePresenter.loadRecentAlbums();
}
}

View file

@ -0,0 +1,154 @@
package code.name.monkey.retromusic.ui.fragments.player;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.transform.CustPagerTransformer;
import code.name.monkey.retromusic.transform.NormalPageTransformer;
import code.name.monkey.retromusic.transform.ParallaxPagerTransformer;
import code.name.monkey.retromusic.ui.adapter.album.AlbumCoverPagerAdapter;
import code.name.monkey.retromusic.ui.fragments.NowPlayingScreen;
import code.name.monkey.retromusic.ui.fragments.base.AbsMusicServiceFragment;
import code.name.monkey.retromusic.util.PreferenceUtil;
public class PlayerAlbumCoverFragment extends AbsMusicServiceFragment implements
ViewPager.OnPageChangeListener {
public static final String TAG = PlayerAlbumCoverFragment.class.getSimpleName();
public static final long VISIBILITY_ANIM_DURATION = 300;
@BindView(R.id.player_album_cover_viewpager)
ViewPager viewPager;
private Unbinder unbinder;
private Callbacks callbacks;
private int currentPosition;
private AlbumCoverPagerAdapter.AlbumCoverFragment.ColorReceiver colorReceiver =
new AlbumCoverPagerAdapter.AlbumCoverFragment.ColorReceiver() {
@Override
public void onColorReady(int color, int requestCode) {
if (currentPosition == requestCode) {
notifyColorChange(color);
}
}
};
public void removeSlideEffect() {
ParallaxPagerTransformer transformer = new ParallaxPagerTransformer(R.id.player_image);
transformer.setSpeed(0.3f);
viewPager.setPageTransformer(true, transformer);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_player_album_cover, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
viewPager.addOnPageChangeListener(this);
//noinspection ConstantConditions
if (PreferenceUtil.getInstance(getContext()).carouselEffect() && !(
(PreferenceUtil.getInstance(getContext()).getNowPlayingScreen() == NowPlayingScreen.FULL) ||
(PreferenceUtil.getInstance(getContext()).getNowPlayingScreen()
== NowPlayingScreen.FLAT))) {
viewPager.setClipToPadding(false);
viewPager.setPadding(96, 0, 96, 0);
viewPager.setPageMargin(18);
viewPager.setPageTransformer(false, new CustPagerTransformer(getContext()));
} else {
viewPager.setPageTransformer(true, new NormalPageTransformer());
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
viewPager.removeOnPageChangeListener(this);
unbinder.unbind();
}
@Override
public void onServiceConnected() {
updatePlayingQueue();
}
@Override
public void onPlayingMetaChanged() {
viewPager.setCurrentItem(MusicPlayerRemote.getPosition());
}
@Override
public void onQueueChanged() {
updatePlayingQueue();
}
private void updatePlayingQueue() {
viewPager.setAdapter(
new AlbumCoverPagerAdapter(getFragmentManager(), MusicPlayerRemote.getPlayingQueue()));
//noinspection ConstantConditions
viewPager.getAdapter().notifyDataSetChanged();
viewPager.setCurrentItem(MusicPlayerRemote.getPosition());
onPageSelected(MusicPlayerRemote.getPosition());
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
currentPosition = position;
if (viewPager.getAdapter() != null) {
((AlbumCoverPagerAdapter) viewPager.getAdapter()).receiveColor(colorReceiver, position);
}
if (position != MusicPlayerRemote.getPosition()) {
MusicPlayerRemote.playSongAt(position);
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
private void notifyColorChange(int color) {
if (callbacks != null) {
callbacks.onColorChanged(color);
}
}
public void setCallbacks(Callbacks listener) {
callbacks = listener;
}
public void removeEffect() {
viewPager.setPageTransformer(false, null);
}
public interface Callbacks {
void onColorChanged(int color);
void onFavoriteToggled();
}
}

View file

@ -0,0 +1,165 @@
package code.name.monkey.retromusic.ui.fragments.player.adaptive;
import android.os.Bundle;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerFragment;
import code.name.monkey.retromusic.ui.fragments.player.PlayerAlbumCoverFragment;
import code.name.monkey.retromusic.ui.fragments.player.PlayerAlbumCoverFragment.Callbacks;
import code.name.monkey.retromusic.ui.fragments.player.normal.PlayerFragment;
public class AdaptiveFragment extends AbsPlayerFragment implements Callbacks {
@BindView(R.id.player_toolbar)
Toolbar toolbar;
@BindView(R.id.status_bar)
View statusBar;
private int lastColor;
private AdaptivePlaybackControlsFragment playbackControlsFragment;
private Unbinder unbinder;
public static PlayerFragment newInstance() {
Bundle args = new Bundle();
PlayerFragment fragment = new PlayerFragment();
fragment.setArguments(args);
return fragment;
}
@Override
@ColorInt
public int getPaletteColor() {
return lastColor;
}
@Override
public void onShow() {
playbackControlsFragment.show();
}
@Override
public void onHide() {
playbackControlsFragment.hide();
onBackPressed();
}
@Override
public boolean onBackPressed() {
return false;
}
@Override
public Toolbar getToolbar() {
return toolbar;
}
@Override
public int toolbarIconColor() {
return ATHUtil.resolveColor(getContext(), R.attr.iconColor);
}
@Override
public void onColorChanged(int color) {
playbackControlsFragment.setDark(color);
lastColor = color;
getCallbacks().onPaletteColorChanged();
ToolbarContentTintHelper.colorizeToolbar(toolbar,
ATHUtil.resolveColor(getContext(), R.attr.iconColor), getActivity());
}
@Override
protected void toggleFavorite(Song song) {
super.toggleFavorite(song);
if (song.id == MusicPlayerRemote.getCurrentSong().id) {
updateIsFavorite();
}
}
@Override
public void onFavoriteToggled() {
toggleFavorite(MusicPlayerRemote.getCurrentSong());
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_adaptive_player, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
toggleStatusBar(statusBar);
setUpSubFragments();
setUpPlayerToolbar();
}
private void setUpSubFragments() {
playbackControlsFragment =
(AdaptivePlaybackControlsFragment) getChildFragmentManager()
.findFragmentById(R.id.playback_controls_fragment);
PlayerAlbumCoverFragment playerAlbumCoverFragment =
(PlayerAlbumCoverFragment) getChildFragmentManager()
.findFragmentById(R.id.player_album_cover_fragment);
playerAlbumCoverFragment.setCallbacks(this);
playerAlbumCoverFragment.removeSlideEffect();
}
private void setUpPlayerToolbar() {
int primaryColor = ATHUtil.resolveColor(getContext(), R.attr.iconColor);
toolbar.inflateMenu(R.menu.menu_player);
toolbar.setNavigationOnClickListener(v -> getActivity().onBackPressed());
toolbar.setOnMenuItemClickListener(this);
ToolbarContentTintHelper.colorizeToolbar(toolbar, primaryColor, getActivity());
toolbar.setTitleTextColor(primaryColor);
toolbar.setSubtitleTextColor(ThemeStore.textColorSecondary(getContext()));
}
@Override
public void onServiceConnected() {
updateIsFavorite();
updateSong();
}
private void updateSong() {
Song song = MusicPlayerRemote.getCurrentSong();
toolbar.setTitle(song.title);
toolbar.setSubtitle(song.artistName);
}
@Override
public void onPlayingMetaChanged() {
updateIsFavorite();
updateSong();
}
}

View file

@ -0,0 +1,313 @@
package code.name.monkey.retromusic.ui.fragments.player.adaptive;
import android.animation.ObjectAnimator;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.AppCompatSeekBar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper;
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler;
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener;
import code.name.monkey.retromusic.service.MusicService;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerControlsFragment;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.views.PlayPauseDrawable;
public class AdaptivePlaybackControlsFragment extends AbsPlayerControlsFragment {
@BindView(R.id.player_play_pause_button)
ImageButton playPauseButton;
@BindView(R.id.player_prev_button)
ImageButton prevButton;
@BindView(R.id.player_next_button)
ImageButton nextButton;
@BindView(R.id.player_repeat_button)
ImageButton repeatButton;
@BindView(R.id.player_shuffle_button)
ImageButton shuffleButton;
@BindView(R.id.player_progress_slider)
AppCompatSeekBar progressSlider;
@BindView(R.id.player_song_total_time)
TextView songTotalTime;
@BindView(R.id.player_song_current_progress)
TextView songCurrentProgress;
@BindView(R.id.volume_fragment_container)
View volumeContainer;
private Unbinder unbinder;
private PlayPauseDrawable playPauseDrawable;
private int lastPlaybackControlsColor;
private int lastDisabledPlaybackControlsColor;
private MusicProgressViewUpdateHelper progressViewUpdateHelper;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressViewUpdateHelper = new MusicProgressViewUpdateHelper(this);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater
.inflate(R.layout.fragment_adaptive_player_playback_controls, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
unbinder = ButterKnife.bind(this, view);
setUpMusicControllers();
hideVolumeIfAvailable();
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Override
public void onResume() {
super.onResume();
progressViewUpdateHelper.start();
}
@Override
public void onPause() {
super.onPause();
progressViewUpdateHelper.stop();
}
@Override
public void onServiceConnected() {
updatePlayPauseDrawableState(false);
updateRepeatState();
updateShuffleState();
}
@Override
public void onPlayStateChanged() {
updatePlayPauseDrawableState(true);
}
@Override
public void onRepeatModeChanged() {
updateRepeatState();
}
@Override
public void onShuffleModeChanged() {
updateShuffleState();
}
@Override
public void setDark(int dark) {
if (ColorUtil.isColorLight(ATHUtil.resolveColor(getContext(), android.R.attr.windowBackground))) {
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(getActivity(), true);
lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(getActivity(), true);
} else {
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(getActivity(), false);
lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(getActivity(), false);
}
updateRepeatState();
updateShuffleState();
updatePrevNextColor();
updatePlayPauseColor();
TintHelper.setTintAuto(playPauseButton, MaterialValueHelper.getPrimaryTextColor(getContext(), ColorUtil.isColorLight(dark)), false);
TintHelper.setTintAuto(playPauseButton, dark, true);
TintHelper.setTintAuto(progressSlider, dark, false);
}
private void updatePlayPauseColor() {
//playPauseButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
}
private void setUpPlayPauseButton() {
playPauseDrawable = new PlayPauseDrawable(getActivity());
playPauseButton.setImageDrawable(playPauseDrawable);
updatePlayPauseColor();
playPauseButton.setOnClickListener(new PlayPauseButtonOnClickHandler());
playPauseButton.post(() -> {
if (playPauseButton != null) {
playPauseButton.setPivotX(playPauseButton.getWidth() / 2);
playPauseButton.setPivotY(playPauseButton.getHeight() / 2);
}
});
}
protected void updatePlayPauseDrawableState(boolean animate) {
if (MusicPlayerRemote.isPlaying()) {
playPauseDrawable.setPause(animate);
} else {
playPauseDrawable.setPlay(animate);
}
}
private void setUpMusicControllers() {
setUpPlayPauseButton();
setUpPrevNext();
setUpRepeatButton();
setUpShuffleButton();
setUpProgressSlider();
}
private void setUpPrevNext() {
updatePrevNextColor();
nextButton.setOnClickListener(v -> MusicPlayerRemote.playNextSong());
prevButton.setOnClickListener(v -> MusicPlayerRemote.back());
}
private void updatePrevNextColor() {
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
prevButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
}
private void setUpShuffleButton() {
shuffleButton.setOnClickListener(v -> MusicPlayerRemote.toggleShuffleMode());
}
@Override
protected void updateShuffleState() {
switch (MusicPlayerRemote.getShuffleMode()) {
case MusicService.SHUFFLE_MODE_SHUFFLE:
shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
default:
shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
private void setUpRepeatButton() {
repeatButton.setOnClickListener(v -> MusicPlayerRemote.cycleRepeatMode());
}
@Override
protected void updateRepeatState() {
switch (MusicPlayerRemote.getRepeatMode()) {
case MusicService.REPEAT_MODE_NONE:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_ALL:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_THIS:
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp);
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
@Override
protected void show() {
//Ignore
}
@Override
protected void hide() {
//Ignore
}
@Override
protected void setUpProgressSlider() {
progressSlider.setOnSeekBarChangeListener(new SimpleOnSeekbarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
MusicPlayerRemote.seekTo(progress);
onUpdateProgressViews(MusicPlayerRemote.getSongProgressMillis(),
MusicPlayerRemote.getSongDurationMillis());
}
}
});
}
public void showBouceAnimation() {
playPauseButton.clearAnimation();
playPauseButton.setScaleX(0.9f);
playPauseButton.setScaleY(0.9f);
playPauseButton.setVisibility(View.VISIBLE);
playPauseButton.setPivotX(playPauseButton.getWidth() / 2);
playPauseButton.setPivotY(playPauseButton.getHeight() / 2);
playPauseButton.animate()
.setDuration(200)
.setInterpolator(new DecelerateInterpolator())
.scaleX(1.1f)
.scaleY(1.1f)
.withEndAction(() -> playPauseButton.animate()
.setDuration(200)
.setInterpolator(new AccelerateInterpolator())
.scaleX(1f)
.scaleY(1f)
.alpha(1f)
.start())
.start();
}
@OnClick(R.id.player_play_pause_button)
void showAnimation() {
if (MusicPlayerRemote.isPlaying()) {
MusicPlayerRemote.pauseSong();
} else {
MusicPlayerRemote.resumePlaying();
}
showBouceAnimation();
}
@Override
public void onUpdateProgressViews(int progress, int total) {
progressSlider.setMax(total);
ObjectAnimator animator = ObjectAnimator.ofInt(progressSlider, "progress", progress);
animator.setDuration(1500);
animator.setInterpolator(new LinearInterpolator());
animator.start();
songTotalTime.setText(MusicUtil.getReadableDurationString(total));
songCurrentProgress.setText(MusicUtil.getReadableDurationString(progress));
}
public void hideVolumeIfAvailable() {
volumeContainer.setVisibility(
PreferenceUtil.getInstance(getContext()).getVolumeToggle() ? View.VISIBLE : View.GONE);
}
}

View file

@ -0,0 +1,301 @@
package code.name.monkey.retromusic.ui.fragments.player.blur;
import android.animation.ObjectAnimator;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.AppCompatSeekBar;
import android.support.v7.widget.AppCompatTextView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper;
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler;
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.service.MusicService;
import code.name.monkey.retromusic.ui.fragments.VolumeFragment;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerControlsFragment;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.views.PlayPauseDrawable;
public class BlurPlaybackControlsFragment extends AbsPlayerControlsFragment {
@BindView(R.id.player_play_pause_button)
ImageButton playPauseFab;
@BindView(R.id.player_prev_button)
ImageButton prevButton;
@BindView(R.id.player_next_button)
ImageButton nextButton;
@BindView(R.id.player_repeat_button)
ImageButton repeatButton;
@BindView(R.id.player_shuffle_button)
ImageButton shuffleButton;
@BindView(R.id.player_progress_slider)
AppCompatSeekBar progressSlider;
@BindView(R.id.player_song_total_time)
TextView songTotalTime;
@BindView(R.id.player_song_current_progress)
TextView songCurrentProgress;
@BindView(R.id.title)
AppCompatTextView title;
@BindView(R.id.text)
TextView text;
@BindView(R.id.volume_fragment_container)
View mVolumeContainer;
private Unbinder unbinder;
private PlayPauseDrawable playerFabPlayPauseDrawable;
private int lastPlaybackControlsColor;
private int lastDisabledPlaybackControlsColor;
private MusicProgressViewUpdateHelper progressViewUpdateHelper;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressViewUpdateHelper = new MusicProgressViewUpdateHelper(this);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_blur_playback_controls, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
unbinder = ButterKnife.bind(this, view);
setUpMusicControllers();
mVolumeContainer.setVisibility(PreferenceUtil.getInstance(getContext()).getVolumeToggle() ? View.VISIBLE : View.GONE);
VolumeFragment mVolumeFragment = (VolumeFragment) getChildFragmentManager().findFragmentById(R.id.volume_fragment);
mVolumeFragment.tintWhiteColor();
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
private void updateSong() {
Song song = MusicPlayerRemote.getCurrentSong();
title.setText(song.title);
text.setText(song.artistName);
}
@Override
public void onResume() {
super.onResume();
progressViewUpdateHelper.start();
}
@Override
public void onPause() {
super.onPause();
progressViewUpdateHelper.stop();
}
@Override
public void onServiceConnected() {
updatePlayPauseDrawableState(false);
updateRepeatState();
updateShuffleState();
updateSong();
}
@Override
public void onPlayingMetaChanged() {
super.onPlayingMetaChanged();
updateSong();
}
@Override
public void onPlayStateChanged() {
updatePlayPauseDrawableState(true);
}
@Override
public void onRepeatModeChanged() {
updateRepeatState();
}
@Override
public void onShuffleModeChanged() {
updateShuffleState();
}
@Override
public void setDark(int dark) {
lastPlaybackControlsColor = Color.WHITE;
lastDisabledPlaybackControlsColor = ContextCompat.getColor(getContext(), R.color.md_grey_500);
setProgressBarColor(Color.WHITE);
songCurrentProgress.setTextColor(lastPlaybackControlsColor);
songTotalTime.setTextColor(lastPlaybackControlsColor);
updateRepeatState();
updateShuffleState();
updatePrevNextColor();
}
public void setProgressBarColor(int newColor) {
TintHelper.setTintAuto(progressSlider, newColor, false);
}
private void setUpPlayPauseFab() {
final int fabColor = Color.WHITE;
TintHelper.setTintAuto(playPauseFab, fabColor, true);
playerFabPlayPauseDrawable = new PlayPauseDrawable(getActivity());
playPauseFab.setImageDrawable(playerFabPlayPauseDrawable); // Note: set the drawable AFTER TintHelper.setTintAuto() was called
playPauseFab.setColorFilter(MaterialValueHelper.getPrimaryTextColor(getContext(), ColorUtil.isColorLight(fabColor)), PorterDuff.Mode.SRC_IN);
playPauseFab.setOnClickListener(new PlayPauseButtonOnClickHandler());
playPauseFab.post(() -> {
if (playPauseFab != null) {
playPauseFab.setPivotX(playPauseFab.getWidth() / 2);
playPauseFab.setPivotY(playPauseFab.getHeight() / 2);
}
});
}
protected void updatePlayPauseDrawableState(boolean animate) {
if (MusicPlayerRemote.isPlaying()) {
playerFabPlayPauseDrawable.setPause(animate);
} else {
playerFabPlayPauseDrawable.setPlay(animate);
}
}
private void setUpMusicControllers() {
setUpPlayPauseFab();
setUpPrevNext();
setUpRepeatButton();
setUpShuffleButton();
setUpProgressSlider();
}
private void setUpPrevNext() {
updatePrevNextColor();
nextButton.setOnClickListener(v -> MusicPlayerRemote.playNextSong());
prevButton.setOnClickListener(v -> MusicPlayerRemote.back());
}
private void updatePrevNextColor() {
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
prevButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
}
private void setUpShuffleButton() {
shuffleButton.setOnClickListener(v -> MusicPlayerRemote.toggleShuffleMode());
}
@Override
protected void updateShuffleState() {
switch (MusicPlayerRemote.getShuffleMode()) {
case MusicService.SHUFFLE_MODE_SHUFFLE:
shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
default:
shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
private void setUpRepeatButton() {
repeatButton.setOnClickListener(v -> MusicPlayerRemote.cycleRepeatMode());
}
@Override
protected void updateRepeatState() {
switch (MusicPlayerRemote.getRepeatMode()) {
case MusicService.REPEAT_MODE_NONE:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_ALL:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_THIS:
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp);
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
@Override
protected void show() {
playPauseFab.animate()
.scaleX(1f)
.scaleY(1f)
.rotation(360f)
.setInterpolator(new DecelerateInterpolator())
.start();
}
@Override
protected void hide() {
if (playPauseFab != null) {
playPauseFab.setScaleX(0f);
playPauseFab.setScaleY(0f);
playPauseFab.setRotation(0f);
}
}
@Override
protected void setUpProgressSlider() {
progressSlider.setOnSeekBarChangeListener(new SimpleOnSeekbarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
MusicPlayerRemote.seekTo(progress);
onUpdateProgressViews(MusicPlayerRemote.getSongProgressMillis(), MusicPlayerRemote.getSongDurationMillis());
}
}
});
}
@Override
public void onUpdateProgressViews(int progress, int total) {
progressSlider.setMax(total);
ObjectAnimator animator = ObjectAnimator.ofInt(progressSlider, "progress", progress);
animator.setDuration(1500);
animator.setInterpolator(new LinearInterpolator());
animator.start();
songTotalTime.setText(MusicUtil.getReadableDurationString(total));
songCurrentProgress.setText(MusicUtil.getReadableDurationString(progress));
}
public void hideVolumeIfAvailable() {
mVolumeContainer.setVisibility(View.GONE);
}
}

View file

@ -0,0 +1,315 @@
package code.name.monkey.retromusic.ui.fragments.player.blur;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.h6ah4i.android.widget.advrecyclerview.animator.GeneralItemAnimator;
import com.h6ah4i.android.widget.advrecyclerview.animator.RefactoredDefaultItemAnimator;
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager;
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget;
import code.name.monkey.retromusic.glide.SongGlideRequest;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.ui.adapter.song.PlayingQueueAdapter;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerFragment;
import code.name.monkey.retromusic.ui.fragments.player.PlayerAlbumCoverFragment;
import code.name.monkey.retromusic.ui.fragments.player.normal.PlayerFragment;
import jp.wasabeef.glide.transformations.BlurTransformation;
/**
* @author Hemanth S (h4h13).
*/
public class BlurPlayerFragment extends AbsPlayerFragment implements PlayerAlbumCoverFragment.Callbacks {
@BindView(R.id.player_toolbar)
Toolbar toolbar;
@BindView(R.id.toolbar_container)
View toolbarContainer;
@BindView(R.id.gradient_background)
ImageView colorBackground;
@BindView(R.id.status_bar)
View statusBar;
@Nullable
@BindView(R.id.recycler_view)
RecyclerView recyclerView;
@Nullable
@BindView(R.id.title)
TextView title;
private int lastColor;
private BlurPlaybackControlsFragment playbackControlsFragment;
private Unbinder unbinder;
private RecyclerView.Adapter wrappedAdapter;
private RecyclerViewDragDropManager recyclerViewDragDropManager;
private PlayingQueueAdapter playingQueueAdapter;
private LinearLayoutManager layoutManager;
public static PlayerFragment newInstance() {
Bundle args = new Bundle();
PlayerFragment fragment = new PlayerFragment();
fragment.setArguments(args);
return fragment;
}
@Override
@ColorInt
public int getPaletteColor() {
return lastColor;
}
@Override
public void onShow() {
playbackControlsFragment.show();
}
@Override
public void onHide() {
playbackControlsFragment.hide();
onBackPressed();
}
@Override
public boolean onBackPressed() {
return false;
}
@Override
public Toolbar getToolbar() {
return toolbar;
}
@Override
public int toolbarIconColor() {
return Color.WHITE;
}
@Override
public void onColorChanged(int color) {
playbackControlsFragment.setDark(color);
lastColor = color;
getCallbacks().onPaletteColorChanged();
ToolbarContentTintHelper.colorizeToolbar(toolbar, Color.WHITE, getActivity());
if (title != null && playingQueueAdapter != null) {
if (ColorUtil.isColorLight(color)) {
title.setTextColor(Color.BLACK);
playingQueueAdapter.usePalette(false);
} else {
title.setTextColor(Color.WHITE);
playingQueueAdapter.usePalette(true);
}
}
}
@Override
protected void toggleFavorite(Song song) {
super.toggleFavorite(song);
if (song.id == MusicPlayerRemote.getCurrentSong().id) {
updateIsFavorite();
}
}
@Override
public void onFavoriteToggled() {
toggleFavorite(MusicPlayerRemote.getCurrentSong());
}
@Override
public void onDestroyView() {
super.onDestroyView();
if (recyclerViewDragDropManager != null) {
recyclerViewDragDropManager.release();
recyclerViewDragDropManager = null;
}
if (recyclerView != null) {
recyclerView.setItemAnimator(null);
recyclerView.setAdapter(null);
recyclerView = null;
}
if (wrappedAdapter != null) {
WrapperAdapterUtils.releaseAll(wrappedAdapter);
wrappedAdapter = null;
}
playingQueueAdapter = null;
layoutManager = null;
super.onDestroyView();
unbinder.unbind();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_blur, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
toggleStatusBar(statusBar);
setUpSubFragments();
setUpPlayerToolbar();
}
private void setUpSubFragments() {
playbackControlsFragment = (BlurPlaybackControlsFragment) getChildFragmentManager()
.findFragmentById(R.id.playback_controls_fragment);
PlayerAlbumCoverFragment playerAlbumCoverFragment =
(PlayerAlbumCoverFragment) getChildFragmentManager()
.findFragmentById(R.id.player_album_cover_fragment);
playerAlbumCoverFragment.setCallbacks(this);
}
private void setUpPlayerToolbar() {
toolbar.inflateMenu(R.menu.menu_player);
toolbar.setNavigationOnClickListener(v -> getActivity().onBackPressed());
toolbar.setOnMenuItemClickListener(this);
ToolbarContentTintHelper.colorizeToolbar(toolbar, Color.WHITE, getActivity());
}
private void updateBlur() {
Activity activity = getActivity();
if (activity == null) {
return;
}
int blurAmount = PreferenceManager.getDefaultSharedPreferences(getContext()).getInt("blur_amount", 25);
colorBackground.clearColorFilter();
SongGlideRequest.Builder.from(Glide.with(activity), MusicPlayerRemote.getCurrentSong())
.checkIgnoreMediaStore(activity)
.generatePalette(activity)
.build()
.override(320, 480)
.transform(new BlurTransformation(getActivity(), blurAmount))
.into(new RetroMusicColoredTarget(colorBackground) {
@Override
public void onColorReady(int color) {
if (color == getDefaultFooterColor()) {
colorBackground.setColorFilter(color);
}
}
});
}
@Override
public void onServiceConnected() {
updateIsFavorite();
updateBlur();
setUpRecyclerView();
}
@Override
public void onPlayingMetaChanged() {
updateIsFavorite();
updateBlur();
updateQueuePosition();
}
private void setUpRecyclerView() {
if (recyclerView != null) {
recyclerViewDragDropManager = new RecyclerViewDragDropManager();
final GeneralItemAnimator animator = new RefactoredDefaultItemAnimator();
playingQueueAdapter = new PlayingQueueAdapter(
(AppCompatActivity) getActivity(),
MusicPlayerRemote.getPlayingQueue(),
MusicPlayerRemote.getPosition(),
R.layout.item_song,
false,
null);
wrappedAdapter = recyclerViewDragDropManager.createWrappedAdapter(playingQueueAdapter);
layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(wrappedAdapter);
recyclerView.setItemAnimator(animator);
recyclerViewDragDropManager.attachRecyclerView(recyclerView);
layoutManager.scrollToPositionWithOffset(MusicPlayerRemote.getPosition() + 1, 0);
}
}
@Override
public void onQueueChanged() {
updateQueue();
updateCurrentSong();
}
@Override
public void onMediaStoreChanged() {
updateQueue();
updateCurrentSong();
}
@SuppressWarnings("ConstantConditions")
private void updateCurrentSong() {
}
private void updateQueuePosition() {
if (playingQueueAdapter != null) {
playingQueueAdapter.setCurrent(MusicPlayerRemote.getPosition());
// if (slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) {
resetToCurrentPosition();
//}
}
}
private void updateQueue() {
if (playingQueueAdapter != null) {
playingQueueAdapter.swapDataSet(MusicPlayerRemote.getPlayingQueue(), MusicPlayerRemote.getPosition());
resetToCurrentPosition();
}
}
private void resetToCurrentPosition() {
if (recyclerView != null) {
recyclerView.stopScroll();
layoutManager.scrollToPositionWithOffset(MusicPlayerRemote.getPosition() + 1, 0);
}
}
@Override
public void onPause() {
if (recyclerViewDragDropManager != null) {
recyclerViewDragDropManager.cancelDrag();
}
super.onPause();
}
}

View file

@ -0,0 +1,283 @@
package code.name.monkey.retromusic.ui.fragments.player.card;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.h6ah4i.android.widget.advrecyclerview.animator.GeneralItemAnimator;
import com.h6ah4i.android.widget.advrecyclerview.animator.RefactoredDefaultItemAnimator;
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager;
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.ui.adapter.song.PlayingQueueAdapter;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerFragment;
import code.name.monkey.retromusic.ui.fragments.player.PlayerAlbumCoverFragment;
import code.name.monkey.retromusic.ui.fragments.player.normal.PlayerFragment;
public class CardFragment extends AbsPlayerFragment implements PlayerAlbumCoverFragment.Callbacks {
@BindView(R.id.player_toolbar)
Toolbar toolbar;
@BindView(R.id.status_bar)
View statusBar;
@Nullable
@BindView(R.id.recycler_view)
RecyclerView recyclerView;
@Nullable
@BindView(R.id.title)
TextView title;
private RecyclerView.Adapter wrappedAdapter;
private RecyclerViewDragDropManager recyclerViewDragDropManager;
private PlayingQueueAdapter playingQueueAdapter;
private LinearLayoutManager layoutManager;
private int lastColor;
private CardPlaybackControlsFragment playbackControlsFragment;
private Unbinder unbinder;
public static PlayerFragment newInstance() {
Bundle args = new Bundle();
PlayerFragment fragment = new PlayerFragment();
fragment.setArguments(args);
return fragment;
}
@Override
@ColorInt
public int getPaletteColor() {
return lastColor;
}
@Override
public void onShow() {
playbackControlsFragment.show();
}
@Override
public void onHide() {
playbackControlsFragment.hide();
onBackPressed();
}
@Override
public void onResume() {
super.onResume();
}
@Override
public boolean onBackPressed() {
return false;
}
@Override
public Toolbar getToolbar() {
return toolbar;
}
@Override
public int toolbarIconColor() {
return Color.WHITE;
}
@Override
public void onColorChanged(int color) {
playbackControlsFragment.setDark(color);
lastColor = color;
getCallbacks().onPaletteColorChanged();
ToolbarContentTintHelper.colorizeToolbar(toolbar, Color.WHITE, getActivity());
if (title != null && playingQueueAdapter != null) {
if (ColorUtil.isColorLight(color)) {
title.setTextColor(Color.BLACK);
playingQueueAdapter.usePalette(false);
} else {
title.setTextColor(Color.WHITE);
playingQueueAdapter.usePalette(true);
}
}
}
@Override
protected void toggleFavorite(Song song) {
super.toggleFavorite(song);
if (song.id == MusicPlayerRemote.getCurrentSong().id) {
updateIsFavorite();
}
}
@Override
public void onFavoriteToggled() {
toggleFavorite(MusicPlayerRemote.getCurrentSong());
}
@Override
public void onDestroyView() {
super.onDestroyView();
if (recyclerViewDragDropManager != null) {
recyclerViewDragDropManager.release();
recyclerViewDragDropManager = null;
}
if (recyclerView != null) {
recyclerView.setItemAnimator(null);
recyclerView.setAdapter(null);
recyclerView = null;
}
if (wrappedAdapter != null) {
WrapperAdapterUtils.releaseAll(wrappedAdapter);
wrappedAdapter = null;
}
playingQueueAdapter = null;
layoutManager = null;
super.onDestroyView();
unbinder.unbind();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_card_player, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
toggleStatusBar(statusBar);
setUpSubFragments();
setUpPlayerToolbar();
setUpRecyclerView();
}
private void setUpSubFragments() {
playbackControlsFragment =
(CardPlaybackControlsFragment) getChildFragmentManager()
.findFragmentById(R.id.playback_controls_fragment);
PlayerAlbumCoverFragment playerAlbumCoverFragment = (PlayerAlbumCoverFragment) getChildFragmentManager()
.findFragmentById(R.id.player_album_cover_fragment);
playerAlbumCoverFragment.setCallbacks(this);
playerAlbumCoverFragment.removeSlideEffect();
}
private void setUpPlayerToolbar() {
toolbar.inflateMenu(R.menu.menu_player);
toolbar.setNavigationOnClickListener(v -> getActivity().onBackPressed());
toolbar.setOnMenuItemClickListener(this);
ToolbarContentTintHelper.colorizeToolbar(toolbar, Color.WHITE, getActivity());
}
@Override
public void onServiceConnected() {
updateIsFavorite();
//updateLyrics();
setUpRecyclerView();
}
@Override
public void onPlayingMetaChanged() {
updateIsFavorite();
//updateLyrics();
updateQueuePosition();
}
private void setUpRecyclerView() {
if (recyclerView != null) {
recyclerViewDragDropManager = new RecyclerViewDragDropManager();
final GeneralItemAnimator animator = new RefactoredDefaultItemAnimator();
playingQueueAdapter = new PlayingQueueAdapter(
(AppCompatActivity) getActivity(),
MusicPlayerRemote.getPlayingQueue(),
MusicPlayerRemote.getPosition(),
R.layout.item_song,
false,
null);
wrappedAdapter = recyclerViewDragDropManager.createWrappedAdapter(playingQueueAdapter);
layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(wrappedAdapter);
recyclerView.setItemAnimator(animator);
recyclerViewDragDropManager.attachRecyclerView(recyclerView);
layoutManager.scrollToPositionWithOffset(MusicPlayerRemote.getPosition() + 1, 0);
}
}
@Override
public void onQueueChanged() {
updateQueue();
updateCurrentSong();
}
@Override
public void onMediaStoreChanged() {
updateQueue();
updateCurrentSong();
}
@SuppressWarnings("ConstantConditions")
private void updateCurrentSong() {
}
private void updateQueuePosition() {
if (playingQueueAdapter != null) {
playingQueueAdapter.setCurrent(MusicPlayerRemote.getPosition());
}
// if (slidingUpPanelLayout.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) {
resetToCurrentPosition();
//}
}
private void updateQueue() {
if (playingQueueAdapter != null) {
playingQueueAdapter.swapDataSet(MusicPlayerRemote.getPlayingQueue(),
MusicPlayerRemote.getPosition());
resetToCurrentPosition();
}
}
private void resetToCurrentPosition() {
if (recyclerView != null) {
recyclerView.stopScroll();
layoutManager.scrollToPositionWithOffset(MusicPlayerRemote.getPosition() + 1, 0);
}
}
@Override
public void onPause() {
if (recyclerViewDragDropManager != null) {
recyclerViewDragDropManager.cancelDrag();
}
super.onPause();
}
}

View file

@ -0,0 +1,358 @@
package code.name.monkey.retromusic.ui.fragments.player.card;
import android.animation.ObjectAnimator;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.AppCompatSeekBar;
import android.support.v7.widget.AppCompatTextView;
import android.support.v7.widget.CardView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper;
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler;
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.service.MusicService;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerControlsFragment;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.views.PlayPauseDrawable;
public class CardPlaybackControlsFragment extends AbsPlayerControlsFragment {
@BindView(R.id.player_play_pause_button)
ImageButton playPauseButton;
@BindView(R.id.player_prev_button)
ImageButton prevButton;
@BindView(R.id.player_next_button)
ImageButton nextButton;
@BindView(R.id.player_repeat_button)
ImageButton repeatButton;
@BindView(R.id.player_shuffle_button)
ImageButton shuffleButton;
@BindView(R.id.player_progress_slider)
AppCompatSeekBar progressSlider;
@BindView(R.id.player_song_total_time)
TextView songTotalTime;
@BindView(R.id.player_song_current_progress)
TextView songCurrentProgress;
@BindView(R.id.title)
AppCompatTextView title;
@BindView(R.id.text)
TextView text;
@BindView(R.id.volume_fragment_container)
View volumeContainer;
@BindView(R.id.menu)
View menuView;
@BindView(R.id.image_text_container)
CardView colorContainer;
@BindView(R.id.image)
ImageView playImageView;
@BindView(R.id.playback_controls)
View playbackControls;
private Unbinder unbinder;
private PlayPauseDrawable playPauseDrawable;
private int lastPlaybackControlsColor;
private int lastDisabledPlaybackControlsColor;
private MusicProgressViewUpdateHelper progressViewUpdateHelper;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressViewUpdateHelper = new MusicProgressViewUpdateHelper(this);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_card_player_playback_controls, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
unbinder = ButterKnife.bind(this, view);
setUpMusicControllers();
hideVolumeIfAvailable();
setupControls();
}
private void setupControls() {
playImageView.setImageResource(R.drawable.ic_play_circle_filled_white_24dp);
//noinspection ConstantConditions
int iconPadding = getActivity().getResources().getDimensionPixelSize(R.dimen.list_item_image_icon_padding);
playImageView.setPadding(iconPadding, iconPadding, iconPadding, iconPadding);
menuView.setVisibility(View.GONE);
int primaryColor = ThemeStore.primaryColor(getContext());
playbackControls.setBackgroundColor(primaryColor);
colorContainer.setCardBackgroundColor(primaryColor);
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
private void updateSong() {
Song song = MusicPlayerRemote.getCurrentSong();
title.setText(song.title);
text.setText(song.artistName);
}
@Override
public void onResume() {
super.onResume();
progressViewUpdateHelper.start();
}
@Override
public void onPause() {
super.onPause();
progressViewUpdateHelper.stop();
}
@Override
public void onServiceConnected() {
updatePlayPauseDrawableState(false);
updateRepeatState();
updateShuffleState();
updateSong();
}
@Override
public void onPlayingMetaChanged() {
super.onPlayingMetaChanged();
updateSong();
}
@Override
public void onPlayStateChanged() {
updatePlayPauseDrawableState(true);
}
@Override
public void onRepeatModeChanged() {
updateRepeatState();
}
@Override
public void onShuffleModeChanged() {
updateShuffleState();
}
@Override
public void setDark(int dark) {
playImageView.setColorFilter(dark, PorterDuff.Mode.SRC_IN);
if (ColorUtil.isColorLight(ATHUtil.resolveColor(getContext(), android.R.attr.windowBackground))) {
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(getActivity(), true);
lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(getActivity(), true);
} else {
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(getActivity(), false);
lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(getActivity(), false);
}
updateRepeatState();
updateShuffleState();
updatePrevNextColor();
updatePlayPauseColor();
updateProgressTextColor();
TintHelper.setTintAuto(playPauseButton, MaterialValueHelper.getPrimaryTextColor(getContext(), ColorUtil.isColorLight(dark)), false);
TintHelper.setTintAuto(playPauseButton, dark, true);
}
private void updatePlayPauseColor() {
//playPauseButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
}
private void setUpPlayPauseButton() {
playPauseDrawable = new PlayPauseDrawable(getActivity());
playPauseButton.setImageDrawable(playPauseDrawable);
updatePlayPauseColor();
playPauseButton.setOnClickListener(new PlayPauseButtonOnClickHandler());
playPauseButton.post(() -> {
if (playPauseButton != null) {
playPauseButton.setPivotX(playPauseButton.getWidth() / 2);
playPauseButton.setPivotY(playPauseButton.getHeight() / 2);
}
});
}
protected void updatePlayPauseDrawableState(boolean animate) {
if (MusicPlayerRemote.isPlaying()) {
playPauseDrawable.setPause(animate);
} else {
playPauseDrawable.setPlay(animate);
}
}
private void setUpMusicControllers() {
setUpPlayPauseButton();
setUpPrevNext();
setUpRepeatButton();
setUpShuffleButton();
setUpProgressSlider();
}
private void setUpPrevNext() {
updatePrevNextColor();
nextButton.setOnClickListener(v -> MusicPlayerRemote.playNextSong());
prevButton.setOnClickListener(v -> MusicPlayerRemote.back());
}
private void updatePrevNextColor() {
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
prevButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
}
private void setUpShuffleButton() {
shuffleButton.setOnClickListener(v -> MusicPlayerRemote.toggleShuffleMode());
}
@Override
protected void updateShuffleState() {
switch (MusicPlayerRemote.getShuffleMode()) {
case MusicService.SHUFFLE_MODE_SHUFFLE:
shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
default:
shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
private void setUpRepeatButton() {
repeatButton.setOnClickListener(v -> MusicPlayerRemote.cycleRepeatMode());
}
@Override
protected void updateRepeatState() {
switch (MusicPlayerRemote.getRepeatMode()) {
case MusicService.REPEAT_MODE_NONE:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_ALL:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_THIS:
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp);
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
private void updateProgressTextColor() {
int color = MaterialValueHelper.getPrimaryTextColor(getContext(), false);
songTotalTime.setTextColor(color);
songCurrentProgress.setTextColor(color);
}
@Override
protected void show() {
//Ignore
}
@Override
protected void hide() {
//Ignore
}
@Override
protected void setUpProgressSlider() {
progressSlider.setOnSeekBarChangeListener(new SimpleOnSeekbarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
MusicPlayerRemote.seekTo(progress);
onUpdateProgressViews(MusicPlayerRemote.getSongProgressMillis(), MusicPlayerRemote.getSongDurationMillis());
}
}
});
}
public void showBouceAnimation() {
playPauseButton.clearAnimation();
playPauseButton.setScaleX(0.9f);
playPauseButton.setScaleY(0.9f);
playPauseButton.setVisibility(View.VISIBLE);
playPauseButton.setPivotX(playPauseButton.getWidth() / 2);
playPauseButton.setPivotY(playPauseButton.getHeight() / 2);
playPauseButton.animate()
.setDuration(200)
.setInterpolator(new DecelerateInterpolator())
.scaleX(1.1f)
.scaleY(1.1f)
.withEndAction(() -> playPauseButton.animate()
.setDuration(200)
.setInterpolator(new AccelerateInterpolator())
.scaleX(1f)
.scaleY(1f)
.alpha(1f)
.start())
.start();
}
@OnClick(R.id.player_play_pause_button)
void showAnimation() {
if (MusicPlayerRemote.isPlaying()) {
MusicPlayerRemote.pauseSong();
} else {
MusicPlayerRemote.resumePlaying();
}
showBouceAnimation();
}
@Override
public void onUpdateProgressViews(int progress, int total) {
progressSlider.setMax(total);
ObjectAnimator animator = ObjectAnimator.ofInt(progressSlider, "progress", progress);
animator.setDuration(1500);
animator.setInterpolator(new LinearInterpolator());
animator.start();
songTotalTime.setText(MusicUtil.getReadableDurationString(total));
songCurrentProgress.setText(MusicUtil.getReadableDurationString(progress));
}
public void hideVolumeIfAvailable() {
volumeContainer.setVisibility(PreferenceUtil.getInstance(getContext()).getVolumeToggle() ? View.VISIBLE : View.GONE);
}
}

View file

@ -0,0 +1,192 @@
package code.name.monkey.retromusic.ui.fragments.player.cardblur;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget;
import code.name.monkey.retromusic.glide.SongGlideRequest;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerFragment;
import code.name.monkey.retromusic.ui.fragments.player.PlayerAlbumCoverFragment;
import code.name.monkey.retromusic.ui.fragments.player.normal.PlayerFragment;
import jp.wasabeef.glide.transformations.BlurTransformation;
public class CardBlurFragment extends AbsPlayerFragment implements PlayerAlbumCoverFragment.Callbacks {
@BindView(R.id.player_toolbar)
Toolbar toolbar;
@BindView(R.id.status_bar)
View statusBar;
@BindView(R.id.gradient_background)
ImageView colorBackground;
private int lastColor;
private CardBlurPlaybackControlsFragment playbackControlsFragment;
private Unbinder unbinder;
public static PlayerFragment newInstance() {
Bundle args = new Bundle();
PlayerFragment fragment = new PlayerFragment();
fragment.setArguments(args);
return fragment;
}
@Override
@ColorInt
public int getPaletteColor() {
return lastColor;
}
@Override
public void onShow() {
playbackControlsFragment.show();
}
@Override
public void onHide() {
playbackControlsFragment.hide();
onBackPressed();
}
@Override
public void onResume() {
super.onResume();
}
@Override
public boolean onBackPressed() {
return false;
}
@Override
public Toolbar getToolbar() {
return toolbar;
}
@Override
public int toolbarIconColor() {
return Color.WHITE;
}
@Override
public void onColorChanged(int color) {
playbackControlsFragment.setDark(color);
lastColor = color;
getCallbacks().onPaletteColorChanged();
ToolbarContentTintHelper.colorizeToolbar(toolbar, Color.WHITE, getActivity());
}
@Override
protected void toggleFavorite(Song song) {
super.toggleFavorite(song);
if (song.id == MusicPlayerRemote.getCurrentSong().id) {
updateIsFavorite();
}
}
@Override
public void onFavoriteToggled() {
toggleFavorite(MusicPlayerRemote.getCurrentSong());
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_card_blur_player, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
toggleStatusBar(statusBar);
setUpSubFragments();
setUpPlayerToolbar();
}
private void setUpSubFragments() {
playbackControlsFragment = (CardBlurPlaybackControlsFragment) getChildFragmentManager()
.findFragmentById(R.id.playback_controls_fragment);
PlayerAlbumCoverFragment playerAlbumCoverFragment =
(PlayerAlbumCoverFragment) getChildFragmentManager()
.findFragmentById(R.id.player_album_cover_fragment);
playerAlbumCoverFragment.setCallbacks(this);
playerAlbumCoverFragment.removeEffect();
}
private void setUpPlayerToolbar() {
toolbar.inflateMenu(R.menu.menu_player);
toolbar.setNavigationOnClickListener(v -> getActivity().onBackPressed());
toolbar.setOnMenuItemClickListener(this);
/* for (int i = 0; i < toolbar.getMenu().size(); i++) {
MenuItem menuItem = toolbar.getMenu().getItem(i);
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
}*/
ToolbarContentTintHelper.colorizeToolbar(toolbar, Color.WHITE, getActivity());
}
@Override
public void onServiceConnected() {
updateIsFavorite();
updateBlur();
}
@Override
public void onPlayingMetaChanged() {
updateIsFavorite();
updateBlur();
}
private void updateBlur() {
Activity activity = getActivity();
if (activity == null) {
return;
}
int blurAmount = PreferenceManager.getDefaultSharedPreferences(getContext()).getInt("blur_amount", 25);
colorBackground.clearColorFilter();
SongGlideRequest.Builder.from(Glide.with(activity), MusicPlayerRemote.getCurrentSong())
.checkIgnoreMediaStore(activity)
.generatePalette(activity)
.build()
.transform(new BlurTransformation(getActivity(), blurAmount))
.into(new RetroMusicColoredTarget(colorBackground) {
@Override
public void onColorReady(int color) {
if (color == getDefaultFooterColor()) {
colorBackground.setColorFilter(color);
}
}
});
}
}

View file

@ -0,0 +1,335 @@
package code.name.monkey.retromusic.ui.fragments.player.cardblur;
import android.animation.ObjectAnimator;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.AppCompatSeekBar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper;
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler;
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.service.MusicService;
import code.name.monkey.retromusic.ui.fragments.VolumeFragment;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerControlsFragment;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.views.PlayPauseDrawable;
public class CardBlurPlaybackControlsFragment extends AbsPlayerControlsFragment {
@BindView(R.id.player_play_pause_button)
ImageButton playPauseFab;
@BindView(R.id.player_prev_button)
ImageButton prevButton;
@BindView(R.id.player_next_button)
ImageButton nextButton;
@BindView(R.id.player_repeat_button)
ImageButton repeatButton;
@BindView(R.id.player_shuffle_button)
ImageButton shuffleButton;
@BindView(R.id.player_progress_slider)
AppCompatSeekBar progressSlider;
@BindView(R.id.player_song_total_time)
TextView songTotalTime;
@BindView(R.id.player_song_current_progress)
TextView songCurrentProgress;
@BindView(R.id.volume_fragment_container)
View volumeContainer;
@BindView(R.id.text)
TextView text;
@BindView(R.id.title)
TextView title;
private Unbinder unbinder;
private PlayPauseDrawable playerFabPlayPauseDrawable;
private int lastPlaybackControlsColor;
private int lastDisabledPlaybackControlsColor;
private MusicProgressViewUpdateHelper progressViewUpdateHelper;
private void updateSong() {
Song song = MusicPlayerRemote.getCurrentSong();
title.setText(song.title);
text.setText(song.artistName);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressViewUpdateHelper = new MusicProgressViewUpdateHelper(this);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_card_blur_player_playback_controls, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
unbinder = ButterKnife.bind(this, view);
setUpMusicControllers();
hideVolumeIfAvailable();
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Override
public void onResume() {
super.onResume();
progressViewUpdateHelper.start();
}
@Override
public void onPause() {
super.onPause();
progressViewUpdateHelper.stop();
}
@Override
public void onServiceConnected() {
updatePlayPauseDrawableState(false);
updateRepeatState();
updateSong();
updateShuffleState();
}
@Override
public void onPlayingMetaChanged() {
super.onPlayingMetaChanged();
updateSong();
}
@Override
public void onPlayStateChanged() {
updatePlayPauseDrawableState(true);
}
@Override
public void onRepeatModeChanged() {
updateRepeatState();
}
@Override
public void onShuffleModeChanged() {
updateShuffleState();
}
@Override
public void setDark(int dark) {
title.setTextColor(Color.WHITE);
text.setTextColor(Color.WHITE);
lastPlaybackControlsColor = Color.WHITE;
lastDisabledPlaybackControlsColor = ColorUtil.withAlpha(Color.WHITE, 0.3f);
updateRepeatState();
updateShuffleState();
updatePrevNextColor();
updateProgressTextColor();
}
private void setUpPlayPauseFab() {
final int fabColor = Color.WHITE;
TintHelper.setTintAuto(playPauseFab, fabColor, true);
playerFabPlayPauseDrawable = new PlayPauseDrawable(getActivity());
playPauseFab.setImageDrawable(playerFabPlayPauseDrawable); // Note: set the drawable AFTER TintHelper.setTintAuto() was called
playPauseFab.setColorFilter(MaterialValueHelper.getPrimaryTextColor(getContext(),
ColorUtil.isColorLight(fabColor)), PorterDuff.Mode.SRC_IN);
playPauseFab.setOnClickListener(new PlayPauseButtonOnClickHandler());
playPauseFab.post(() -> {
if (playPauseFab != null) {
playPauseFab.setPivotX(playPauseFab.getWidth() / 2);
playPauseFab.setPivotY(playPauseFab.getHeight() / 2);
}
});
}
protected void updatePlayPauseDrawableState(boolean animate) {
if (MusicPlayerRemote.isPlaying()) {
playerFabPlayPauseDrawable.setPause(animate);
} else {
playerFabPlayPauseDrawable.setPlay(animate);
}
}
private void setUpMusicControllers() {
setUpPlayPauseFab();
setUpPrevNext();
setUpRepeatButton();
setUpShuffleButton();
setUpProgressSlider();
setupVolumeControls();
}
private void setupVolumeControls() {
VolumeFragment volumeFragment = (VolumeFragment) getChildFragmentManager()
.findFragmentById(R.id.volume_fragment);
volumeFragment.tintWhiteColor();
}
private void setUpPrevNext() {
updatePrevNextColor();
nextButton.setOnClickListener(v -> MusicPlayerRemote.playNextSong());
prevButton.setOnClickListener(v -> MusicPlayerRemote.back());
}
private void updatePrevNextColor() {
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
prevButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
}
private void setUpShuffleButton() {
shuffleButton.setOnClickListener(v -> MusicPlayerRemote.toggleShuffleMode());
}
@Override
protected void updateShuffleState() {
switch (MusicPlayerRemote.getShuffleMode()) {
case MusicService.SHUFFLE_MODE_SHUFFLE:
shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
default:
shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
private void setUpRepeatButton() {
repeatButton.setOnClickListener(v -> MusicPlayerRemote.cycleRepeatMode());
}
@Override
protected void updateRepeatState() {
switch (MusicPlayerRemote.getRepeatMode()) {
case MusicService.REPEAT_MODE_NONE:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_ALL:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_THIS:
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp);
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
private void updateProgressTextColor() {
int color = MaterialValueHelper.getPrimaryTextColor(getContext(), false);
songTotalTime.setTextColor(color);
songCurrentProgress.setTextColor(color);
}
@Override
protected void show() {
//Ignore
}
@Override
protected void hide() {
//Ignore
}
@Override
protected void setUpProgressSlider() {
progressSlider.setOnSeekBarChangeListener(new SimpleOnSeekbarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
MusicPlayerRemote.seekTo(progress);
onUpdateProgressViews(MusicPlayerRemote.getSongProgressMillis(), MusicPlayerRemote.getSongDurationMillis());
}
}
});
progressSlider.setBackgroundTintList(ColorStateList.valueOf(Color.WHITE));
}
public void showBouceAnimation() {
playPauseFab.clearAnimation();
playPauseFab.setScaleX(0.9f);
playPauseFab.setScaleY(0.9f);
playPauseFab.setVisibility(View.VISIBLE);
playPauseFab.setPivotX(playPauseFab.getWidth() / 2);
playPauseFab.setPivotY(playPauseFab.getHeight() / 2);
playPauseFab.animate()
.setDuration(200)
.setInterpolator(new DecelerateInterpolator())
.scaleX(1.1f)
.scaleY(1.1f)
.withEndAction(() -> playPauseFab.animate()
.setDuration(200)
.setInterpolator(new AccelerateInterpolator())
.scaleX(1f)
.scaleY(1f)
.alpha(1f)
.start())
.start();
}
@OnClick(R.id.player_play_pause_button)
void showAnimation() {
if (MusicPlayerRemote.isPlaying()) {
MusicPlayerRemote.pauseSong();
} else {
MusicPlayerRemote.resumePlaying();
}
showBouceAnimation();
}
@Override
public void onUpdateProgressViews(int progress, int total) {
progressSlider.setMax(total);
ObjectAnimator animator = ObjectAnimator.ofInt(progressSlider, "progress", progress);
animator.setDuration(1500);
animator.setInterpolator(new LinearInterpolator());
animator.start();
songTotalTime.setText(MusicUtil.getReadableDurationString(total));
songCurrentProgress.setText(MusicUtil.getReadableDurationString(progress));
}
public void hideVolumeIfAvailable() {
volumeContainer.setVisibility(PreferenceUtil.getInstance(getContext()).getVolumeToggle() ? View.VISIBLE : View.GONE);
}
}

View file

@ -0,0 +1,305 @@
package code.name.monkey.retromusic.ui.fragments.player.color;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.graphics.Palette;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.animation.GlideAnimation;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget;
import code.name.monkey.retromusic.glide.SongGlideRequest;
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.model.lyrics.Lyrics;
import code.name.monkey.retromusic.ui.activities.LyricsActivity;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerFragment;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.RetroColorUtil;
import code.name.monkey.retromusic.util.ViewUtil;
public class ColorFragment extends AbsPlayerFragment {
@BindView(R.id.player_toolbar)
Toolbar toolbar;
@BindView(R.id.gradient_background)
View colorBackground;
@BindView(R.id.status_bar)
View statusBar;
@BindView(R.id.image)
ImageView imageView;
@BindView(R.id.lyrics)
TextView lyricsView;
@BindView(R.id.lyrics_container)
View lyricsViewContainer;
@BindView(R.id.album_cover_container)
View imageViewContainer;
private int lastColor;
private int backgroundColor;
private ColorPlaybackControlsFragment playbackControlsFragment;
private Unbinder unbinder;
private ValueAnimator valueAnimator;
private AsyncTask updateLyricsAsyncTask;
private Lyrics lyrics;
public static ColorFragment newInstance() {
Bundle args = new Bundle();
ColorFragment fragment = new ColorFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onShow() {
playbackControlsFragment.show();
}
@Override
public void onHide() {
playbackControlsFragment.hide();
onBackPressed();
}
@Override
public boolean onBackPressed() {
return false;
}
@Override
@ColorInt
public int getPaletteColor() {
return backgroundColor;
}
@Override
public Toolbar getToolbar() {
return toolbar;
}
@Override
public int toolbarIconColor() {
return lastColor;
}
@Override
protected void toggleFavorite(Song song) {
super.toggleFavorite(song);
if (song.id == MusicPlayerRemote.getCurrentSong().id) {
updateIsFavorite();
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
if (valueAnimator != null) {
valueAnimator.cancel();
valueAnimator = null;
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_color_player, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
toggleStatusBar(statusBar);
setUpSubFragments();
setUpPlayerToolbar();
}
private void setUpSubFragments() {
playbackControlsFragment = (ColorPlaybackControlsFragment)
getChildFragmentManager().findFragmentById(R.id.playback_controls_fragment);
}
private void setUpPlayerToolbar() {
toolbar.inflateMenu(R.menu.menu_player);
toolbar.setNavigationOnClickListener(v -> getActivity().onBackPressed());
toolbar.setOnMenuItemClickListener(this);
ToolbarContentTintHelper.colorizeToolbar(toolbar,
ATHUtil.resolveColor(getContext(), R.attr.iconColor), getActivity());
}
@Override
public void onPlayingMetaChanged() {
super.onPlayingMetaChanged();
updateSong();
updateLyricsLocal();
}
@Override
public void onServiceConnected() {
super.onServiceConnected();
updateSong();
updateLyricsLocal();
}
private void updateSong() {
Activity activity = getActivity();
SongGlideRequest.Builder.from(Glide.with(activity), MusicPlayerRemote.getCurrentSong())
.checkIgnoreMediaStore(activity)
.generatePalette(activity).build().dontAnimate()
.into(new RetroMusicColoredTarget(imageView) {
@Override
public void onColorReady(int color) {
//setColors(color);
}
@Override
public void onLoadFailed(Exception e, Drawable errorDrawable) {
super.onLoadFailed(e, errorDrawable);
int backgroundColor = getDefaultFooterColor();
int textColor = ColorUtil.isColorLight(getDefaultFooterColor()) ?
MaterialValueHelper.getPrimaryTextColor(getContext(), true) :
MaterialValueHelper.getPrimaryTextColor(getContext(), false);
setColors(backgroundColor, textColor);
}
@Override
public void onResourceReady(BitmapPaletteWrapper resource,
GlideAnimation<? super BitmapPaletteWrapper> glideAnimation) {
super.onResourceReady(resource, glideAnimation);
/* MediaNotificationProcessor processor = new MediaNotificationProcessor(getContext(),
getContext());
Palette.Builder builder = MediaNotificationProcessor
.generatePalette(resource.getBitmap());
int backgroundColor = processor.getBackgroundColor(builder);
int textColor = processor.getTextColor(builder);*/
Palette palette = resource.getPalette();
Palette.Swatch swatch = RetroColorUtil.getSwatch(palette);
int textColor = RetroColorUtil.getTextColor(palette);
int backgroundColor = swatch.getRgb();
setColors(backgroundColor, textColor);
}
});
}
private void setColors(int backgroundColor, int textColor) {
playbackControlsFragment.setDark(textColor, backgroundColor);
colorBackground.setBackgroundColor(backgroundColor);
ToolbarContentTintHelper.colorizeToolbar(toolbar, textColor, getActivity());
lastColor = textColor;
this.backgroundColor = backgroundColor;
getCallbacks().onPaletteColorChanged();
}
private void colorize(int i) {
if (valueAnimator != null) {
valueAnimator.cancel();
}
valueAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), Color.TRANSPARENT, i);
valueAnimator.addUpdateListener(animation -> {
if (colorBackground != null) {
colorBackground.setBackgroundColor((Integer) animation.getAnimatedValue());
}
});
valueAnimator.setDuration(ViewUtil.RETRO_MUSIC_ANIM_TIME).start();
}
@SuppressLint("StaticFieldLeak")
private void updateLyricsLocal() {
if (updateLyricsAsyncTask != null) {
updateLyricsAsyncTask.cancel(false);
}
final Song song = MusicPlayerRemote.getCurrentSong();
updateLyricsAsyncTask = new AsyncTask<Void, Void, Lyrics>() {
@Override
protected void onPreExecute() {
super.onPreExecute();
lyrics = null;
toolbar.getMenu().removeItem(R.id.action_show_lyrics);
}
@Override
protected Lyrics doInBackground(Void... params) {
String data = MusicUtil.getLyrics(song);
if (TextUtils.isEmpty(data)) {
return null;
}
return Lyrics.parse(song, data);
}
@Override
protected void onPostExecute(Lyrics l) {
lyrics = l;
if (lyrics == null) {
lyricsView.setText(R.string.no_lyrics_found);
} else {
lyricsView.setText(lyrics.getText());
}
}
@Override
protected void onCancelled(Lyrics s) {
onPostExecute(null);
}
}.execute();
}
@OnClick(R.id.expand)
void expand() {
startActivity(new Intent(getContext(), LyricsActivity.class));
}
@OnClick({R.id.lyrics, R.id.image})
void toggleLyrics(View view) {
if (lyricsViewContainer.getVisibility() == View.GONE) {
lyricsViewContainer.setVisibility(View.VISIBLE);
} else {
lyricsViewContainer.setVisibility(View.GONE);
}
}
}

View file

@ -0,0 +1,348 @@
package code.name.monkey.retromusic.ui.fragments.player.color;
import android.animation.ObjectAnimator;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.AppCompatSeekBar;
import android.support.v7.widget.AppCompatTextView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper;
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.service.MusicService;
import code.name.monkey.retromusic.ui.fragments.VolumeFragment;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerControlsFragment;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.views.PlayPauseDrawable;
public class ColorPlaybackControlsFragment extends AbsPlayerControlsFragment {
@BindView(R.id.player_play_pause_button)
ImageButton playPauseFab;
@BindView(R.id.player_prev_button)
ImageButton prevButton;
@BindView(R.id.player_next_button)
ImageButton nextButton;
@BindView(R.id.player_repeat_button)
ImageButton repeatButton;
@BindView(R.id.player_shuffle_button)
ImageButton shuffleButton;
@BindView(R.id.player_progress_slider)
AppCompatSeekBar progressSlider;
@BindView(R.id.player_song_total_time)
TextView songTotalTime;
@BindView(R.id.player_song_current_progress)
TextView songCurrentProgress;
@BindView(R.id.title)
AppCompatTextView title;
@BindView(R.id.text)
TextView text;
@BindView(R.id.volume_fragment_container)
View volumeContainer;
private Unbinder unbinder;
private PlayPauseDrawable playerFabPlayPauseDrawable;
private int lastPlaybackControlsColor;
private int lastDisabledPlaybackControlsColor;
private MusicProgressViewUpdateHelper progressViewUpdateHelper;
private VolumeFragment volumeFragment;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressViewUpdateHelper = new MusicProgressViewUpdateHelper(this);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_color_player_playback_controls, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
unbinder = ButterKnife.bind(this, view);
setUpMusicControllers();
if (PreferenceUtil.getInstance(getContext()).getVolumeToggle()) {
volumeContainer.setVisibility(View.VISIBLE);
} else {
volumeContainer.setVisibility(View.GONE);
}
volumeFragment = (VolumeFragment) getChildFragmentManager().findFragmentById(R.id.volume_fragment);
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
private void updateSong() {
Song song = MusicPlayerRemote.getCurrentSong();
title.setText(song.title);
text.setText(song.artistName);
}
@Override
public void onResume() {
super.onResume();
progressViewUpdateHelper.start();
}
@Override
public void onPause() {
super.onPause();
progressViewUpdateHelper.stop();
}
@Override
public void onServiceConnected() {
updatePlayPauseDrawableState(false);
updateRepeatState();
updateShuffleState();
updateSong();
}
@Override
public void onPlayingMetaChanged() {
super.onPlayingMetaChanged();
updateSong();
}
@Override
public void onPlayStateChanged() {
updatePlayPauseDrawableState(true);
}
@Override
public void onRepeatModeChanged() {
updateRepeatState();
}
@Override
public void onShuffleModeChanged() {
updateShuffleState();
}
public void setDark(int textColor, int background) {
setDark(textColor);
TintHelper.setTintAuto(playPauseFab, background, false);
TintHelper.setTintAuto(playPauseFab, textColor, true);
}
@Override
public void setDark(int color) {
lastPlaybackControlsColor = color;
lastDisabledPlaybackControlsColor = ColorUtil.withAlpha(color, 0.5f);
title.setTextColor(lastPlaybackControlsColor);
text.setTextColor(lastDisabledPlaybackControlsColor);
TintHelper.setTintAuto(progressSlider, lastPlaybackControlsColor, false);
volumeFragment.setTintable(lastPlaybackControlsColor);
songCurrentProgress.setTextColor(lastDisabledPlaybackControlsColor);
songTotalTime.setTextColor(lastDisabledPlaybackControlsColor);
updateRepeatState();
updateShuffleState();
updatePrevNextColor();
}
private void setUpPlayPauseFab() {
playerFabPlayPauseDrawable = new PlayPauseDrawable(getActivity());
playPauseFab.setImageDrawable(playerFabPlayPauseDrawable); // Note: set the drawable AFTER TintHelper.setTintAuto() was called
playPauseFab.setColorFilter(MaterialValueHelper.getPrimaryTextColor(getContext(), ColorUtil.isColorLight(Color.BLACK)), PorterDuff.Mode.SRC_IN);
//playPauseFab.setOnClickListener(new PlayPauseButtonOnClickHandler());
playPauseFab.post(() -> {
if (playPauseFab != null) {
playPauseFab.setPivotX(playPauseFab.getWidth() / 2);
playPauseFab.setPivotY(playPauseFab.getHeight() / 2);
}
});
}
protected void updatePlayPauseDrawableState(boolean animate) {
if (MusicPlayerRemote.isPlaying()) {
playerFabPlayPauseDrawable.setPause(animate);
} else {
playerFabPlayPauseDrawable.setPlay(animate);
}
}
private void setUpMusicControllers() {
setUpPlayPauseFab();
setUpPrevNext();
setUpRepeatButton();
setUpShuffleButton();
setUpProgressSlider();
}
private void setUpPrevNext() {
updatePrevNextColor();
nextButton.setOnClickListener(v -> MusicPlayerRemote.playNextSong());
prevButton.setOnClickListener(v -> MusicPlayerRemote.back());
}
private void updatePrevNextColor() {
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
prevButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
}
private void setUpShuffleButton() {
shuffleButton.setOnClickListener(v -> MusicPlayerRemote.toggleShuffleMode());
}
@Override
protected void updateShuffleState() {
switch (MusicPlayerRemote.getShuffleMode()) {
case MusicService.SHUFFLE_MODE_SHUFFLE:
shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
default:
shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
private void setUpRepeatButton() {
repeatButton.setOnClickListener(v -> MusicPlayerRemote.cycleRepeatMode());
}
@Override
protected void updateRepeatState() {
switch (MusicPlayerRemote.getRepeatMode()) {
case MusicService.REPEAT_MODE_NONE:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_ALL:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_THIS:
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp);
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
@Override
protected void show() {
playPauseFab.animate()
.scaleX(1f)
.scaleY(1f)
.rotation(360f)
.setInterpolator(new DecelerateInterpolator())
.start();
}
@Override
protected void hide() {
if (playPauseFab != null) {
playPauseFab.setScaleX(0f);
playPauseFab.setScaleY(0f);
playPauseFab.setRotation(0f);
}
}
@Override
protected void setUpProgressSlider() {
progressSlider.setOnSeekBarChangeListener(new SimpleOnSeekbarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
MusicPlayerRemote.seekTo(progress);
onUpdateProgressViews(MusicPlayerRemote.getSongProgressMillis(), MusicPlayerRemote.getSongDurationMillis());
}
}
});
}
public void showBouceAnimation() {
playPauseFab.clearAnimation();
playPauseFab.setScaleX(0.9f);
playPauseFab.setScaleY(0.9f);
playPauseFab.setVisibility(View.VISIBLE);
playPauseFab.setPivotX(playPauseFab.getWidth() / 2);
playPauseFab.setPivotY(playPauseFab.getHeight() / 2);
playPauseFab.animate()
.setDuration(200)
.setInterpolator(new DecelerateInterpolator())
.scaleX(1.1f)
.scaleY(1.1f)
.withEndAction(() -> playPauseFab.animate()
.setDuration(200)
.setInterpolator(new AccelerateInterpolator())
.scaleX(1f)
.scaleY(1f)
.alpha(1f)
.start())
.start();
}
@OnClick(R.id.player_play_pause_button)
void showAnimation() {
if (MusicPlayerRemote.isPlaying()) {
MusicPlayerRemote.pauseSong();
} else {
MusicPlayerRemote.resumePlaying();
}
showBouceAnimation();
}
@Override
public void onUpdateProgressViews(int progress, int total) {
progressSlider.setMax(total);
ObjectAnimator animator = ObjectAnimator.ofInt(progressSlider, "progress", progress);
animator.setDuration(1500);
animator.setInterpolator(new LinearInterpolator());
animator.start();
songTotalTime.setText(MusicUtil.getReadableDurationString(total));
songCurrentProgress.setText(MusicUtil.getReadableDurationString(progress));
}
public void hideVolumeIfAvailable() {
volumeContainer.setVisibility(PreferenceUtil.getInstance(getContext()).getVolumeToggle() ? View.VISIBLE : View.GONE);
}
}

View file

@ -0,0 +1,300 @@
package code.name.monkey.retromusic.ui.fragments.player.flat;
import android.animation.ObjectAnimator;
import android.graphics.PorterDuff;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper;
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper.Callback;
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler;
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.service.MusicService;
import code.name.monkey.retromusic.ui.fragments.base.AbsMusicServiceFragment;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.views.PlayPauseDrawable;
public class FlatPlaybackControlsFragment extends AbsMusicServiceFragment implements Callback {
@BindView(R.id.text)
TextView mText;
@BindView(R.id.title)
TextView mTitle;
@BindView(R.id.playback_controls)
ViewGroup viewGroup;
@BindView(R.id.player_song_total_time)
TextView mSongTotalTime;
@BindView(R.id.player_song_current_progress)
TextView mPlayerSongCurrentProgress;
@BindView(R.id.player_repeat_button)
ImageButton mPlayerRepeatButton;
@BindView(R.id.player_shuffle_button)
ImageButton mPlayerShuffleButton;
@BindView(R.id.player_play_pause_button)
ImageView mPlayerPlayPauseFab;
Unbinder unbinder;
@BindView(R.id.player_progress_slider)
SeekBar progressSlider;
@BindView(R.id.volume_fragment_container)
View mVolumeContainer;
private int lastPlaybackControlsColor;
private int lastDisabledPlaybackControlsColor;
private MusicProgressViewUpdateHelper progressViewUpdateHelper;
private PlayPauseDrawable playerFabPlayPauseDrawable;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressViewUpdateHelper = new MusicProgressViewUpdateHelper(this);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_flat_player_playback_controls, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setUpMusicControllers();
mVolumeContainer.setVisibility(PreferenceUtil.getInstance(getContext()).getVolumeToggle() ? View.VISIBLE : View.GONE);
}
@Override
public void onResume() {
super.onResume();
progressViewUpdateHelper.start();
}
@Override
public void onPause() {
super.onPause();
progressViewUpdateHelper.stop();
}
@Override
public void onUpdateProgressViews(int progress, int total) {
progressSlider.setMax(total);
ObjectAnimator animator = ObjectAnimator.ofInt(progressSlider, "progress", progress);
animator.setDuration(1500);
animator.setInterpolator(new LinearInterpolator());
animator.start();
mPlayerSongCurrentProgress.setText(MusicUtil.getReadableDurationString(progress));
mSongTotalTime.setText(MusicUtil.getReadableDurationString(total));
}
public void show() {
mPlayerPlayPauseFab.animate()
.scaleX(1f)
.scaleY(1f)
.setInterpolator(new DecelerateInterpolator())
.start();
}
public void hide() {
if (mPlayerPlayPauseFab != null) {
mPlayerPlayPauseFab.setScaleX(0f);
mPlayerPlayPauseFab.setScaleY(0f);
mPlayerPlayPauseFab.setRotation(0f);
}
}
public void setDark(int dark) {
int color = ATHUtil.resolveColor(getActivity(), android.R.attr.colorBackground);
boolean isDark = ColorUtil.isColorLight(color);
if (isDark) {
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(getActivity(), true);
lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(getActivity(), true);
} else {
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(getActivity(), false);
lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(getActivity(), false);
}
int accentColor = ThemeStore.accentColor(getContext());
boolean b = PreferenceUtil.getInstance(getContext()).getAdaptiveColor();
updateTextColors(b ? dark : accentColor);
setProgressBarColor(b ? dark : accentColor);
updateRepeatState();
updateShuffleState();
}
private void setProgressBarColor(int dark) {
TintHelper.setTintAuto(progressSlider, dark, false);
//LayerDrawable ld = (LayerDrawable) progressSlider.getProgressDrawable();
//ClipDrawable clipDrawable = (ClipDrawable) ld.findDrawableByLayerId(android.R.id.progress);
//clipDrawable.setColorFilter(dark, PorterDuff.Mode.SRC_IN);
}
private void updateTextColors(int color) {
boolean isDark = ColorUtil.isColorLight(color);
int darkColor = ColorUtil.darkenColor(color);
int colorPrimary = MaterialValueHelper.getPrimaryTextColor(getContext(), isDark);
int colorSecondary = MaterialValueHelper.getSecondaryTextColor(getContext(), ColorUtil.isColorLight(darkColor));
TintHelper.setTintAuto(mPlayerPlayPauseFab, colorPrimary, false);
TintHelper.setTintAuto(mPlayerPlayPauseFab, color, true);
mTitle.setBackgroundColor(color);
mTitle.setTextColor(colorPrimary);
mText.setBackgroundColor(darkColor);
mText.setTextColor(colorSecondary);
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Override
public void onServiceConnected() {
updatePlayPauseDrawableState(false);
updateRepeatState();
updateShuffleState();
updateSong();
}
@Override
public void onPlayingMetaChanged() {
super.onPlayingMetaChanged();
updateSong();
}
@Override
public void onPlayStateChanged() {
updatePlayPauseDrawableState(true);
}
protected void updatePlayPauseDrawableState(boolean animate) {
if (MusicPlayerRemote.isPlaying()) {
playerFabPlayPauseDrawable.setPause(animate);
} else {
playerFabPlayPauseDrawable.setPlay(animate);
}
}
private void setUpPlayPauseFab() {
playerFabPlayPauseDrawable = new PlayPauseDrawable(getActivity());
mPlayerPlayPauseFab.setImageDrawable(
playerFabPlayPauseDrawable); // Note: set the drawable AFTER TintHelper.setTintAuto() was called
//playPauseFab.setColorFilter(MaterialValueHelper.getPrimaryTextColor(getContext(), ColorUtil.isColorLight(fabColor)), PorterDuff.Mode.SRC_IN);
mPlayerPlayPauseFab.setOnClickListener(new PlayPauseButtonOnClickHandler());
mPlayerPlayPauseFab.post(() -> {
if (mPlayerPlayPauseFab != null) {
mPlayerPlayPauseFab.setPivotX(mPlayerPlayPauseFab.getWidth() / 2);
mPlayerPlayPauseFab.setPivotY(mPlayerPlayPauseFab.getHeight() / 2);
}
});
}
private void setUpMusicControllers() {
setUpPlayPauseFab();
setUpRepeatButton();
setUpShuffleButton();
setUpProgressSlider();
}
private void updateSong() {
//TransitionManager.beginDelayedTransition(viewGroup, new ChangeText().setChangeBehavior(ChangeText.CHANGE_BEHAVIOR_OUT_IN));
Song song = MusicPlayerRemote.getCurrentSong();
mTitle.setText(song.title);
mText.setText(song.artistName);
}
private void setUpProgressSlider() {
progressSlider.setOnSeekBarChangeListener(new SimpleOnSeekbarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
MusicPlayerRemote.seekTo(progress);
onUpdateProgressViews(MusicPlayerRemote.getSongProgressMillis(),
MusicPlayerRemote.getSongDurationMillis());
}
}
});
}
@Override
public void onRepeatModeChanged() {
updateRepeatState();
}
@Override
public void onShuffleModeChanged() {
updateShuffleState();
}
private void setUpRepeatButton() {
mPlayerRepeatButton.setOnClickListener(v -> MusicPlayerRemote.cycleRepeatMode());
}
private void updateRepeatState() {
switch (MusicPlayerRemote.getRepeatMode()) {
case MusicService.REPEAT_MODE_NONE:
mPlayerRepeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
mPlayerRepeatButton
.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_ALL:
mPlayerRepeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
mPlayerRepeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_THIS:
mPlayerRepeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp);
mPlayerRepeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
private void setUpShuffleButton() {
mPlayerShuffleButton.setOnClickListener(v -> MusicPlayerRemote.toggleShuffleMode());
}
private void updateShuffleState() {
switch (MusicPlayerRemote.getShuffleMode()) {
case MusicService.SHUFFLE_MODE_SHUFFLE:
mPlayerShuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
default:
mPlayerShuffleButton
.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
}

View file

@ -0,0 +1,174 @@
package code.name.monkey.retromusic.ui.fragments.player.flat;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerFragment;
import code.name.monkey.retromusic.ui.fragments.player.PlayerAlbumCoverFragment;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.util.ViewUtil;
import code.name.monkey.retromusic.views.DrawableGradient;
public class FlatPlayerFragment extends AbsPlayerFragment implements
PlayerAlbumCoverFragment.Callbacks {
@BindView(R.id.player_toolbar)
Toolbar toolbar;
@BindView(R.id.gradient_background)
View colorBackground;
@BindView(R.id.toolbar_container)
FrameLayout toolbarContainer;
@BindView(R.id.status_bar)
View statusBar;
private Unbinder unbinder;
private ValueAnimator valueAnimator;
private FlatPlaybackControlsFragment flatPlaybackControlsFragment;
private int lastColor;
private void setUpSubFragments() {
flatPlaybackControlsFragment = (FlatPlaybackControlsFragment)
getChildFragmentManager().findFragmentById(R.id.playback_controls_fragment);
PlayerAlbumCoverFragment playerAlbumCoverFragment = (PlayerAlbumCoverFragment)
getChildFragmentManager().findFragmentById(R.id.player_album_cover_fragment);
playerAlbumCoverFragment.setCallbacks(this);
}
private void setUpPlayerToolbar() {
toolbar.inflateMenu(R.menu.menu_player);
toolbar.setNavigationOnClickListener(v -> getActivity().onBackPressed());
toolbar.setOnMenuItemClickListener(this);
ToolbarContentTintHelper.colorizeToolbar(toolbar, ATHUtil.resolveColor(getContext(),
R.attr.iconColor), getActivity());
}
private void colorize(int i) {
if (valueAnimator != null) {
valueAnimator.cancel();
}
valueAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), android.R.color.transparent, i);
valueAnimator.addUpdateListener(animation -> {
GradientDrawable drawable = new DrawableGradient(GradientDrawable.Orientation.TOP_BOTTOM,
new int[]{(int) animation.getAnimatedValue(), android.R.color.transparent}, 0);
if (colorBackground != null) {
colorBackground.setBackground(drawable);
}
});
valueAnimator.setDuration(ViewUtil.RETRO_MUSIC_ANIM_TIME).start();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_flat_player, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
toggleStatusBar(statusBar);
setUpPlayerToolbar();
setUpSubFragments();
}
@Override
public int getPaletteColor() {
return lastColor;
}
@Override
public void onShow() {
flatPlaybackControlsFragment.show();
}
@Override
public void onHide() {
flatPlaybackControlsFragment.hide();
onBackPressed();
}
@Override
public boolean onBackPressed() {
return false;
}
@Override
public Toolbar getToolbar() {
return toolbar;
}
@Override
public int toolbarIconColor() {
boolean isLight = ColorUtil.isColorLight(lastColor);
return PreferenceUtil.getInstance(getContext()).getAdaptiveColor() ?
MaterialValueHelper.getPrimaryTextColor(getContext(), isLight) :
ATHUtil.resolveColor(getContext(), R.attr.iconColor);
}
@Override
public void onColorChanged(int color) {
lastColor = color;
flatPlaybackControlsFragment.setDark(color);
getCallbacks().onPaletteColorChanged();
boolean isLight = ColorUtil.isColorLight(color);
//TransitionManager.beginDelayedTransition(mToolbar);
int iconColor = PreferenceUtil.getInstance(getContext()).getAdaptiveColor() ?
MaterialValueHelper.getPrimaryTextColor(getContext(), isLight) :
ATHUtil.resolveColor(getContext(), R.attr.iconColor);
ToolbarContentTintHelper.colorizeToolbar(toolbar, iconColor, getActivity());
if (PreferenceUtil.getInstance(getContext()).getAdaptiveColor()) {
colorize(color);
}
}
@Override
public void onFavoriteToggled() {
toggleFavorite(MusicPlayerRemote.getCurrentSong());
}
@Override
protected void toggleFavorite(Song song) {
super.toggleFavorite(song);
if (song.id == MusicPlayerRemote.getCurrentSong().id) {
updateIsFavorite();
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
}

View file

@ -0,0 +1,301 @@
package code.name.monkey.retromusic.ui.fragments.player.full;
import android.animation.ObjectAnimator;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper;
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler;
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.service.MusicService;
import code.name.monkey.retromusic.ui.fragments.VolumeFragment;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerControlsFragment;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
/**
* Created by hemanths on 20/09/17.
*/
public class FullPlaybackControlsFragment extends AbsPlayerControlsFragment {
@BindView(R.id.player_song_current_progress)
TextView mPlayerSongCurrentProgress;
@BindView(R.id.player_song_total_time)
TextView songTotalTime;
@BindView(R.id.player_progress_slider)
SeekBar progressSlider;
@BindView(R.id.player_prev_button)
ImageButton playerPrevButton;
@BindView(R.id.player_next_button)
ImageButton playerNextButton;
@BindView(R.id.player_repeat_button)
ImageButton playerRepeatButton;
@BindView(R.id.player_shuffle_button)
ImageButton playerShuffleButton;
@BindView(R.id.player_play_pause_button)
ImageButton playerPlayPauseFab;
Unbinder unbinder;
@BindView(R.id.title)
TextView mTitle;
@BindView(R.id.text)
TextView mText;
@BindView(R.id.volume_fragment_container)
View mVolumeContainer;
private int lastPlaybackControlsColor;
private int lastDisabledPlaybackControlsColor;
private MusicProgressViewUpdateHelper progressViewUpdateHelper;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressViewUpdateHelper = new MusicProgressViewUpdateHelper(this);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_full_player_controls, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setUpMusicControllers();
mVolumeContainer.setVisibility(PreferenceUtil.getInstance(getContext()).getVolumeToggle() ? View.VISIBLE : View.GONE);
VolumeFragment volumeFragment = (VolumeFragment) getChildFragmentManager().findFragmentById(R.id.volume_fragment);
volumeFragment.tintWhiteColor();
}
@Override
public void onResume() {
super.onResume();
progressViewUpdateHelper.start();
}
@Override
public void onPause() {
super.onPause();
progressViewUpdateHelper.stop();
}
@Override
public void onUpdateProgressViews(int progress, int total) {
progressSlider.setMax(total);
ObjectAnimator animator = ObjectAnimator.ofInt(progressSlider, "progress", progress);
animator.setDuration(1500);
animator.setInterpolator(new LinearInterpolator());
animator.start();
mPlayerSongCurrentProgress.setText(MusicUtil.getReadableDurationString(progress));
songTotalTime.setText(MusicUtil.getReadableDurationString(total));
}
public void show() {
playerPlayPauseFab.animate()
.scaleX(1f)
.scaleY(1f)
.setInterpolator(new DecelerateInterpolator())
.start();
}
public void hide() {
if (playerPlayPauseFab != null) {
playerPlayPauseFab.setScaleX(0f);
playerPlayPauseFab.setScaleY(0f);
playerPlayPauseFab.setRotation(0f);
}
}
public void setDark(int dark) {
lastPlaybackControlsColor = Color.WHITE;
lastDisabledPlaybackControlsColor = ContextCompat.getColor(getContext(), R.color.md_grey_500);
if (PreferenceUtil.getInstance(getContext()).getAdaptiveColor()) {
setProgressBarColor(dark);
} else {
int accentColor = ThemeStore.accentColor(getContext());
setProgressBarColor(accentColor);
}
updateRepeatState();
updateShuffleState();
updatePrevNextColor();
updateProgressTextColor();
}
private void setProgressBarColor(int dark) {
LayerDrawable ld = (LayerDrawable) progressSlider.getProgressDrawable();
ClipDrawable clipDrawable = (ClipDrawable) ld.findDrawableByLayerId(android.R.id.progress);
clipDrawable.setColorFilter(dark, PorterDuff.Mode.SRC_IN);
}
@Override
public void onServiceConnected() {
updatePlayPauseDrawableState(false);
updateRepeatState();
updateShuffleState();
updateSong();
}
private void updateSong() {
Song song = MusicPlayerRemote.getCurrentSong();
mTitle.setText(song.title);
mText.setText(song.artistName);
}
@Override
public void onPlayingMetaChanged() {
super.onPlayingMetaChanged();
updateSong();
}
@Override
public void onPlayStateChanged() {
updatePlayPauseDrawableState(true);
}
protected void updatePlayPauseDrawableState(boolean animate) {
if (MusicPlayerRemote.isPlaying()) {
playerPlayPauseFab.setImageResource(R.drawable.ic_pause_white_24dp);
} else {
playerPlayPauseFab.setImageResource(R.drawable.ic_play_arrow_white_24dp);
}
}
private void setUpPlayPauseFab() {
playerPlayPauseFab.setOnClickListener(new PlayPauseButtonOnClickHandler());
playerPlayPauseFab.post(() -> {
if (playerPlayPauseFab != null) {
playerPlayPauseFab.setPivotX(playerPlayPauseFab.getWidth() / 2);
playerPlayPauseFab.setPivotY(playerPlayPauseFab.getHeight() / 2);
}
});
}
private void setUpMusicControllers() {
setUpPlayPauseFab();
setUpPrevNext();
setUpRepeatButton();
setUpShuffleButton();
setUpProgressSlider();
}
private void setUpPrevNext() {
updatePrevNextColor();
playerNextButton.setOnClickListener(v -> MusicPlayerRemote.playNextSong());
playerPrevButton.setOnClickListener(v -> MusicPlayerRemote.back());
}
private void updateProgressTextColor() {
int color = MaterialValueHelper.getSecondaryTextColor(getContext(), false);
//songTotalTime.setTextColor(color);
//songCurrentProgress.setTextColor(color);
}
private void updatePrevNextColor() {
playerNextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
playerPrevButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
}
@Override
protected void setUpProgressSlider() {
progressSlider.setOnSeekBarChangeListener(new SimpleOnSeekbarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
MusicPlayerRemote.seekTo(progress);
onUpdateProgressViews(MusicPlayerRemote.getSongProgressMillis(), MusicPlayerRemote.getSongDurationMillis());
}
}
});
}
@Override
public void onRepeatModeChanged() {
updateRepeatState();
}
@Override
public void onShuffleModeChanged() {
updateShuffleState();
}
private void setUpRepeatButton() {
playerRepeatButton.setOnClickListener(v -> MusicPlayerRemote.cycleRepeatMode());
}
@Override
protected void updateRepeatState() {
switch (MusicPlayerRemote.getRepeatMode()) {
case MusicService.REPEAT_MODE_NONE:
playerRepeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
playerRepeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_ALL:
playerRepeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
playerRepeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_THIS:
playerRepeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp);
playerRepeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
private void setUpShuffleButton() {
playerShuffleButton.setOnClickListener(v -> MusicPlayerRemote.toggleShuffleMode());
}
@Override
public void updateShuffleState() {
switch (MusicPlayerRemote.getShuffleMode()) {
case MusicService.SHUFFLE_MODE_SHUFFLE:
playerShuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
default:
playerShuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
}

View file

@ -0,0 +1,123 @@
package code.name.monkey.retromusic.ui.fragments.player.full;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerFragment;
import code.name.monkey.retromusic.ui.fragments.player.PlayerAlbumCoverFragment;
public class FullPlayerFragment extends AbsPlayerFragment implements PlayerAlbumCoverFragment.Callbacks {
@BindView(R.id.player_toolbar)
Toolbar toolbar;
Unbinder unbinder;
private int lastColor;
private FullPlaybackControlsFragment fullPlaybackControlsFragment;
private void setUpPlayerToolbar() {
toolbar.inflateMenu(R.menu.menu_player);
toolbar.setNavigationIcon(R.drawable.ic_close_white_24dp);
toolbar.setNavigationOnClickListener(v -> getActivity().onBackPressed());
toolbar.setOnMenuItemClickListener(this);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_full, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setUpSubFragments();
setUpPlayerToolbar();
}
private void setUpSubFragments() {
fullPlaybackControlsFragment = (FullPlaybackControlsFragment)
getChildFragmentManager().findFragmentById(R.id.playback_controls_fragment);
PlayerAlbumCoverFragment playerAlbumCoverFragment = (PlayerAlbumCoverFragment)
getChildFragmentManager().findFragmentById(R.id.player_album_cover_fragment);
playerAlbumCoverFragment.setCallbacks(this);
playerAlbumCoverFragment.removeSlideEffect();
}
@Override
@ColorInt
public int getPaletteColor() {
return lastColor;
}
@Override
public void onShow() {
}
@Override
public void onHide() {
}
@Override
public boolean onBackPressed() {
return false;
}
@Override
public Toolbar getToolbar() {
return toolbar;
}
@Override
public int toolbarIconColor() {
return Color.WHITE;
}
@Override
public void onColorChanged(int color) {
lastColor = color;
fullPlaybackControlsFragment.setDark(color);
getCallbacks().onPaletteColorChanged();
ToolbarContentTintHelper.colorizeToolbar(toolbar, Color.WHITE, getActivity());
}
@Override
public void onFavoriteToggled() {
toggleFavorite(MusicPlayerRemote.getCurrentSong());
}
@Override
protected void toggleFavorite(Song song) {
super.toggleFavorite(song);
if (song.id == MusicPlayerRemote.getCurrentSong().id) {
updateIsFavorite();
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
}

View file

@ -0,0 +1,144 @@
package code.name.monkey.retromusic.ui.fragments.player.hmm;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.service.MusicService;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerControlsFragment;
/**
* @author Hemanth S (h4h13).
*/
public class HmmPlaybackControlsFragment extends AbsPlayerControlsFragment {
@BindView(R.id.player_repeat_button)
ImageButton repeatButton;
@BindView(R.id.player_shuffle_button)
ImageButton shuffleButton;
private Unbinder unbinder;
private int mLastPlaybackControlsColor;
private int mLastDisabledPlaybackControlsColor;
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Override
public void onRepeatModeChanged() {
updateRepeatState();
}
@Override
public void onShuffleModeChanged() {
updateShuffleState();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_hmm_controls_fragment, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setUpMusicControllers();
}
private void setUpMusicControllers() {
setUpRepeatButton();
setUpShuffleButton();
setUpProgressSlider();
}
@Override
protected void show() {
}
@Override
protected void hide() {
}
private void setUpShuffleButton() {
shuffleButton.setOnClickListener(v -> MusicPlayerRemote.toggleShuffleMode());
}
@Override
protected void updateShuffleState() {
switch (MusicPlayerRemote.getShuffleMode()) {
case MusicService.SHUFFLE_MODE_SHUFFLE:
shuffleButton.setColorFilter(mLastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
default:
shuffleButton.setColorFilter(mLastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
private void setUpRepeatButton() {
repeatButton.setOnClickListener(v -> MusicPlayerRemote.cycleRepeatMode());
}
@Override
protected void updateRepeatState() {
switch (MusicPlayerRemote.getRepeatMode()) {
case MusicService.REPEAT_MODE_NONE:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(mLastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_ALL:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(mLastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_THIS:
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp);
repeatButton.setColorFilter(mLastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
@Override
protected void setUpProgressSlider() {
}
@Override
public void setDark(int dark) {
if (ColorUtil.isColorLight(dark)) {
mLastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(getActivity(), true);
mLastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(getActivity(), true);
} else {
mLastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(getActivity(), false);
mLastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(getActivity(), false);
}
updateRepeatState();
updateShuffleState();
}
@Override
public void onUpdateProgressViews(int progress, int total) {
}
}

View file

@ -0,0 +1,220 @@
package code.name.monkey.retromusic.ui.fragments.player.hmm;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.afollestad.materialdialogs.internal.MDTintHelper;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper;
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.ui.fragments.MiniPlayerFragment;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerFragment;
import code.name.monkey.retromusic.ui.fragments.player.PlayerAlbumCoverFragment;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
/**
* @author Hemanth S (h4h13).
*/
public class HmmPlayerFragment extends AbsPlayerFragment implements
MusicProgressViewUpdateHelper.Callback, PlayerAlbumCoverFragment.Callbacks {
@BindView(R.id.title)
TextView title;
@BindView(R.id.text)
TextView text;
@BindView(R.id.player_song_total_time)
TextView totalTime;
@BindView(R.id.progress_bar)
ProgressBar progressBar;
@BindView(R.id.player_toolbar)
Toolbar toolbar;
@BindView(R.id.status_bar)
View statusBar;
private MusicProgressViewUpdateHelper progressViewUpdateHelper;
private Unbinder unBinder;
private int lastColor;
private HmmPlaybackControlsFragment hmmPlaybackControlsFragment;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressViewUpdateHelper = new MusicProgressViewUpdateHelper(this);
}
@Override
public void onResume() {
super.onResume();
progressViewUpdateHelper.start();
}
@Override
public void onPause() {
super.onPause();
progressViewUpdateHelper.stop();
}
private void updateSong() {
Song song = MusicPlayerRemote.getCurrentSong();
title.setText(song.title);
text.setText(String.format("%s \nby -%s", song.albumName, song.artistName));
}
@Override
public void onDestroyView() {
super.onDestroyView();
unBinder.unbind();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_hmm_player, container, false);
unBinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
toggleStatusBar(statusBar);
progressBar.setOnClickListener(new PlayPauseButtonOnClickHandler());
progressBar.setOnTouchListener(new MiniPlayerFragment.FlingPlayBackController(getActivity()));
setUpPlayerToolbar();
setUpSubFragments();
}
private void setUpSubFragments() {
hmmPlaybackControlsFragment = (HmmPlaybackControlsFragment) getChildFragmentManager()
.findFragmentById(R.id.playback_controls_fragment);
PlayerAlbumCoverFragment playerAlbumCoverFragment = (PlayerAlbumCoverFragment) getChildFragmentManager()
.findFragmentById(R.id.player_album_cover_fragment);
playerAlbumCoverFragment.setCallbacks(this);
}
@Override
public int getPaletteColor() {
return lastColor;
}
@Override
public void onShow() {
hmmPlaybackControlsFragment.show();
}
@Override
public void onHide() {
hmmPlaybackControlsFragment.hide();
}
@Override
public boolean onBackPressed() {
return false;
}
@Override
public Toolbar getToolbar() {
return toolbar;
}
@Override
public int toolbarIconColor() {
return MaterialValueHelper
.getSecondaryTextColor(getContext(), ColorUtil.isColorLight(lastColor));
}
@Override
public void onUpdateProgressViews(int progress, int total) {
progressBar.setMax(total);
ObjectAnimator animator = ObjectAnimator.ofInt(progressBar, "progress", progress);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playSequentially(animator);
animatorSet.setDuration(1500);
animatorSet.setInterpolator(new LinearInterpolator());
animatorSet.start();
totalTime.setText(String.format("%s/%s", MusicUtil.getReadableDurationString(total),
MusicUtil.getReadableDurationString(progress)));
}
private void setUpPlayerToolbar() {
toolbar.inflateMenu(R.menu.menu_player);
toolbar.setNavigationOnClickListener(v -> getActivity().onBackPressed());
toolbar.setOnMenuItemClickListener(this);
}
@Override
protected void toggleFavorite(Song song) {
super.toggleFavorite(song);
if (song.id == MusicPlayerRemote.getCurrentSong().id) {
updateIsFavorite();
}
}
@Override
public void onServiceConnected() {
super.onServiceConnected();
updateSong();
}
@Override
public void onPlayingMetaChanged() {
super.onPlayingMetaChanged();
updateSong();
}
@Override
public void onColorChanged(int color) {
lastColor = PreferenceUtil.getInstance(getContext()).getAdaptiveColor() ? color :
ThemeStore.accentColor(getContext());
getCallbacks().onPaletteColorChanged();
hmmPlaybackControlsFragment.setDark(lastColor);
setProgressBarColor(lastColor);
int iconColor = MaterialValueHelper
.getSecondaryTextColor(getContext(), ColorUtil.isColorLight(lastColor));
ToolbarContentTintHelper.colorizeToolbar(toolbar, iconColor, getActivity());
}
private void setProgressBarColor(int color) {
MDTintHelper.setTint(progressBar, color);
}
@Override
public void onFavoriteToggled() {
toggleFavorite(MusicPlayerRemote.getCurrentSong());
}
}

View file

@ -0,0 +1,294 @@
package code.name.monkey.retromusic.ui.fragments.player.lockscreen;
import android.animation.ObjectAnimator;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.AppCompatImageButton;
import android.support.v7.widget.AppCompatSeekBar;
import android.support.v7.widget.AppCompatTextView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper;
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.ui.fragments.VolumeFragment;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerControlsFragment;
import code.name.monkey.retromusic.util.MusicUtil;
/**
* @author Hemanth S (h4h13).
*/
public class LockScreenPlayerControlsFragment extends AbsPlayerControlsFragment {
@BindView(R.id.player_play_pause_button)
AppCompatImageButton playPauseFab;
@BindView(R.id.player_prev_button)
ImageButton prevButton;
@BindView(R.id.player_next_button)
ImageButton nextButton;
@BindView(R.id.player_progress_slider)
AppCompatSeekBar progressSlider;
@BindView(R.id.player_song_total_time)
TextView songTotalTime;
@BindView(R.id.player_song_current_progress)
TextView songCurrentProgress;
@BindView(R.id.title)
AppCompatTextView title;
@BindView(R.id.text)
AppCompatTextView text;
private Unbinder unbinder;
private MusicProgressViewUpdateHelper progressViewUpdateHelper;
private int lastPlaybackControlsColor;
public LockScreenPlayerControlsFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressViewUpdateHelper = new MusicProgressViewUpdateHelper(this);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_lock_screen_playback_controls, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setUpMusicControllers();
VolumeFragment volumeFragment = (VolumeFragment) getChildFragmentManager().findFragmentById(R.id.volume_fragment);
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
private void updateSong() {
Song song = MusicPlayerRemote.getCurrentSong();
title.setText(song.title);
text.setText(String.format("%s - %s", song.artistName, song.albumName));
}
@Override
public void onResume() {
super.onResume();
progressViewUpdateHelper.start();
}
@Override
public void onPause() {
super.onPause();
progressViewUpdateHelper.stop();
}
@Override
public void onServiceConnected() {
updatePlayPauseDrawableState(false);
updateRepeatState();
updateShuffleState();
updateSong();
}
@Override
public void onPlayingMetaChanged() {
super.onPlayingMetaChanged();
updateSong();
}
@Override
public void onPlayStateChanged() {
updatePlayPauseDrawableState(true);
}
@Override
public void onRepeatModeChanged() {
updateRepeatState();
}
@Override
public void onShuffleModeChanged() {
updateShuffleState();
}
@Override
public void setDark(int dark) {
setProgressBarColor(progressSlider, dark);
if (ColorUtil.isColorLight(ATHUtil.resolveColor(getContext(), android.R.attr.windowBackground))) {
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(getActivity(), true);
} else {
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(getActivity(), false);
}
updatePrevNextColor();
boolean isDark = ColorUtil.isColorLight(dark);
text.setTextColor(dark);
TintHelper.setTintAuto(playPauseFab, MaterialValueHelper.getPrimaryTextColor(getContext(), isDark), false);
TintHelper.setTintAuto(playPauseFab, dark, true);
}
public void setProgressBarColor(SeekBar progressBar, int newColor) {
TintHelper.setTintAuto(progressBar, newColor, false);
//LayerDrawable ld = (LayerDrawable) progressBar.getProgressDrawable();
//ClipDrawable clipDrawable = (ClipDrawable) ld.findDrawableByLayerId(android.R.id.progress);
//clipDrawable.setColorFilter(newColor, PorterDuff.Mode.SRC_IN);
}
private void setUpPlayPauseFab() {
playPauseFab.post(() -> {
if (playPauseFab != null) {
playPauseFab.setPivotX(playPauseFab.getWidth() / 2);
playPauseFab.setPivotY(playPauseFab.getHeight() / 2);
}
});
}
private void setUpMusicControllers() {
setUpPlayPauseFab();
setUpPrevNext();
setUpProgressSlider();
}
private void setUpPrevNext() {
updatePrevNextColor();
nextButton.setOnClickListener(v -> MusicPlayerRemote.playNextSong());
prevButton.setOnClickListener(v -> MusicPlayerRemote.back());
}
private void updatePrevNextColor() {
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
prevButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
}
@Override
protected void show() {
playPauseFab.animate()
.scaleX(1f)
.scaleY(1f)
.rotation(360f)
.setInterpolator(new DecelerateInterpolator())
.start();
}
@Override
protected void hide() {
if (playPauseFab != null) {
playPauseFab.setScaleX(0f);
playPauseFab.setScaleY(0f);
playPauseFab.setRotation(0f);
}
}
@Override
protected void updateShuffleState() {
//TODO(Nothing to Implement)
}
@Override
protected void updateRepeatState() {
//TODO(Nothing to Implement)
}
@Override
protected void setUpProgressSlider() {
progressSlider.setOnSeekBarChangeListener(new SimpleOnSeekbarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
MusicPlayerRemote.seekTo(progress);
onUpdateProgressViews(MusicPlayerRemote.getSongProgressMillis(),
MusicPlayerRemote.getSongDurationMillis());
}
}
});
}
public void showBouceAnimation() {
playPauseFab.clearAnimation();
playPauseFab.setScaleX(0.9f);
playPauseFab.setScaleY(0.9f);
playPauseFab.setVisibility(View.VISIBLE);
playPauseFab.setPivotX(playPauseFab.getWidth() / 2);
playPauseFab.setPivotY(playPauseFab.getHeight() / 2);
playPauseFab.animate()
.setDuration(200)
.setInterpolator(new DecelerateInterpolator())
.scaleX(1.1f)
.scaleY(1.1f)
.withEndAction(() -> playPauseFab.animate()
.setDuration(200)
.setInterpolator(new AccelerateInterpolator())
.scaleX(1f)
.scaleY(1f)
.alpha(1f)
.start())
.start();
}
protected void updatePlayPauseDrawableState(boolean animate) {
if (MusicPlayerRemote.isPlaying()) {
playPauseFab.setImageResource(R.drawable.ic_pause_white_24dp);
} else {
playPauseFab.setImageResource(R.drawable.ic_play_arrow_white_24dp);
}
}
@OnClick(R.id.player_play_pause_button)
void showAnimation() {
if (MusicPlayerRemote.isPlaying()) {
MusicPlayerRemote.pauseSong();
} else {
MusicPlayerRemote.resumePlaying();
}
showBouceAnimation();
}
@Override
public void onUpdateProgressViews(int progress, int total) {
progressSlider.setMax(total);
ObjectAnimator animator = ObjectAnimator.ofInt(progressSlider, "progress", progress);
animator.setDuration(1500);
animator.setInterpolator(new LinearInterpolator());
animator.start();
songTotalTime.setText(MusicUtil.getReadableDurationString(total));
songCurrentProgress.setText(MusicUtil.getReadableDurationString(progress));
}
}

View file

@ -0,0 +1,273 @@
package code.name.monkey.retromusic.ui.fragments.player.material;
import android.animation.ObjectAnimator;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.AppCompatSeekBar;
import android.support.v7.widget.AppCompatTextView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper;
import code.name.monkey.retromusic.helper.PlayPauseButtonOnClickHandler;
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.service.MusicService;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerControlsFragment;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
/**
* @author Hemanth S (h4h13).
*/
public class MaterialControlsFragment extends AbsPlayerControlsFragment {
@BindView(R.id.player_play_pause_button)
ImageButton playPauseFab;
@BindView(R.id.player_prev_button)
ImageButton prevButton;
@BindView(R.id.player_next_button)
ImageButton nextButton;
@BindView(R.id.player_repeat_button)
ImageButton repeatButton;
@BindView(R.id.player_shuffle_button)
ImageButton shuffleButton;
@BindView(R.id.player_progress_slider)
AppCompatSeekBar progressSlider;
@BindView(R.id.player_song_total_time)
TextView songTotalTime;
@BindView(R.id.player_song_current_progress)
TextView songCurrentProgress;
@BindView(R.id.title)
AppCompatTextView title;
@BindView(R.id.text)
TextView text;
@BindView(R.id.volume_fragment_container)
View mVolumeContainer;
private Unbinder unbinder;
private int lastPlaybackControlsColor;
private int lastDisabledPlaybackControlsColor;
private MusicProgressViewUpdateHelper progressViewUpdateHelper;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressViewUpdateHelper = new MusicProgressViewUpdateHelper(this);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_material_playback_controls, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
unbinder = ButterKnife.bind(this, view);
setUpMusicControllers();
if (PreferenceUtil.getInstance(getContext()).getVolumeToggle()) {
mVolumeContainer.setVisibility(View.VISIBLE);
} else {
mVolumeContainer.setVisibility(View.GONE);
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
private void updateSong() {
Song song = MusicPlayerRemote.getCurrentSong();
title.setText(song.title);
text.setText(song.artistName);
}
@Override
public void onResume() {
super.onResume();
progressViewUpdateHelper.start();
}
@Override
public void onPause() {
super.onPause();
progressViewUpdateHelper.stop();
}
@Override
public void onServiceConnected() {
updatePlayPauseDrawableState();
updateRepeatState();
updateShuffleState();
updateSong();
}
@Override
public void onPlayingMetaChanged() {
super.onPlayingMetaChanged();
updateSong();
}
@Override
public void onPlayStateChanged() {
updatePlayPauseDrawableState();
}
@Override
public void onRepeatModeChanged() {
updateRepeatState();
}
@Override
public void onShuffleModeChanged() {
updateShuffleState();
}
@Override
public void setDark(int dark) {
int color = ATHUtil.resolveColor(getActivity(), android.R.attr.colorBackground);
if (ColorUtil.isColorLight(color)) {
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(getActivity(), true);
lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(getActivity(), true);
} else {
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(getActivity(), false);
lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(getActivity(), false);
}
updatePlayPauseColor();
updateRepeatState();
updateShuffleState();
updatePrevNextColor();
}
private void setUpPlayPauseFab() {
playPauseFab.setOnClickListener(new PlayPauseButtonOnClickHandler());
}
protected void updatePlayPauseDrawableState() {
if (MusicPlayerRemote.isPlaying()) {
playPauseFab.setImageResource(R.drawable.ic_pause_white_big);
} else {
playPauseFab.setImageResource(R.drawable.ic_play_arrow_white_big);
}
}
private void setUpMusicControllers() {
setUpPlayPauseFab();
setUpPrevNext();
setUpRepeatButton();
setUpShuffleButton();
setUpProgressSlider();
}
private void setUpPrevNext() {
updatePrevNextColor();
nextButton.setOnClickListener(v -> MusicPlayerRemote.playNextSong());
prevButton.setOnClickListener(v -> MusicPlayerRemote.back());
}
private void updatePrevNextColor() {
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
prevButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
}
private void updatePlayPauseColor() {
playPauseFab.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
}
private void setUpShuffleButton() {
shuffleButton.setOnClickListener(v -> MusicPlayerRemote.toggleShuffleMode());
}
@Override
protected void updateShuffleState() {
switch (MusicPlayerRemote.getShuffleMode()) {
case MusicService.SHUFFLE_MODE_SHUFFLE:
shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
default:
shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
private void setUpRepeatButton() {
repeatButton.setOnClickListener(v -> MusicPlayerRemote.cycleRepeatMode());
}
@Override
protected void updateRepeatState() {
switch (MusicPlayerRemote.getRepeatMode()) {
case MusicService.REPEAT_MODE_NONE:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_ALL:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_THIS:
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp);
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
@Override
protected void show() {
}
@Override
protected void hide() {
}
@Override
protected void setUpProgressSlider() {
progressSlider.setOnSeekBarChangeListener(new SimpleOnSeekbarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
MusicPlayerRemote.seekTo(progress);
onUpdateProgressViews(MusicPlayerRemote.getSongProgressMillis(),
MusicPlayerRemote.getSongDurationMillis());
}
}
});
}
@Override
public void onUpdateProgressViews(int progress, int total) {
progressSlider.setMax(total);
ObjectAnimator animator = ObjectAnimator.ofInt(progressSlider, "progress", progress);
animator.setDuration(1500);
animator.setInterpolator(new LinearInterpolator());
animator.start();
songTotalTime.setText(MusicUtil.getReadableDurationString(total));
songCurrentProgress.setText(MusicUtil.getReadableDurationString(progress));
}
}

View file

@ -0,0 +1,153 @@
package code.name.monkey.retromusic.ui.fragments.player.material;
import android.os.Bundle;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerFragment;
import code.name.monkey.retromusic.ui.fragments.player.PlayerAlbumCoverFragment;
import code.name.monkey.retromusic.ui.fragments.player.normal.PlayerFragment;
/**
* @author Hemanth S (h4h13).
*/
public class MaterialFragment extends AbsPlayerFragment implements PlayerAlbumCoverFragment.Callbacks {
@BindView(R.id.player_toolbar)
Toolbar toolbar;
@BindView(R.id.status_bar)
View statusBar;
private int lastColor;
private MaterialControlsFragment playbackControlsFragment;
private Unbinder unbinder;
public static PlayerFragment newInstance() {
Bundle args = new Bundle();
PlayerFragment fragment = new PlayerFragment();
fragment.setArguments(args);
return fragment;
}
@Override
@ColorInt
public int getPaletteColor() {
return lastColor;
}
@Override
public void onShow() {
playbackControlsFragment.show();
}
@Override
public void onHide() {
playbackControlsFragment.hide();
onBackPressed();
}
@Override
public boolean onBackPressed() {
return false;
}
@Override
public Toolbar getToolbar() {
return toolbar;
}
@Override
public int toolbarIconColor() {
return ATHUtil.resolveColor(getContext(), R.attr.iconColor);
}
@Override
public void onColorChanged(int color) {
playbackControlsFragment.setDark(color);
lastColor = color;
getCallbacks().onPaletteColorChanged();
ToolbarContentTintHelper.colorizeToolbar(toolbar,
ATHUtil.resolveColor(getContext(), R.attr.iconColor), getActivity());
}
@Override
protected void toggleFavorite(Song song) {
super.toggleFavorite(song);
if (song.id == MusicPlayerRemote.getCurrentSong().id) {
updateIsFavorite();
}
}
@Override
public void onFavoriteToggled() {
toggleFavorite(MusicPlayerRemote.getCurrentSong());
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_material, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
toggleStatusBar(statusBar);
setUpSubFragments();
setUpPlayerToolbar();
}
private void setUpSubFragments() {
playbackControlsFragment = (MaterialControlsFragment) getChildFragmentManager()
.findFragmentById(R.id.playback_controls_fragment);
PlayerAlbumCoverFragment playerAlbumCoverFragment =
(PlayerAlbumCoverFragment) getChildFragmentManager()
.findFragmentById(R.id.player_album_cover_fragment);
playerAlbumCoverFragment.setCallbacks(this);
}
private void setUpPlayerToolbar() {
toolbar.inflateMenu(R.menu.menu_player);
toolbar.setNavigationOnClickListener(v -> getActivity().onBackPressed());
toolbar.setOnMenuItemClickListener(this);
ToolbarContentTintHelper.colorizeToolbar(toolbar,
ATHUtil.resolveColor(getContext(), R.attr.iconColor), getActivity());
}
@Override
public void onServiceConnected() {
updateIsFavorite();
}
@Override
public void onPlayingMetaChanged() {
updateIsFavorite();
}
}

View file

@ -0,0 +1,181 @@
package code.name.monkey.retromusic.ui.fragments.player.normal;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerFragment;
import code.name.monkey.retromusic.ui.fragments.player.PlayerAlbumCoverFragment;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.util.ViewUtil;
import code.name.monkey.retromusic.views.DrawableGradient;
public class PlayerFragment extends AbsPlayerFragment implements PlayerAlbumCoverFragment.Callbacks {
@BindView(R.id.player_toolbar)
Toolbar toolbar;
@BindView(R.id.gradient_background)
View colorBackground;
@BindView(R.id.status_bar)
View statusBar;
private int lastColor;
private PlayerPlaybackControlsFragment playbackControlsFragment;
private Unbinder unbinder;
private ValueAnimator valueAnimator;
public static PlayerFragment newInstance() {
Bundle args = new Bundle();
PlayerFragment fragment = new PlayerFragment();
fragment.setArguments(args);
return fragment;
}
private void colorize(int i) {
if (valueAnimator != null) {
valueAnimator.cancel();
}
valueAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), android.R.color.transparent, i);
valueAnimator.addUpdateListener(animation -> {
GradientDrawable drawable = new DrawableGradient(GradientDrawable.Orientation.TOP_BOTTOM,
new int[]{(int) animation.getAnimatedValue(), android.R.color.transparent}, 0);
if (colorBackground != null) {
colorBackground.setBackground(drawable);
}
});
valueAnimator.setDuration(ViewUtil.RETRO_MUSIC_ANIM_TIME).start();
}
@Override
@ColorInt
public int getPaletteColor() {
return lastColor;
}
@Override
public void onShow() {
playbackControlsFragment.show();
}
@Override
public void onHide() {
playbackControlsFragment.hide();
onBackPressed();
}
@Override
public boolean onBackPressed() {
return false;
}
@Override
public Toolbar getToolbar() {
return toolbar;
}
@Override
public int toolbarIconColor() {
return ATHUtil.resolveColor(getContext(), R.attr.iconColor);
}
@Override
public void onColorChanged(int color) {
playbackControlsFragment.setDark(color);
lastColor = color;
getCallbacks().onPaletteColorChanged();
ToolbarContentTintHelper.colorizeToolbar(toolbar,
ATHUtil.resolveColor(getContext(), R.attr.iconColor), getActivity());
if (PreferenceUtil.getInstance(getContext()).getAdaptiveColor()) {
colorize(color);
}
}
@Override
protected void toggleFavorite(Song song) {
super.toggleFavorite(song);
if (song.id == MusicPlayerRemote.getCurrentSong().id) {
updateIsFavorite();
}
}
@Override
public void onFavoriteToggled() {
toggleFavorite(MusicPlayerRemote.getCurrentSong());
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_player, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
toggleStatusBar(statusBar);
setUpSubFragments();
setUpPlayerToolbar();
}
private void setUpSubFragments() {
playbackControlsFragment = (PlayerPlaybackControlsFragment) getChildFragmentManager()
.findFragmentById(R.id.playback_controls_fragment);
PlayerAlbumCoverFragment playerAlbumCoverFragment =
(PlayerAlbumCoverFragment) getChildFragmentManager()
.findFragmentById(R.id.player_album_cover_fragment);
playerAlbumCoverFragment.setCallbacks(this);
}
private void setUpPlayerToolbar() {
toolbar.inflateMenu(R.menu.menu_player);
toolbar.setNavigationOnClickListener(v -> getActivity().onBackPressed());
toolbar.setOnMenuItemClickListener(this);
ToolbarContentTintHelper.colorizeToolbar(toolbar,
ATHUtil.resolveColor(getContext(), R.attr.iconColor), getActivity());
}
@Override
public void onServiceConnected() {
updateIsFavorite();
}
@Override
public void onPlayingMetaChanged() {
updateIsFavorite();
}
}

View file

@ -0,0 +1,345 @@
package code.name.monkey.retromusic.ui.fragments.player.normal;
import android.animation.ObjectAnimator;
import android.graphics.PorterDuff;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.AppCompatSeekBar;
import android.support.v7.widget.AppCompatTextView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper;
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.service.MusicService;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerControlsFragment;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.views.PlayPauseDrawable;
public class PlayerPlaybackControlsFragment extends AbsPlayerControlsFragment {
@BindView(R.id.player_play_pause_button)
ImageButton playPauseFab;
@BindView(R.id.player_prev_button)
ImageButton prevButton;
@BindView(R.id.player_next_button)
ImageButton nextButton;
@BindView(R.id.player_repeat_button)
ImageButton repeatButton;
@BindView(R.id.player_shuffle_button)
ImageButton shuffleButton;
@BindView(R.id.player_progress_slider)
AppCompatSeekBar progressSlider;
@BindView(R.id.player_song_total_time)
TextView songTotalTime;
@BindView(R.id.player_song_current_progress)
TextView songCurrentProgress;
@BindView(R.id.title)
AppCompatTextView title;
@BindView(R.id.text)
TextView text;
@BindView(R.id.volume_fragment_container)
View mVolumeContainer;
private Unbinder unbinder;
private PlayPauseDrawable playerFabPlayPauseDrawable;
private int lastPlaybackControlsColor;
private int lastDisabledPlaybackControlsColor;
private MusicProgressViewUpdateHelper progressViewUpdateHelper;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressViewUpdateHelper = new MusicProgressViewUpdateHelper(this);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_player_playback_controls, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
unbinder = ButterKnife.bind(this, view);
setUpMusicControllers();
if (PreferenceUtil.getInstance(getContext()).getVolumeToggle()) {
mVolumeContainer.setVisibility(View.VISIBLE);
} else {
mVolumeContainer.setVisibility(View.GONE);
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
private void updateSong() {
Song song = MusicPlayerRemote.getCurrentSong();
title.setText(song.title);
text.setText(song.artistName);
}
@Override
public void onResume() {
super.onResume();
progressViewUpdateHelper.start();
}
@Override
public void onPause() {
super.onPause();
progressViewUpdateHelper.stop();
}
@Override
public void onServiceConnected() {
updatePlayPauseDrawableState(false);
updateRepeatState();
updateShuffleState();
updateSong();
}
@Override
public void onPlayingMetaChanged() {
super.onPlayingMetaChanged();
updateSong();
}
@Override
public void onPlayStateChanged() {
updatePlayPauseDrawableState(true);
}
@Override
public void onRepeatModeChanged() {
updateRepeatState();
}
@Override
public void onShuffleModeChanged() {
updateShuffleState();
}
@Override
public void setDark(int dark) {
int color = ATHUtil.resolveColor(getActivity(), android.R.attr.colorBackground);
if (ColorUtil.isColorLight(color)) {
lastPlaybackControlsColor = MaterialValueHelper.getSecondaryTextColor(getActivity(), true);
lastDisabledPlaybackControlsColor = MaterialValueHelper.getSecondaryDisabledTextColor(getActivity(), true);
} else {
lastPlaybackControlsColor = MaterialValueHelper.getPrimaryTextColor(getActivity(), false);
lastDisabledPlaybackControlsColor = MaterialValueHelper.getPrimaryDisabledTextColor(getActivity(), false);
}
if (PreferenceUtil.getInstance(getContext()).getAdaptiveColor()) {
setFabColor(dark);
} else {
setFabColor(ThemeStore.accentColor(getContext()));
}
updateRepeatState();
updateShuffleState();
updatePrevNextColor();
}
private void setFabColor(int i) {
TintHelper.setTintAuto(playPauseFab, MaterialValueHelper.getPrimaryTextColor(getContext(), ColorUtil.isColorLight(i)), false);
TintHelper.setTintAuto(playPauseFab, i, true);
setProgressBarColor(i);
}
public void setProgressBarColor(int newColor) {
LayerDrawable ld = (LayerDrawable) progressSlider.getProgressDrawable();
ClipDrawable clipDrawable = (ClipDrawable) ld.findDrawableByLayerId(android.R.id.progress);
clipDrawable.setColorFilter(newColor, PorterDuff.Mode.SRC_IN);
}
private void setUpPlayPauseFab() {
playerFabPlayPauseDrawable = new PlayPauseDrawable(getActivity());
playPauseFab.setImageDrawable(
playerFabPlayPauseDrawable); // Note: set the drawable AFTER TintHelper.setTintAuto() was called
//playPauseFab.setColorFilter(MaterialValueHelper.getPrimaryTextColor(getContext(), ColorUtil.isColorLight(fabColor)), PorterDuff.Mode.SRC_IN);
//playPauseFab.setOnClickListener(new PlayPauseButtonOnClickHandler());
playPauseFab.post(() -> {
if (playPauseFab != null) {
playPauseFab.setPivotX(playPauseFab.getWidth() / 2);
playPauseFab.setPivotY(playPauseFab.getHeight() / 2);
}
});
}
protected void updatePlayPauseDrawableState(boolean animate) {
if (MusicPlayerRemote.isPlaying()) {
playerFabPlayPauseDrawable.setPause(animate);
} else {
playerFabPlayPauseDrawable.setPlay(animate);
}
}
private void setUpMusicControllers() {
setUpPlayPauseFab();
setUpPrevNext();
setUpRepeatButton();
setUpShuffleButton();
setUpProgressSlider();
}
private void setUpPrevNext() {
updatePrevNextColor();
nextButton.setOnClickListener(v -> MusicPlayerRemote.playNextSong());
prevButton.setOnClickListener(v -> MusicPlayerRemote.back());
}
private void updatePrevNextColor() {
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
prevButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
}
private void setUpShuffleButton() {
shuffleButton.setOnClickListener(v -> MusicPlayerRemote.toggleShuffleMode());
}
@Override
protected void updateShuffleState() {
switch (MusicPlayerRemote.getShuffleMode()) {
case MusicService.SHUFFLE_MODE_SHUFFLE:
shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
default:
shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
private void setUpRepeatButton() {
repeatButton.setOnClickListener(v -> MusicPlayerRemote.cycleRepeatMode());
}
@Override
protected void updateRepeatState() {
switch (MusicPlayerRemote.getRepeatMode()) {
case MusicService.REPEAT_MODE_NONE:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_ALL:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_THIS:
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp);
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
@Override
protected void show() {
playPauseFab.animate()
.scaleX(1f)
.scaleY(1f)
.rotation(360f)
.setInterpolator(new DecelerateInterpolator())
.start();
}
@Override
protected void hide() {
if (playPauseFab != null) {
playPauseFab.setScaleX(0f);
playPauseFab.setScaleY(0f);
playPauseFab.setRotation(0f);
}
}
@Override
protected void setUpProgressSlider() {
progressSlider.setOnSeekBarChangeListener(new SimpleOnSeekbarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
MusicPlayerRemote.seekTo(progress);
onUpdateProgressViews(MusicPlayerRemote.getSongProgressMillis(),
MusicPlayerRemote.getSongDurationMillis());
}
}
});
}
public void showBouceAnimation() {
playPauseFab.clearAnimation();
playPauseFab.setScaleX(0.9f);
playPauseFab.setScaleY(0.9f);
playPauseFab.setVisibility(View.VISIBLE);
playPauseFab.setPivotX(playPauseFab.getWidth() / 2);
playPauseFab.setPivotY(playPauseFab.getHeight() / 2);
playPauseFab.animate()
.setDuration(200)
.setInterpolator(new DecelerateInterpolator())
.scaleX(1.1f)
.scaleY(1.1f)
.withEndAction(() -> playPauseFab.animate()
.setDuration(200)
.setInterpolator(new AccelerateInterpolator())
.scaleX(1f)
.scaleY(1f)
.alpha(1f)
.start())
.start();
}
@OnClick(R.id.player_play_pause_button)
void showAnimation() {
if (MusicPlayerRemote.isPlaying()) {
MusicPlayerRemote.pauseSong();
} else {
MusicPlayerRemote.resumePlaying();
}
showBouceAnimation();
}
@Override
public void onUpdateProgressViews(int progress, int total) {
progressSlider.setMax(total);
ObjectAnimator animator = ObjectAnimator.ofInt(progressSlider, "progress", progress);
animator.setDuration(1500);
animator.setInterpolator(new LinearInterpolator());
animator.start();
songTotalTime.setText(MusicUtil.getReadableDurationString(total));
songCurrentProgress.setText(MusicUtil.getReadableDurationString(progress));
}
}

View file

@ -0,0 +1,324 @@
package code.name.monkey.retromusic.ui.fragments.player.plain;
import android.animation.ObjectAnimator;
import android.graphics.PorterDuff;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.retromusic.misc.SimpleOnSeekbarChangeListener;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper;
import code.name.monkey.retromusic.service.MusicService;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerControlsFragment;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.views.PlayPauseDrawable;
/**
* @author Hemanth S (h4h13).
*/
public class PlainPlaybackControlsFragment extends AbsPlayerControlsFragment {
@BindView(R.id.player_play_pause_button)
ImageButton playPauseFab;
@BindView(R.id.player_prev_button)
ImageButton prevButton;
@BindView(R.id.player_next_button)
ImageButton nextButton;
@BindView(R.id.player_repeat_button)
ImageButton repeatButton;
@BindView(R.id.player_shuffle_button)
ImageButton shuffleButton;
@BindView(R.id.player_progress_slider)
SeekBar progressSlider;
@BindView(R.id.player_song_total_time)
TextView songTotalTime;
@BindView(R.id.player_song_current_progress)
TextView songCurrentProgress;
@BindView(R.id.volume_fragment_container)
View volumeContainer;
private Unbinder unbinder;
private PlayPauseDrawable playerFabPlayPauseDrawable;
private int lastPlaybackControlsColor;
private int lastDisabledPlaybackControlsColor;
private MusicProgressViewUpdateHelper progressViewUpdateHelper;
@Override
public void onPlayStateChanged() {
updatePlayPauseDrawableState(true);
}
@Override
public void onRepeatModeChanged() {
updateRepeatState();
}
@Override
public void onShuffleModeChanged() {
updateShuffleState();
}
@Override
public void onServiceConnected() {
updatePlayPauseDrawableState(false);
updateRepeatState();
updateShuffleState();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressViewUpdateHelper = new MusicProgressViewUpdateHelper(this);
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_plain_controls_fragment, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onResume() {
super.onResume();
progressViewUpdateHelper.start();
}
@Override
public void onPause() {
super.onPause();
progressViewUpdateHelper.stop();
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setUpMusicControllers();
if (PreferenceUtil.getInstance(getContext()).getVolumeToggle()) {
volumeContainer.setVisibility(View.VISIBLE);
} else {
volumeContainer.setVisibility(View.GONE);
}
}
private void setUpMusicControllers() {
setUpPlayPauseFab();
setUpPrevNext();
setUpRepeatButton();
setUpShuffleButton();
setUpProgressSlider();
}
private void setUpPrevNext() {
updatePrevNextColor();
nextButton.setOnClickListener(v -> MusicPlayerRemote.playNextSong());
prevButton.setOnClickListener(v -> MusicPlayerRemote.back());
}
private void updatePrevNextColor() {
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
prevButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
}
private void setUpShuffleButton() {
shuffleButton.setOnClickListener(v -> MusicPlayerRemote.toggleShuffleMode());
}
@Override
protected void updateShuffleState() {
switch (MusicPlayerRemote.getShuffleMode()) {
case MusicService.SHUFFLE_MODE_SHUFFLE:
shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
default:
shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
private void setUpRepeatButton() {
repeatButton.setOnClickListener(v -> MusicPlayerRemote.cycleRepeatMode());
}
@Override
protected void updateRepeatState() {
switch (MusicPlayerRemote.getRepeatMode()) {
case MusicService.REPEAT_MODE_NONE:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_ALL:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_THIS:
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp);
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
@Override
protected void show() {
playPauseFab.animate()
.scaleX(1f)
.scaleY(1f)
.rotation(360f)
.setInterpolator(new DecelerateInterpolator())
.start();
}
@Override
protected void hide() {
if (playPauseFab != null) {
playPauseFab.setScaleX(0f);
playPauseFab.setScaleY(0f);
playPauseFab.setRotation(0f);
}
}
@Override
protected void setUpProgressSlider() {
progressSlider.setOnSeekBarChangeListener(new SimpleOnSeekbarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
MusicPlayerRemote.seekTo(progress);
onUpdateProgressViews(MusicPlayerRemote.getSongProgressMillis(), MusicPlayerRemote.getSongDurationMillis());
}
}
});
}
public void showBouceAnimation() {
playPauseFab.clearAnimation();
playPauseFab.setScaleX(0.9f);
playPauseFab.setScaleY(0.9f);
playPauseFab.setVisibility(View.VISIBLE);
playPauseFab.setPivotX(playPauseFab.getWidth() / 2);
playPauseFab.setPivotY(playPauseFab.getHeight() / 2);
playPauseFab.animate()
.setDuration(200)
.setInterpolator(new DecelerateInterpolator())
.scaleX(1.1f)
.scaleY(1.1f)
.withEndAction(() -> playPauseFab.animate()
.setDuration(200)
.setInterpolator(new AccelerateInterpolator())
.scaleX(1f)
.scaleY(1f)
.alpha(1f)
.start())
.start();
}
@OnClick(R.id.player_play_pause_button)
void showAnimation() {
if (MusicPlayerRemote.isPlaying()) {
MusicPlayerRemote.pauseSong();
} else {
MusicPlayerRemote.resumePlaying();
}
showBouceAnimation();
}
@Override
public void onUpdateProgressViews(int progress, int total) {
progressSlider.setMax(total);
ObjectAnimator animator = ObjectAnimator.ofInt(progressSlider, "progress", progress);
animator.setDuration(1500);
animator.setInterpolator(new LinearInterpolator());
animator.start();
songTotalTime.setText(MusicUtil.getReadableDurationString(total));
songCurrentProgress.setText(MusicUtil.getReadableDurationString(progress));
}
@Override
public void setDark(int dark) {
int color = ATHUtil.resolveColor(getActivity(), android.R.attr.colorBackground);
if (ColorUtil.isColorLight(color)) {
lastPlaybackControlsColor =
MaterialValueHelper.getSecondaryTextColor(getActivity(), true);
lastDisabledPlaybackControlsColor =
MaterialValueHelper.getSecondaryDisabledTextColor(getActivity(), true);
} else {
lastPlaybackControlsColor =
MaterialValueHelper.getPrimaryTextColor(getActivity(), false);
lastDisabledPlaybackControlsColor =
MaterialValueHelper.getPrimaryDisabledTextColor(getActivity(), false);
}
if (PreferenceUtil.getInstance(getContext()).getAdaptiveColor()) {
TintHelper.setTintAuto(playPauseFab, MaterialValueHelper.getPrimaryTextColor(getContext(), ColorUtil.isColorLight(dark)), false);
TintHelper.setTintAuto(playPauseFab, dark, true);
setProgressBarColor(progressSlider, dark);
}
updateRepeatState();
updateShuffleState();
updatePrevNextColor();
}
public void setProgressBarColor(SeekBar progressBar, int newColor) {
LayerDrawable ld = (LayerDrawable) progressBar.getProgressDrawable();
ClipDrawable clipDrawable = (ClipDrawable) ld.findDrawableByLayerId(android.R.id.progress);
clipDrawable.setColorFilter(newColor, PorterDuff.Mode.SRC_IN);
}
private void setUpPlayPauseFab() {
playerFabPlayPauseDrawable = new PlayPauseDrawable(getActivity());
playPauseFab.setImageDrawable(playerFabPlayPauseDrawable); // Note: set the drawable AFTER TintHelper.setTintAuto() was called
//playPauseFab.setColorFilter(MaterialValueHelper.getPrimaryTextColor(getContext(), ColorUtil.isColorLight(fabColor)), PorterDuff.Mode.SRC_IN);
//playPauseFab.setOnClickListener(new PlayPauseButtonOnClickHandler());
playPauseFab.post(() -> {
if (playPauseFab != null) {
playPauseFab.setPivotX(playPauseFab.getWidth() / 2);
playPauseFab.setPivotY(playPauseFab.getHeight() / 2);
}
});
}
protected void updatePlayPauseDrawableState(boolean animate) {
if (MusicPlayerRemote.isPlaying()) {
playerFabPlayPauseDrawable.setPause(animate);
} else {
playerFabPlayPauseDrawable.setPlay(animate);
}
}
}

View file

@ -0,0 +1,158 @@
package code.name.monkey.retromusic.ui.fragments.player.plain;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerFragment;
import code.name.monkey.retromusic.ui.fragments.player.PlayerAlbumCoverFragment;
/**
* @author Hemanth S (h4h13).
*/
public class PlainPlayerFragment extends AbsPlayerFragment implements
PlayerAlbumCoverFragment.Callbacks {
@BindView(R.id.title)
TextView title;
@BindView(R.id.text)
TextView text;
@BindView(R.id.player_toolbar)
Toolbar toolbar;
@BindView(R.id.toolbar_container)
FrameLayout toolbarContainer;
@BindView(R.id.status_bar)
View statusBar;
private Unbinder unbinder;
private PlainPlaybackControlsFragment plainPlaybackControlsFragment;
private int mLastColor;
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Override
public void onPlayingMetaChanged() {
super.onPlayingMetaChanged();
updateSong();
}
private void updateSong() {
Song song = MusicPlayerRemote.getCurrentSong();
title.setText(song.title);
text.setText(song.artistName);
}
@Override
public void onServiceConnected() {
super.onServiceConnected();
updateSong();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_plain_player, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
private void setUpPlayerToolbar() {
toolbar.inflateMenu(R.menu.menu_player);
toolbar.setNavigationOnClickListener(v -> getActivity().onBackPressed());
toolbar.setOnMenuItemClickListener(this);
ToolbarContentTintHelper.colorizeToolbar(toolbar,
ATHUtil.resolveColor(getContext(), R.attr.iconColor),
getActivity());
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
toggleStatusBar(statusBar);
setUpSubFragments();
setUpPlayerToolbar();
title.setSelected(true);
}
private void setUpSubFragments() {
plainPlaybackControlsFragment = (PlainPlaybackControlsFragment) getChildFragmentManager()
.findFragmentById(R.id.playback_controls_fragment);
PlayerAlbumCoverFragment playerAlbumCoverFragment = (PlayerAlbumCoverFragment) getChildFragmentManager()
.findFragmentById(R.id.player_album_cover_fragment);
playerAlbumCoverFragment.setCallbacks(this);
}
@Override
public int getPaletteColor() {
return mLastColor;
}
@Override
public void onShow() {
plainPlaybackControlsFragment.show();
}
@Override
public void onHide() {
plainPlaybackControlsFragment.hide();
onBackPressed();
}
@Override
public boolean onBackPressed() {
return false;
}
@Override
public Toolbar getToolbar() {
return toolbar;
}
@Override
public int toolbarIconColor() {
return ATHUtil.resolveColor(getContext(), R.attr.iconColor);
}
@Override
public void onColorChanged(int color) {
plainPlaybackControlsFragment.setDark(color);
mLastColor = color;
getCallbacks().onPaletteColorChanged();
ToolbarContentTintHelper.colorizeToolbar(toolbar,
ATHUtil.resolveColor(getContext(), R.attr.iconColor), getActivity());
}
@Override
public void onFavoriteToggled() {
toggleFavorite(MusicPlayerRemote.getCurrentSong());
}
@Override
protected void toggleFavorite(Song song) {
super.toggleFavorite(song);
if (song.id == MusicPlayerRemote.getCurrentSong().id) {
updateIsFavorite();
}
}
}

View file

@ -0,0 +1,319 @@
package code.name.monkey.retromusic.ui.fragments.player.simple;
import android.graphics.PorterDuff;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.MaterialValueHelper;
import code.name.monkey.appthemehelper.util.TintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.helper.MusicProgressViewUpdateHelper;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.service.MusicService;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerControlsFragment;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.views.PlayPauseDrawable;
/**
* @author Hemanth S (h4h13).
*/
public class SimplePlaybackControlsFragment extends AbsPlayerControlsFragment {
@BindView(R.id.player_play_pause_button)
ImageButton playPauseFab;
@BindView(R.id.player_prev_button)
ImageButton prevButton;
@BindView(R.id.player_next_button)
ImageButton nextButton;
@BindView(R.id.player_repeat_button)
ImageButton repeatButton;
@BindView(R.id.player_shuffle_button)
ImageButton shuffleButton;
@BindView(R.id.player_song_current_progress)
TextView songCurrentProgress;
@BindView(R.id.volume_fragment_container)
View volumeContainer;
@BindView(R.id.title)
TextView title;
@BindView(R.id.text)
TextView text;
private Unbinder unbinder;
private PlayPauseDrawable playerFabPlayPauseDrawable;
private int lastPlaybackControlsColor;
private int lastDisabledPlaybackControlsColor;
private MusicProgressViewUpdateHelper progressViewUpdateHelper;
@Override
public void onPlayStateChanged() {
updatePlayPauseDrawableState(true);
}
@Override
public void onRepeatModeChanged() {
updateRepeatState();
}
@Override
public void onShuffleModeChanged() {
updateShuffleState();
}
@Override
public void onServiceConnected() {
updatePlayPauseDrawableState(false);
updateRepeatState();
updateShuffleState();
updateSong();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressViewUpdateHelper = new MusicProgressViewUpdateHelper(this);
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_simple_controls_fragment, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onResume() {
super.onResume();
progressViewUpdateHelper.start();
}
@Override
public void onPause() {
super.onPause();
progressViewUpdateHelper.stop();
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setUpMusicControllers();
volumeContainer.setVisibility(PreferenceUtil.getInstance(getContext()).getVolumeToggle() ? View.VISIBLE : View.GONE);
}
private void setUpMusicControllers() {
setUpPlayPauseFab();
setUpPrevNext();
setUpRepeatButton();
setUpShuffleButton();
setUpProgressSlider();
}
private void setUpPrevNext() {
updatePrevNextColor();
nextButton.setOnClickListener(v -> MusicPlayerRemote.playNextSong());
prevButton.setOnClickListener(v -> MusicPlayerRemote.back());
}
private void updatePrevNextColor() {
nextButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
prevButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
}
private void setUpShuffleButton() {
shuffleButton.setOnClickListener(v -> MusicPlayerRemote.toggleShuffleMode());
}
@Override
protected void updateShuffleState() {
switch (MusicPlayerRemote.getShuffleMode()) {
case MusicService.SHUFFLE_MODE_SHUFFLE:
shuffleButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
default:
shuffleButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
private void setUpRepeatButton() {
repeatButton.setOnClickListener(v -> MusicPlayerRemote.cycleRepeatMode());
}
@Override
protected void updateRepeatState() {
switch (MusicPlayerRemote.getRepeatMode()) {
case MusicService.REPEAT_MODE_NONE:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(lastDisabledPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_ALL:
repeatButton.setImageResource(R.drawable.ic_repeat_white_24dp);
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
case MusicService.REPEAT_MODE_THIS:
repeatButton.setImageResource(R.drawable.ic_repeat_one_white_24dp);
repeatButton.setColorFilter(lastPlaybackControlsColor, PorterDuff.Mode.SRC_IN);
break;
}
}
private void updateSong() {
Song song = MusicPlayerRemote.getCurrentSong();
title.setText(song.title);
text.setText(song.artistName);
}
@Override
public void onPlayingMetaChanged() {
super.onPlayingMetaChanged();
updateSong();
}
@Override
protected void setUpProgressSlider() {
}
@Override
protected void show() {
playPauseFab.animate()
.scaleX(1f)
.scaleY(1f)
.rotation(360f)
.setInterpolator(new DecelerateInterpolator())
.start();
}
@Override
protected void hide() {
if (playPauseFab != null) {
playPauseFab.setScaleX(0f);
playPauseFab.setScaleY(0f);
playPauseFab.setRotation(0f);
}
}
public void showBouceAnimation() {
playPauseFab.clearAnimation();
playPauseFab.setScaleX(0.9f);
playPauseFab.setScaleY(0.9f);
playPauseFab.setVisibility(View.VISIBLE);
playPauseFab.setPivotX(playPauseFab.getWidth() / 2);
playPauseFab.setPivotY(playPauseFab.getHeight() / 2);
playPauseFab.animate()
.setDuration(200)
.setInterpolator(new DecelerateInterpolator())
.scaleX(1.1f)
.scaleY(1.1f)
.withEndAction(() -> playPauseFab.animate()
.setDuration(200)
.setInterpolator(new AccelerateInterpolator())
.scaleX(1f)
.scaleY(1f)
.alpha(1f)
.start())
.start();
}
@OnClick(R.id.player_play_pause_button)
void showAnimation() {
if (MusicPlayerRemote.isPlaying()) {
MusicPlayerRemote.pauseSong();
} else {
MusicPlayerRemote.resumePlaying();
}
showBouceAnimation();
}
@Override
public void onUpdateProgressViews(int progress, int total) {
songCurrentProgress.setText(String.format("%s / %s", MusicUtil.getReadableDurationString(progress),
MusicUtil.getReadableDurationString(total)));
}
@Override
public void setDark(int dark) {
int color = ATHUtil.resolveColor(getActivity(), android.R.attr.colorBackground);
if (ColorUtil.isColorLight(color)) {
lastPlaybackControlsColor = MaterialValueHelper
.getSecondaryTextColor(getActivity(), true);
lastDisabledPlaybackControlsColor = MaterialValueHelper
.getSecondaryDisabledTextColor(getActivity(), true);
} else {
lastPlaybackControlsColor = MaterialValueHelper
.getPrimaryTextColor(getActivity(), false);
lastDisabledPlaybackControlsColor = MaterialValueHelper
.getPrimaryDisabledTextColor(getActivity(), false);
}
if (PreferenceUtil.getInstance(getContext()).getAdaptiveColor()) {
TintHelper.setTintAuto(playPauseFab, MaterialValueHelper.getPrimaryTextColor(getContext(), ColorUtil.isColorLight(dark)), false);
TintHelper.setTintAuto(playPauseFab, dark, true);
text.setTextColor(dark);
} else {
text.setTextColor(ThemeStore.accentColor(getContext()));
}
updateRepeatState();
updateShuffleState();
updatePrevNextColor();
}
public void setProgressBarColor(SeekBar progressBar, int newColor) {
LayerDrawable ld = (LayerDrawable) progressBar.getProgressDrawable();
ClipDrawable clipDrawable = (ClipDrawable) ld.findDrawableByLayerId(android.R.id.progress);
clipDrawable.setColorFilter(newColor, PorterDuff.Mode.SRC_IN);
}
private void setUpPlayPauseFab() {
playerFabPlayPauseDrawable = new PlayPauseDrawable(getActivity());
playPauseFab.setImageDrawable(playerFabPlayPauseDrawable); // Note: set the drawable AFTER TintHelper.setTintAuto() was called
//playPauseFab.setColorFilter(MaterialValueHelper.getPrimaryTextColor(getContext(), ColorUtil.isColorLight(fabColor)), PorterDuff.Mode.SRC_IN);
//playPauseFab.setOnClickListener(new PlayPauseButtonOnClickHandler());
playPauseFab.post(() -> {
if (playPauseFab != null) {
playPauseFab.setPivotX(playPauseFab.getWidth() / 2);
playPauseFab.setPivotY(playPauseFab.getHeight() / 2);
}
});
}
protected void updatePlayPauseDrawableState(boolean animate) {
if (MusicPlayerRemote.isPlaying()) {
playerFabPlayPauseDrawable.setPause(animate);
} else {
playerFabPlayPauseDrawable.setPlay(animate);
}
}
}

View file

@ -0,0 +1,132 @@
package code.name.monkey.retromusic.ui.fragments.player.simple;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.util.ATHUtil;
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.ui.fragments.base.AbsPlayerFragment;
import code.name.monkey.retromusic.ui.fragments.player.PlayerAlbumCoverFragment;
/**
* @author Hemanth S (h4h13).
*/
public class SimplePlayerFragment extends AbsPlayerFragment implements
PlayerAlbumCoverFragment.Callbacks {
@BindView(R.id.player_toolbar)
Toolbar toolbar;
@BindView(R.id.status_bar)
View statusBar;
private Unbinder unbinder;
private SimplePlaybackControlsFragment simplePlaybackControlsFragment;
private int lastColor;
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_simple_player, container, false);
unbinder = ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
toggleStatusBar(statusBar);
setUpSubFragments();
setUpPlayerToolbar();
}
private void setUpSubFragments() {
PlayerAlbumCoverFragment playerAlbumCoverFragment = (PlayerAlbumCoverFragment)
getChildFragmentManager().findFragmentById(R.id.player_album_cover_fragment);
playerAlbumCoverFragment.setCallbacks(this);
simplePlaybackControlsFragment = (SimplePlaybackControlsFragment)
getChildFragmentManager().findFragmentById(R.id.playback_controls_fragment);
}
@Override
public int getPaletteColor() {
return lastColor;
}
@Override
public void onShow() {
simplePlaybackControlsFragment.show();
}
@Override
public void onHide() {
simplePlaybackControlsFragment.hide();
}
@Override
public boolean onBackPressed() {
return false;
}
@Override
public Toolbar getToolbar() {
return toolbar;
}
@Override
public int toolbarIconColor() {
return ATHUtil.resolveColor(getContext(), R.attr.iconColor);
}
@Override
public void onColorChanged(int color) {
lastColor = color;
getCallbacks().onPaletteColorChanged();
simplePlaybackControlsFragment.setDark(color);
ToolbarContentTintHelper.colorizeToolbar(toolbar,
ATHUtil.resolveColor(getContext(), R.attr.iconColor), getActivity());
}
@Override
public void onFavoriteToggled() {
toggleFavorite(MusicPlayerRemote.getCurrentSong());
}
@Override
protected void toggleFavorite(Song song) {
super.toggleFavorite(song);
if (song.id == MusicPlayerRemote.getCurrentSong().id) {
updateIsFavorite();
}
}
private void setUpPlayerToolbar() {
toolbar.inflateMenu(R.menu.menu_player);
toolbar.setNavigationOnClickListener(v -> getActivity().onBackPressed());
toolbar.setOnMenuItemClickListener(this);
ToolbarContentTintHelper.colorizeToolbar(toolbar,
ATHUtil.resolveColor(getContext(), R.attr.iconColor),
getActivity());
}
}

View file

@ -0,0 +1,89 @@
package code.name.monkey.retromusic.ui.fragments.settings;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Toast;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEPreferenceFragmentCompat;
import code.name.monkey.retromusic.preferences.BlacklistPreference;
import code.name.monkey.retromusic.preferences.BlacklistPreferenceDialog;
import code.name.monkey.retromusic.preferences.NowPlayingScreenPreference;
import code.name.monkey.retromusic.preferences.NowPlayingScreenPreferenceDialog;
import code.name.monkey.retromusic.ui.activities.SettingsActivity;
import code.name.monkey.retromusic.util.DensityUtil;
import code.name.monkey.retromusic.util.NavigationUtil;
/**
* @author Hemanth S (h4h13).
*/
public abstract class AbsSettingsFragment extends ATEPreferenceFragmentCompat {
protected void showProToastAndNavigate(String message) {
Toast.makeText(getContext(), message + " is Pro version feature.", Toast.LENGTH_SHORT).show();
//noinspection ConstantConditions
NavigationUtil.goToProVersion(getActivity());
}
protected void setSummary(@NonNull Preference preference) {
setSummary(preference, PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getString(preference.getKey(), ""));
}
protected void setSummary(Preference preference, @NonNull Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) {
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue);
preference.setSummary(index >= 0 ? listPreference.getEntries()[index] : null);
} else {
preference.setSummary(stringValue);
}
}
public abstract void invalidateSettings();
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setDividerHeight(0);
setDivider(new ColorDrawable(Color.TRANSPARENT));
getListView().setPadding(DensityUtil.dip2px(getContext(), 0), 0, 0, 0);
getListView().addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (getActivity() != null) {
((SettingsActivity) getActivity())
.addAppbarLayoutElevation(recyclerView.canScrollVertically(RecyclerView.NO_POSITION) ? 8f : 0f);
}
}
});
//noinspection ConstantConditions
getListView().setBackgroundColor(ThemeStore.primaryColor(getContext()));
getListView().setOverScrollMode(View.OVER_SCROLL_NEVER);
invalidateSettings();
}
@Nullable
@Override
public DialogFragment onCreatePreferenceDialog(Preference preference) {
if (preference instanceof NowPlayingScreenPreference) {
return NowPlayingScreenPreferenceDialog.newInstance();
} else if (preference instanceof BlacklistPreference) {
return BlacklistPreferenceDialog.newInstance();
}
return super.onCreatePreferenceDialog(preference);
}
}

View file

@ -0,0 +1,49 @@
package code.name.monkey.retromusic.ui.fragments.settings;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.media.audiofx.AudioEffect;
import android.os.Bundle;
import android.support.v7.preference.Preference;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.util.NavigationUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
/**
* @author Hemanth S (h4h13).
*/
public class AudioSettings extends AbsSettingsFragment {
@Override
public void invalidateSettings() {
Preference findPreference = findPreference("equalizer");
if (!hasEqualizer() && !PreferenceUtil.getInstance(getContext()).getSelectedEqualizer().equals("retro")) {
findPreference.setEnabled(false);
findPreference.setSummary(getResources().getString(R.string.no_equalizer));
} else {
findPreference.setEnabled(true);
}
findPreference.setOnPreferenceClickListener(preference -> {
//noinspection ConstantConditions
NavigationUtil.openEqualizer(getActivity());
return true;
});
}
private boolean hasEqualizer() {
final Intent effects = new Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL);
//noinspection ConstantConditions
PackageManager pm = getActivity().getPackageManager();
ResolveInfo ri = pm.resolveActivity(effects, 0);
return ri != null;
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.pref_audio);
}
}

View file

@ -0,0 +1,28 @@
package code.name.monkey.retromusic.ui.fragments.settings;
import android.os.Bundle;
import android.support.v7.preference.Preference;
import code.name.monkey.retromusic.R;
/**
* @author Hemanth S (h4h13).
*/
public class ImageSettingFragment extends AbsSettingsFragment {
@Override
public void invalidateSettings() {
final Preference autoDownloadImagesPolicy = findPreference("auto_download_images_policy");
setSummary(autoDownloadImagesPolicy);
autoDownloadImagesPolicy.setOnPreferenceChangeListener((preference, o) -> {
setSummary(autoDownloadImagesPolicy, o);
return true;
});
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.pref_images);
}
}

View file

@ -0,0 +1,85 @@
package code.name.monkey.retromusic.ui.fragments.settings;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
import butterknife.BindView;
import butterknife.BindViews;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.ui.activities.SettingsActivity;
import code.name.monkey.retromusic.views.IconImageView;
public class MainSettingsFragment extends Fragment {
Unbinder unbinder;
@BindViews({R.id.general_settings_icon, R.id.audio_settings_icon,
R.id.now_playing_settings_icon, R.id.image_settings_icon,
R.id.notification_settings_icon, R.id.other_settings_icon})
List<IconImageView> icons;
ButterKnife.Action<View> apply = (view, index) -> {
//noinspection ConstantConditions
((IconImageView) view).setColorFilter(ThemeStore.accentColor(getContext()), PorterDuff.Mode.SRC_IN);
};
@BindView(R.id.container)
ViewGroup container;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.fragment_main_settings, container, false);
unbinder = ButterKnife.bind(this, layout);
ButterKnife.apply(icons, apply);
return layout;
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
@OnClick({R.id.general_settings, R.id.audio_settings, R.id.now_playing_settings,
R.id.image_settings, R.id.notification_settings, R.id.other_settings})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.general_settings:
inflateFragment(new ThemeSettingsFragment());
break;
case R.id.audio_settings:
inflateFragment(new AudioSettings());
break;
case R.id.now_playing_settings:
inflateFragment(new NowPlayingSettingsFragment());
break;
case R.id.image_settings:
inflateFragment(new ImageSettingFragment());
break;
case R.id.notification_settings:
inflateFragment(new NotificationSettingsFragment());
break;
case R.id.other_settings:
inflateFragment(new OtherSettingsFragment());
break;
}
}
private void inflateFragment(Fragment fragment) {
if (getActivity() != null) {
((SettingsActivity) getActivity()).setupFragment(fragment);
}
}
}

View file

@ -0,0 +1,43 @@
package code.name.monkey.retromusic.ui.fragments.settings;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.preference.TwoStatePreference;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.service.MusicService;
import code.name.monkey.retromusic.util.PreferenceUtil;
/**
* @author Hemanth S (h4h13).
*/
public class NotificationSettingsFragment extends AbsSettingsFragment {
@Override
public void invalidateSettings() {
final TwoStatePreference classicNotification = (TwoStatePreference) findPreference("classic_notification");
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
classicNotification.setVisible(false);
} else {
classicNotification.setChecked(PreferenceUtil.getInstance(getActivity()).classicNotification());
classicNotification.setOnPreferenceChangeListener((preference, newValue) -> {
// Save preference
PreferenceUtil.getInstance(getActivity()).setClassicNotification((Boolean) newValue);
final MusicService service = MusicPlayerRemote.musicService;
if (service != null) {
service.initNotification();
service.updateNotification();
}
return true;
});
}
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.pref_notification);
}
}

View file

@ -0,0 +1,92 @@
package code.name.monkey.retromusic.ui.fragments.settings;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.preference.TwoStatePreference;
import android.view.View;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.RetroApplication;
import code.name.monkey.retromusic.util.PreferenceUtil;
/**
* @author Hemanth S (h4h13).
*/
public class NowPlayingSettingsFragment extends AbsSettingsFragment implements
SharedPreferences.OnSharedPreferenceChangeListener {
@SuppressWarnings("ConstantConditions")
@Override
public void invalidateSettings() {
updateNowPlayingScreenSummary();
final TwoStatePreference cornerWindow = (TwoStatePreference) findPreference("corner_window");
cornerWindow.setOnPreferenceChangeListener((preference, newValue) -> {
if ((Boolean) newValue && !RetroApplication.isProVersion()) {
showProToastAndNavigate(getActivity().getString(R.string.pref_title_round_corners));
return false;
}
getActivity().recreate();
return true;
});
final TwoStatePreference carouselEffect = (TwoStatePreference) findPreference(
"carousel_effect");
carouselEffect.setOnPreferenceChangeListener((preference, newValue) -> {
if ((Boolean) newValue && !RetroApplication.isProVersion()) {
showProToastAndNavigate(
getActivity().getString(R.string.pref_title_toggle_carousel_effect));
return false;
}
return true;
});
final TwoStatePreference toggleFullScreen = (TwoStatePreference) findPreference(
"toggle_full_screen");
toggleFullScreen.setOnPreferenceChangeListener((preference, newValue) -> {
getActivity().recreate();
return true;
});
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.pref_now_playing_screen);
addPreferencesFromResource(R.xml.pref_ui);
addPreferencesFromResource(R.xml.pref_window);
addPreferencesFromResource(R.xml.pref_lockscreen);
}
private void updateNowPlayingScreenSummary() {
//noinspection ConstantConditions
findPreference("now_playing_screen_id")
.setSummary(PreferenceUtil.getInstance(getActivity()).getNowPlayingScreen().titleRes);
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//noinspection ConstantConditions
PreferenceUtil.getInstance(getContext()).registerOnSharedPreferenceChangedListener(this);
}
@Override
public void onDestroyView() {
super.onDestroyView();
//noinspection ConstantConditions
PreferenceUtil.getInstance(getContext()).unregisterOnSharedPreferenceChangedListener(this);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
switch (key) {
case PreferenceUtil.NOW_PLAYING_SCREEN_ID:
updateNowPlayingScreenSummary();
break;
case PreferenceUtil.CIRCULAR_ALBUM_ART:
case PreferenceUtil.CAROUSEL_EFFECT:
invalidateSettings();
break;
}
}
}

View file

@ -0,0 +1,23 @@
package code.name.monkey.retromusic.ui.fragments.settings;
import android.os.Bundle;
import code.name.monkey.retromusic.R;
/**
* @author Hemanth S (h4h13).
*/
public class OtherSettingsFragment extends AbsSettingsFragment {
@Override
public void invalidateSettings() {
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.pref_blacklist);
addPreferencesFromResource(R.xml.pref_playlists);
addPreferencesFromResource(R.xml.pref_advanced);
}
}

View file

@ -0,0 +1,143 @@
package code.name.monkey.retromusic.ui.fragments.settings;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.support.v7.preference.Preference;
import android.support.v7.preference.TwoStatePreference;
import com.afollestad.materialdialogs.color.ColorChooserDialog;
import code.name.monkey.appthemehelper.ThemeStore;
import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEColorPreference;
import code.name.monkey.appthemehelper.util.ColorUtil;
import code.name.monkey.appthemehelper.util.VersionUtils;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.RetroApplication;
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager;
import code.name.monkey.retromusic.ui.activities.SettingsActivity;
import code.name.monkey.retromusic.util.PreferenceUtil;
/**
* @author Hemanth S (h4h13).
*/
public class ThemeSettingsFragment extends AbsSettingsFragment {
@Override
public void invalidateSettings() {
final ATEColorPreference primaryColorPref = (ATEColorPreference) findPreference(
"primary_color");
//noinspection ConstantConditions
primaryColorPref.setVisible(PreferenceUtil.getInstance(getActivity()).getGeneralTheme() == R.style.Theme_RetroMusic_Color);
final int primaryColor = ThemeStore.primaryColor(getActivity());
primaryColorPref.setColor(primaryColor, ColorUtil.darkenColor(primaryColor));
primaryColorPref.setOnPreferenceClickListener(preference -> {
new ColorChooserDialog.Builder(getActivity(), R.string.primary_color)
.accentMode(false)
.allowUserColorInput(true)
.allowUserColorInputAlpha(false)
.preselect(primaryColor)
.show(getActivity());
return true;
});
final Preference generalTheme = findPreference("general_theme");
setSummary(generalTheme);
generalTheme.setOnPreferenceChangeListener((preference, newValue) -> {
String theme = (String) newValue;
if (theme.equals("color") && !RetroApplication.isProVersion()) {
primaryColorPref.setVisible(false);
showProToastAndNavigate("Color theme");
return false;
} else {
primaryColorPref.setVisible(true);
}
setSummary(generalTheme, newValue);
switch (theme) {
case "light":
ThemeStore.editTheme(getContext()).primaryColor(Color.WHITE).commit();
break;
case "black":
ThemeStore.editTheme(getContext()).primaryColor(Color.BLACK).commit();
break;
case "dark":
ThemeStore.editTheme(getContext()).primaryColor(ContextCompat.getColor(getContext(), R.color.md_grey_900)).commit();
break;
case "color":
ThemeStore.editTheme(getContext()).primaryColor(ContextCompat.getColor(getContext(), R.color.md_blue_grey_800)).commit();
break;
}
ThemeStore.editTheme(getActivity())
.activityTheme(PreferenceUtil.getThemeResFromPrefValue(theme))
.commit();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
getActivity().setTheme(PreferenceUtil.getThemeResFromPrefValue(theme));
new DynamicShortcutManager(getActivity()).updateDynamicShortcuts();
}
getActivity().recreate();
//invalidateSettings();
return true;
});
ATEColorPreference accentColorPref = (ATEColorPreference) findPreference("accent_color");
final int accentColor = ThemeStore.accentColor(getActivity());
accentColorPref.setColor(accentColor, ColorUtil.darkenColor(accentColor));
accentColorPref.setOnPreferenceClickListener(preference -> {
new ColorChooserDialog.Builder(((SettingsActivity) getActivity()), R.string.accent_color)
.accentMode(true)
.allowUserColorInput(true)
.allowUserColorInputAlpha(false)
.preselect(accentColor)
.show(getActivity());
return true;
});
TwoStatePreference colorNavBar = (TwoStatePreference) findPreference(
"should_color_navigation_bar");
if (!VersionUtils.hasLollipop()) {
colorNavBar.setEnabled(false);
colorNavBar.setSummary(R.string.pref_only_lollipop);
} else {
colorNavBar.setChecked(ThemeStore.coloredNavigationBar(getActivity()));
colorNavBar.setOnPreferenceChangeListener((preference, newValue) -> {
ThemeStore.editTheme(getActivity())
.coloredNavigationBar((Boolean) newValue)
.commit();
getActivity().recreate();
return true;
});
}
TwoStatePreference colorAppShortcuts = (TwoStatePreference) findPreference(
"should_color_app_shortcuts");
if (!VersionUtils.hasNougatMR()) {
colorAppShortcuts.setVisible(false);
} else {
colorAppShortcuts.setChecked(PreferenceUtil.getInstance(getActivity()).coloredAppShortcuts());
colorAppShortcuts.setOnPreferenceChangeListener((preference, newValue) -> {
// Save preference
PreferenceUtil.getInstance(getActivity()).setColoredAppShortcuts((Boolean) newValue);
// Update app shortcuts
new DynamicShortcutManager(getActivity()).updateDynamicShortcuts();
return true;
});
}
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.pref_general);
}
}