Playlists [beta]
This commit is contained in:
parent
f7bc62a2df
commit
de15a34365
33 changed files with 896 additions and 56 deletions
|
|
@ -52,12 +52,13 @@ dependencies {
|
|||
compile 'com.nhaarman.listviewanimations:lib-core:3.1.0@aar'
|
||||
compile 'com.nhaarman.listviewanimations:lib-manipulation:3.1.0@aar'
|
||||
compile 'com.nhaarman.listviewanimations:lib-core-slh:3.1.0@aar'
|
||||
compile 'com.nineoldandroids:library:2.4.0+'
|
||||
compile 'com.nineoldandroids:library:2.4.0'
|
||||
compile 'com.melnykov:floatingactionbutton:1.2.0'
|
||||
compile 'com.github.ksoichiro:android-observablescrollview:1.5.0'
|
||||
compile 'com.mcxiaoke.volley:library:1.0.+'
|
||||
compile 'com.squareup.picasso:picasso:2.5.0'
|
||||
compile 'com.squareup:otto:1.3.6'
|
||||
compile 'com.squareup.okhttp:okhttp:2.2.0'
|
||||
compile('com.crashlytics.sdk.android:crashlytics:2.2.1@aar') {
|
||||
transitive = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,6 +70,11 @@
|
|||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/music_player_widget_info" />
|
||||
</receiver>
|
||||
|
||||
<activity
|
||||
android:name=".ui.activities.PlaylistDetailActivity"
|
||||
android:label="@string/title_activity_playlist_detail" >
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
|||
import com.kabouzeid.gramophone.misc.AppKeys;
|
||||
import com.squareup.otto.Bus;
|
||||
import com.squareup.otto.ThreadEnforcer;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import io.fabric.sdk.android.Fabric;
|
||||
|
||||
|
|
@ -31,6 +32,7 @@ public class App extends Application {
|
|||
super.onCreate();
|
||||
Fabric.with(this, new Crashlytics());
|
||||
MusicPlayerRemote.init(this);
|
||||
//Picasso.with(this).setIndicatorsEnabled(true);// debug only
|
||||
}
|
||||
|
||||
public int getAppTheme() {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ public class PlayingQueueAdapter extends ArrayAdapter<Song> {
|
|||
private Activity activity;
|
||||
|
||||
public PlayingQueueAdapter(Activity activity, List<Song> playList) {
|
||||
super(activity, R.layout.item_list_playlist, playList);
|
||||
super(activity, R.layout.item_list_playlist_song, playList);
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ public class PlayingQueueAdapter extends ArrayAdapter<Song> {
|
|||
public View getView(final int position, View convertView, ViewGroup parent) {
|
||||
final Song song = getItem(position);
|
||||
if (convertView == null) {
|
||||
convertView = LayoutInflater.from(activity).inflate(R.layout.item_list_playlist, parent, false);
|
||||
convertView = LayoutInflater.from(activity).inflate(R.layout.item_list_playlist_song, parent, false);
|
||||
}
|
||||
final TextView title = (TextView) convertView.findViewById(R.id.song_title);
|
||||
final ImageView playingIndicator = (ImageView) convertView.findViewById(R.id.playing_indicator);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
package com.kabouzeid.gramophone.adapter;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.support.v4.util.Pair;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.kabouzeid.gramophone.R;
|
||||
import com.kabouzeid.gramophone.model.Playlist;
|
||||
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
|
||||
import com.kabouzeid.gramophone.util.NavigationUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by karim on 16.03.15.
|
||||
*/
|
||||
public class PlaylistAdapter extends RecyclerView.Adapter<PlaylistAdapter.ViewHolder> {
|
||||
public static final String TAG = PlaylistAdapter.class.getSimpleName();
|
||||
protected Activity activity;
|
||||
protected List<Playlist> dataSet;
|
||||
|
||||
public PlaylistAdapter(Activity activity, List<Playlist> objects) {
|
||||
this.activity = activity;
|
||||
dataSet = objects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(activity).inflate(R.layout.item_list_playlist, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
holder.playlistName.setText(dataSet.get(position).playlistName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return dataSet.size();
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
|
||||
public TextView playlistName;
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
playlistName = (TextView) itemView.findViewById(R.id.playlist_name);
|
||||
itemView.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Pair[] sharedViews = null;
|
||||
if (activity instanceof AbsFabActivity) sharedViews = ((AbsFabActivity)activity).getSharedViewsWithFab(sharedViews);
|
||||
NavigationUtil.goToPlaylist(activity, dataSet.get(getPosition()).id, sharedViews);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
package com.kabouzeid.gramophone.adapter.songadapter;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.support.v4.util.Pair;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.kabouzeid.gramophone.R;
|
||||
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
||||
import com.kabouzeid.gramophone.helper.SongDetailDialogHelper;
|
||||
import com.kabouzeid.gramophone.loader.SongFilePathLoader;
|
||||
import com.kabouzeid.gramophone.misc.AppKeys;
|
||||
import com.kabouzeid.gramophone.model.Playlist;
|
||||
import com.kabouzeid.gramophone.model.PlaylistSong;
|
||||
import com.kabouzeid.gramophone.model.Song;
|
||||
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
|
||||
import com.kabouzeid.gramophone.ui.activities.tageditor.SongTagEditorActivity;
|
||||
import com.kabouzeid.gramophone.util.MusicUtil;
|
||||
import com.kabouzeid.gramophone.util.NavigationUtil;
|
||||
import com.kabouzeid.gramophone.util.PlaylistsUtil;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by karim on 27.11.14.
|
||||
*/
|
||||
public class PlaylistSongAdapter extends RecyclerView.Adapter<PlaylistSongAdapter.ViewHolder> {
|
||||
public static final String TAG = AlbumSongAdapter.class.getSimpleName();
|
||||
protected Activity activity;
|
||||
protected List<PlaylistSong> dataSet;
|
||||
|
||||
public PlaylistSongAdapter(Activity activity, List<PlaylistSong> objects) {
|
||||
this.activity = activity;
|
||||
dataSet = objects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(activity).inflate(R.layout.item_list_song, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(final ViewHolder holder, int position) {
|
||||
final Song song = dataSet.get(position);
|
||||
|
||||
holder.songTitle.setText(song.title);
|
||||
holder.songInfo.setText(song.artistName);
|
||||
|
||||
Picasso.with(activity)
|
||||
.load(MusicUtil.getAlbumArtUri(song.albumId))
|
||||
.placeholder(R.drawable.default_album_art)
|
||||
.into(holder.albumArt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return dataSet.size();
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||
TextView songTitle;
|
||||
TextView songInfo;
|
||||
ImageView overflowButton;
|
||||
ImageView albumArt;
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
songTitle = (TextView) itemView.findViewById(R.id.song_title);
|
||||
songInfo = (TextView) itemView.findViewById(R.id.song_info);
|
||||
albumArt = (ImageView) itemView.findViewById(R.id.album_art);
|
||||
overflowButton = (ImageView) itemView.findViewById(R.id.menu);
|
||||
overflowButton.setOnClickListener(this);
|
||||
itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
MusicPlayerRemote.openQueue((List<Song>) (List)dataSet, getAdapterPosition(), true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
PopupMenu popupMenu = new PopupMenu(activity, v);
|
||||
popupMenu.inflate(R.menu.menu_playlist_song);
|
||||
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_delete_from_playlist:
|
||||
int position = getAdapterPosition();
|
||||
PlaylistsUtil.removeFromPlaylist(activity, dataSet.remove(position));
|
||||
notifyItemRemoved(position);
|
||||
return true;
|
||||
case R.id.action_play_next:
|
||||
MusicPlayerRemote.playNext(dataSet.get(getAdapterPosition()));
|
||||
return true;
|
||||
case R.id.action_add_to_current_playing:
|
||||
MusicPlayerRemote.enqueue(dataSet.get(getAdapterPosition()));
|
||||
return true;
|
||||
case R.id.action_tag_editor:
|
||||
Intent intent = new Intent(activity, SongTagEditorActivity.class);
|
||||
intent.putExtra(AppKeys.E_ID, dataSet.get(getAdapterPosition()).id);
|
||||
activity.startActivity(intent);
|
||||
return true;
|
||||
case R.id.action_details:
|
||||
String songFilePath = SongFilePathLoader.getSongFilePath(activity, dataSet.get(getPosition()).id);
|
||||
File songFile = new File(songFilePath);
|
||||
SongDetailDialogHelper.getDialog(activity, songFile).show();
|
||||
return true;
|
||||
case R.id.action_go_to_album:
|
||||
Pair[] albumPairs = new Pair[]{
|
||||
Pair.create(albumArt, activity.getResources().getString(R.string.transition_album_cover))
|
||||
};
|
||||
if (activity instanceof AbsFabActivity)
|
||||
albumPairs = ((AbsFabActivity) activity).getSharedViewsWithFab(albumPairs);
|
||||
NavigationUtil.goToAlbum(activity, dataSet.get(getAdapterPosition()).albumId, albumPairs);
|
||||
return true;
|
||||
case R.id.action_go_to_artist:
|
||||
Pair[] artistPairs = null;
|
||||
if (activity instanceof AbsFabActivity)
|
||||
artistPairs = ((AbsFabActivity) activity).getSharedViewsWithFab(artistPairs);
|
||||
NavigationUtil.goToArtist(activity, dataSet.get(getAdapterPosition()).artistId, artistPairs);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
popupMenu.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -230,6 +230,12 @@ public class MusicPlayerRemote {
|
|||
}
|
||||
}
|
||||
|
||||
public static void removeFromQueue(Song song) {
|
||||
if (musicService != null) {
|
||||
musicService.removeSong(song);
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeFromQueue(int position) {
|
||||
if (musicService != null) {
|
||||
musicService.removeSong(position);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
package com.kabouzeid.gramophone.loader;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.provider.BaseColumns;
|
||||
import android.provider.MediaStore;
|
||||
import android.provider.MediaStore.Audio.PlaylistsColumns;
|
||||
|
||||
import com.kabouzeid.gramophone.model.Playlist;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PlaylistLoader {
|
||||
public static Playlist getPlaylist(final Context context, final int playlistID) {
|
||||
Playlist playlist = new Playlist();
|
||||
Cursor cursor = makePlaylistCursor(context, BaseColumns._ID + "=" + playlistID);
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
final int id = cursor.getInt(0);
|
||||
final String name = cursor.getString(1);
|
||||
playlist = new Playlist(id, name);
|
||||
}
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
return playlist;
|
||||
}
|
||||
|
||||
public static List<Playlist> getAllPlaylists(final Context context) {
|
||||
List<Playlist> playlists = new ArrayList<>();
|
||||
Cursor cursor = makePlaylistCursor(context, null);
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
final int id = cursor.getInt(0);
|
||||
final String name = cursor.getString(1);
|
||||
final Playlist playlist = new Playlist(id, name);
|
||||
playlists.add(playlist);
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
return playlists;
|
||||
}
|
||||
|
||||
public static Cursor makePlaylistCursor(final Context context, final String selection) {
|
||||
return context.getContentResolver().query(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
||||
new String[]{
|
||||
/* 0 */
|
||||
BaseColumns._ID,
|
||||
/* 1 */
|
||||
PlaylistsColumns.NAME
|
||||
}, selection, null, MediaStore.Audio.Playlists.DEFAULT_SORT_ORDER);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
package com.kabouzeid.gramophone.loader;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.provider.MediaStore;
|
||||
import android.provider.MediaStore.Audio.AudioColumns;
|
||||
|
||||
import com.kabouzeid.gramophone.model.Playlist;
|
||||
import com.kabouzeid.gramophone.model.PlaylistSong;
|
||||
import com.kabouzeid.gramophone.model.Song;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class PlaylistSongLoader {
|
||||
|
||||
public static List<PlaylistSong> getPlaylistSongList(final Context context, final int playlistID) {
|
||||
List<PlaylistSong> songs = new ArrayList<>();
|
||||
Cursor cursor = makePlaylistSongCursor(context, playlistID);
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
final int id = cursor.getInt(0);
|
||||
final String songName = cursor.getString(1);
|
||||
final String artist = cursor.getString(2);
|
||||
final String album = cursor.getString(3);
|
||||
final long duration = cursor.getLong(4);
|
||||
final int trackNumber = cursor.getInt(5);
|
||||
final int albumId = cursor.getInt(6);
|
||||
final int artistId = cursor.getInt(7);
|
||||
final int idInPlaylist = cursor.getInt(8);
|
||||
|
||||
final PlaylistSong song = new PlaylistSong(id, albumId, artistId, songName, artist, album, duration, trackNumber, playlistID, idInPlaylist);
|
||||
|
||||
songs.add(song);
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
return songs;
|
||||
}
|
||||
|
||||
public static Cursor makePlaylistSongCursor(final Context context, final int playlistID) {
|
||||
return context.getContentResolver().query(
|
||||
MediaStore.Audio.Playlists.Members.getContentUri("external", playlistID),
|
||||
new String[]{
|
||||
/* 0 */
|
||||
MediaStore.Audio.Playlists.Members.AUDIO_ID,
|
||||
/* 1 */
|
||||
AudioColumns.TITLE,
|
||||
/* 2 */
|
||||
AudioColumns.ARTIST,
|
||||
/* 3 */
|
||||
AudioColumns.ALBUM,
|
||||
/* 4 */
|
||||
AudioColumns.DURATION,
|
||||
/* 5 */
|
||||
AudioColumns.TRACK,
|
||||
/* 6 */
|
||||
AudioColumns.ALBUM_ID,
|
||||
/* 7 */
|
||||
AudioColumns.ARTIST_ID,
|
||||
/* 8 */
|
||||
MediaStore.Audio.Playlists.Members._ID
|
||||
}, (AudioColumns.IS_MUSIC + "=1") + " AND " + AudioColumns.TITLE + " != ''", null,
|
||||
MediaStore.Audio.Playlists.Members.DEFAULT_SORT_ORDER);
|
||||
}
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ public final class AppKeys {
|
|||
public static final String E_ALBUM = "com.kabouzeid.gramophone.ALBUM";
|
||||
public static final String E_ARTIST = "com.kabouzeid.gramophone.ARTIST";
|
||||
public static final String E_SONG = "com.kabouzeid.gramophone.SONG";
|
||||
public static final String E_PLAYLIST = "com.kabouzeid.gramophone.PLAYLIST";
|
||||
public static final String E_TAG_EDIT_MODE = "com.kabouzeid.gramophone.TAG_EDIT_MODE";
|
||||
public static final String E_ID = "com.kabouzeid.gramophone.ID";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
package com.kabouzeid.gramophone.model;
|
||||
|
||||
public class Playlist {
|
||||
public int id;
|
||||
public String playlistName;
|
||||
|
||||
public Playlist(final int id, final String playlistName) {
|
||||
this.id = id;
|
||||
this.playlistName = playlistName;
|
||||
}
|
||||
|
||||
public Playlist() {
|
||||
this.id = -1;
|
||||
this.playlistName = "";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package com.kabouzeid.gramophone.model;
|
||||
|
||||
public class PlaylistSong extends Song{
|
||||
public int playlistId;
|
||||
public int idInPlayList;
|
||||
|
||||
public PlaylistSong(final int id, final int albumId, final int artistId, final String title, final String artistName,
|
||||
final String albumName, final long duration, final int trackNumber, final int playlistId, final int idInPlayList) {
|
||||
super(id, albumId, artistId, title, artistName, albumName, duration, trackNumber);
|
||||
this.playlistId = playlistId;
|
||||
this.idInPlayList = idInPlayList;
|
||||
}
|
||||
|
||||
public PlaylistSong() {
|
||||
super();
|
||||
playlistId = -1;
|
||||
id = -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -499,6 +499,16 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
|
|||
saveState();
|
||||
}
|
||||
|
||||
public void removeSong(Song song){
|
||||
while (playingQueue.contains(song)){
|
||||
playingQueue.remove(song);
|
||||
}
|
||||
while (originalPlayingQueue.contains(song)){
|
||||
originalPlayingQueue.remove(song);
|
||||
}
|
||||
saveState();
|
||||
}
|
||||
|
||||
public void moveSong(int from, int to) {
|
||||
final int currentPosition = getPosition();
|
||||
Song songToMove = playingQueue.remove(from);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import com.kabouzeid.gramophone.ui.fragments.NavigationDrawerFragment;
|
|||
import com.kabouzeid.gramophone.ui.fragments.mainactivityfragments.AlbumViewFragment;
|
||||
import com.kabouzeid.gramophone.ui.fragments.mainactivityfragments.ArtistViewFragment;
|
||||
import com.kabouzeid.gramophone.ui.fragments.mainactivityfragments.AbsMainActivityFragment;
|
||||
import com.kabouzeid.gramophone.ui.fragments.mainactivityfragments.PlaylistViewFragment;
|
||||
import com.kabouzeid.gramophone.ui.fragments.mainactivityfragments.SongViewFragment;
|
||||
import com.kabouzeid.gramophone.util.MusicUtil;
|
||||
import com.kabouzeid.gramophone.util.NavigationUtil;
|
||||
|
|
@ -261,41 +262,11 @@ public class MainActivity extends AbsFabActivity
|
|||
super.onBackPressed();
|
||||
}
|
||||
|
||||
public static class PlaceholderFragmentAbs extends AbsMainActivityFragment {
|
||||
|
||||
public PlaceholderFragmentAbs() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View rootView = inflater.inflate(R.layout.fragment_place_holder, container, false);
|
||||
TextView text = (TextView) rootView.findViewById(R.id.text);
|
||||
text.setText("Coming soon!");
|
||||
return rootView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableViews() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableViews() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areViewsEnabled() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private class MainActivityViewPagerAdapter extends FragmentPagerAdapter {
|
||||
|
||||
private String[] titles;
|
||||
|
||||
private SparseArray<AbsMainActivityFragment> pages; //TODO check if this must be static
|
||||
private SparseArray<AbsMainActivityFragment> pages;
|
||||
private Context context;
|
||||
|
||||
public MainActivityViewPagerAdapter(Activity activity) {
|
||||
|
|
@ -306,7 +277,6 @@ public class MainActivity extends AbsFabActivity
|
|||
context.getResources().getString(R.string.songs),
|
||||
context.getResources().getString(R.string.albums),
|
||||
context.getResources().getString(R.string.artists),
|
||||
context.getResources().getString(R.string.genres),
|
||||
context.getResources().getString(R.string.playlists)
|
||||
};
|
||||
}
|
||||
|
|
@ -321,11 +291,9 @@ public class MainActivity extends AbsFabActivity
|
|||
case 2:
|
||||
return pages.get(position, new ArtistViewFragment());
|
||||
case 3:
|
||||
//TODO genres
|
||||
case 4:
|
||||
//TODO playlists
|
||||
return pages.get(position, new PlaylistViewFragment());
|
||||
}
|
||||
return pages.get(position, new PlaceholderFragmentAbs());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
package com.kabouzeid.gramophone.ui.activities;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.GridLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.kabouzeid.gramophone.R;
|
||||
import com.kabouzeid.gramophone.adapter.songadapter.PlaylistSongAdapter;
|
||||
import com.kabouzeid.gramophone.loader.PlaylistLoader;
|
||||
import com.kabouzeid.gramophone.loader.PlaylistSongLoader;
|
||||
import com.kabouzeid.gramophone.misc.AppKeys;
|
||||
import com.kabouzeid.gramophone.model.Playlist;
|
||||
import com.kabouzeid.gramophone.model.PlaylistSong;
|
||||
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
|
||||
import com.kabouzeid.gramophone.util.NavigationUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PlaylistDetailActivity extends AbsFabActivity {
|
||||
public static final String TAG = PlaylistDetailActivity.class.getSimpleName();
|
||||
private RecyclerView recyclerView;
|
||||
private Playlist playlist;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
setUpTranslucence(false, false);
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_playlist_detail);
|
||||
|
||||
getIntentExtras();
|
||||
setUpToolBar();
|
||||
|
||||
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
|
||||
List<PlaylistSong> songs = PlaylistSongLoader.getPlaylistSongList(this, playlist.id);
|
||||
PlaylistSongAdapter adapter = new PlaylistSongAdapter(this, songs);
|
||||
recyclerView.setLayoutManager(new GridLayoutManager(this, 1));
|
||||
recyclerView.setAdapter(adapter);
|
||||
}
|
||||
|
||||
private void getIntentExtras() {
|
||||
Bundle intentExtras = getIntent().getExtras();
|
||||
final int playlistId = intentExtras.getInt(AppKeys.E_PLAYLIST);
|
||||
playlist = PlaylistLoader.getPlaylist(this, playlistId);
|
||||
if (playlist == null) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
private void setUpToolBar() {
|
||||
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
|
||||
getSupportActionBar().setTitle(playlist.playlistName);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_playlist_detail, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
switch (id) {
|
||||
case android.R.id.home:
|
||||
super.onBackPressed();
|
||||
return true;
|
||||
case R.id.action_settings:
|
||||
return true;
|
||||
case R.id.action_current_playing:
|
||||
NavigationUtil.openCurrentPlayingIfPossible(this, getSharedViewsWithFab(null));
|
||||
return true;
|
||||
case R.id.action_playing_queue:
|
||||
NavigationUtil.openPlayingQueueDialog(this);
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
|
@ -138,7 +138,6 @@ public class NavigationDrawerFragment extends Fragment {
|
|||
navigationDrawerItems.add(new NavigationDrawerItem(getString(R.string.songs), R.drawable.ic_my_library_music_white_24dp));
|
||||
navigationDrawerItems.add(new NavigationDrawerItem(getString(R.string.albums), R.drawable.ic_album_white_24dp));
|
||||
navigationDrawerItems.add(new NavigationDrawerItem(getString(R.string.artists), R.drawable.ic_person_white_24dp));
|
||||
navigationDrawerItems.add(new NavigationDrawerItem(getString(R.string.genres), R.drawable.ic_my_library_music_white_24dp));
|
||||
navigationDrawerItems.add(new NavigationDrawerItem(getString(R.string.playlists), R.drawable.ic_queue_music_white_24dp));
|
||||
|
||||
drawerAdapter = new NavigationDrawerItemAdapter(getActivity(), R.id.navigation_drawer, navigationDrawerItems);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
package com.kabouzeid.gramophone.ui.fragments.mainactivityfragments;
|
||||
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.app.Fragment;
|
||||
import android.support.v7.widget.GridLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.kabouzeid.gramophone.R;
|
||||
import com.kabouzeid.gramophone.adapter.PlaylistAdapter;
|
||||
import com.kabouzeid.gramophone.adapter.songadapter.SongAdapter;
|
||||
import com.kabouzeid.gramophone.loader.PlaylistLoader;
|
||||
import com.kabouzeid.gramophone.loader.SongLoader;
|
||||
import com.kabouzeid.gramophone.model.Playlist;
|
||||
import com.kabouzeid.gramophone.model.Song;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PlaylistViewFragment extends AbsMainActivityFragment {
|
||||
public static final String TAG = PlaylistViewFragment.class.getSimpleName();
|
||||
|
||||
private RecyclerView recyclerView;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_playlist_view, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
|
||||
setUpRecyclerView();
|
||||
}
|
||||
|
||||
private void setUpRecyclerView() {
|
||||
List<Playlist> playlists = PlaylistLoader.getAllPlaylists(getActivity());
|
||||
PlaylistAdapter adapter = new PlaylistAdapter(getActivity(), playlists);
|
||||
|
||||
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 1));
|
||||
recyclerView.setAdapter(adapter);
|
||||
recyclerView.setPadding(0, getTopPadding(), 0, getBottomPadding());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableViews() {
|
||||
super.enableViews();
|
||||
recyclerView.setEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableViews() {
|
||||
super.disableViews();
|
||||
recyclerView.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,15 +4,24 @@ import android.content.ContentResolver;
|
|||
import android.content.ContentUris;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.provider.BaseColumns;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
||||
import com.kabouzeid.gramophone.loader.SongLoader;
|
||||
import com.kabouzeid.gramophone.model.Song;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by karim on 29.12.14.
|
||||
|
|
@ -86,4 +95,57 @@ public class MusicUtil {
|
|||
}
|
||||
return albumArtDir;
|
||||
}
|
||||
|
||||
public static void deleteTracks(final Context context, final List<Song> songs) {
|
||||
final String[] projection = new String[] {
|
||||
BaseColumns._ID, MediaStore.MediaColumns.DATA
|
||||
};
|
||||
final StringBuilder selection = new StringBuilder();
|
||||
selection.append(BaseColumns._ID + " IN (");
|
||||
for (int i = 0; i < songs.size(); i++) {
|
||||
selection.append(songs.get(i).id);
|
||||
if (i < songs.size() - 1) {
|
||||
selection.append(",");
|
||||
}
|
||||
}
|
||||
selection.append(")");
|
||||
final Cursor cursor = context.getContentResolver().query(
|
||||
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, selection.toString(),
|
||||
null, null);
|
||||
if (cursor != null) {
|
||||
// Step 1: Remove selected tracks from the current playlist, as well
|
||||
// as from the album art cache
|
||||
cursor.moveToFirst();
|
||||
while (!cursor.isAfterLast()) {
|
||||
final int id = cursor.getInt(0);
|
||||
final Song song = SongLoader.getSong(context, id);
|
||||
MusicPlayerRemote.removeFromQueue(song);
|
||||
}
|
||||
|
||||
// Step 2: Remove selected tracks from the database
|
||||
context.getContentResolver().delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
|
||||
selection.toString(), null);
|
||||
|
||||
// Step 3: Remove files from card
|
||||
cursor.moveToFirst();
|
||||
while (!cursor.isAfterLast()) {
|
||||
final String name = cursor.getString(1);
|
||||
final File f = new File(name);
|
||||
try { // File.delete can throw a security exception
|
||||
if (!f.delete()) {
|
||||
// I'm not sure if we'd ever get here (deletion would
|
||||
// have to fail, but no exception thrown)
|
||||
Log.e("MusicUtils", "Failed to delete file " + name);
|
||||
}
|
||||
cursor.moveToNext();
|
||||
} catch (final SecurityException ex) {
|
||||
cursor.moveToNext();
|
||||
}
|
||||
}
|
||||
cursor.close();
|
||||
}
|
||||
context.getContentResolver().notifyChange(Uri.parse("content://media"), null);
|
||||
Toast.makeText(context, "Deleted " + songs.size() + " songs", Toast.LENGTH_SHORT).show();
|
||||
//TODO add resource string
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import com.kabouzeid.gramophone.misc.AppKeys;
|
|||
import com.kabouzeid.gramophone.ui.activities.AlbumDetailActivity;
|
||||
import com.kabouzeid.gramophone.ui.activities.ArtistDetailActivity;
|
||||
import com.kabouzeid.gramophone.ui.activities.MusicControllerActivity;
|
||||
import com.kabouzeid.gramophone.ui.activities.PlaylistDetailActivity;
|
||||
|
||||
/**
|
||||
* Created by karim on 12.03.15.
|
||||
|
|
@ -61,6 +62,23 @@ public class NavigationUtil {
|
|||
}
|
||||
}
|
||||
|
||||
public static void goToPlaylist(final Activity activity, final int playlistId, final Pair[] sharedViews) {
|
||||
if ((activity instanceof KabViewsDisableAble && ((KabViewsDisableAble) activity).areViewsEnabled()) || !(activity instanceof KabViewsDisableAble)) {
|
||||
if (activity instanceof KabViewsDisableAble)
|
||||
((KabViewsDisableAble) activity).disableViews();
|
||||
final Intent intent = new Intent(activity, PlaylistDetailActivity.class);
|
||||
intent.putExtra(AppKeys.E_PLAYLIST, playlistId);
|
||||
if (sharedViews != null) {
|
||||
ActivityOptionsCompat optionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(activity,
|
||||
sharedViews
|
||||
);
|
||||
ActivityCompat.startActivity(activity, intent, optionsCompat.toBundle());
|
||||
} else {
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void openCurrentPlayingIfPossible(final Activity activity, final Pair[] sharedViews) {
|
||||
if (activity instanceof MusicControllerActivity) {
|
||||
activity.onBackPressed();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
package com.kabouzeid.gramophone.util;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.MediaStore;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.kabouzeid.gramophone.model.PlaylistSong;
|
||||
import com.kabouzeid.gramophone.model.Song;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by karim on 16.03.15.
|
||||
*/
|
||||
public class PlaylistsUtil {
|
||||
public static int createPlaylist(final Context context, final String name) {
|
||||
if (name != null && name.length() > 0) {
|
||||
final ContentResolver resolver = context.getContentResolver();
|
||||
final String[] projection = new String[]{
|
||||
MediaStore.Audio.PlaylistsColumns.NAME
|
||||
};
|
||||
final String selection = MediaStore.Audio.PlaylistsColumns.NAME + " = '" + name + "'";
|
||||
Cursor cursor = resolver.query(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
||||
projection, selection, null, null);
|
||||
if (cursor.getCount() <= 0) {
|
||||
final ContentValues values = new ContentValues(1);
|
||||
values.put(MediaStore.Audio.PlaylistsColumns.NAME, name);
|
||||
final Uri uri = resolver.insert(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
||||
values);
|
||||
return Integer.parseInt(uri.getLastPathSegment());
|
||||
}
|
||||
cursor.close();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static void deletePlaylist(final Context context, final int playlistId) {
|
||||
final Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId);
|
||||
context.getContentResolver().delete(uri, null, null);
|
||||
}
|
||||
|
||||
public static void addToPlaylist(final Context context, final Song song, final long playlistId) {
|
||||
List<Song> helperList = new ArrayList<>();
|
||||
helperList.add(song);
|
||||
addToPlaylist(context, helperList, playlistId);
|
||||
}
|
||||
|
||||
public static void addToPlaylist(final Context context, final List<Song> songs, final long playlistId) {
|
||||
final ContentResolver resolver = context.getContentResolver();
|
||||
|
||||
final String[] projection = new String[]{
|
||||
MediaStore.Audio.PlaylistsColumns.NAME
|
||||
};
|
||||
|
||||
final Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId);
|
||||
Cursor cursor = resolver.query(uri, projection, null, null, null);
|
||||
cursor.moveToFirst();
|
||||
final String playlistName = cursor.getString(0);
|
||||
cursor.close();
|
||||
|
||||
ContentValues[] contentValues = new ContentValues[songs.size()];
|
||||
for (int i = 0; i < songs.size(); i++) {
|
||||
contentValues[i] = new ContentValues();
|
||||
contentValues[i].put(MediaStore.Audio.Playlists.Members.AUDIO_ID, songs.get(i).id);
|
||||
}
|
||||
|
||||
resolver.bulkInsert(uri, contentValues);
|
||||
Toast.makeText(context, "Added " + contentValues.length + " songs to playlist " + playlistName, Toast.LENGTH_SHORT).show();
|
||||
//TODO add string resource
|
||||
}
|
||||
|
||||
public static void removeFromPlaylist(final Context context, final PlaylistSong song) {
|
||||
Uri uri = MediaStore.Audio.Playlists.Members.getContentUri(
|
||||
"external", song.playlistId);
|
||||
String selection = MediaStore.Audio.Playlists.Members._ID+ " =?";
|
||||
String[] selectionArgs = new String[]{String.valueOf(song.idInPlayList)};
|
||||
|
||||
context.getContentResolver().delete(uri, selection, selectionArgs);
|
||||
}
|
||||
|
||||
public static void removeFromPlaylist(final Context context, final List<PlaylistSong> songs) {
|
||||
Uri uri = MediaStore.Audio.Playlists.Members.getContentUri(
|
||||
"external", songs.get(0).playlistId);
|
||||
String selectionArgs[] = new String[songs.size()];
|
||||
for (int i = 0; i < selectionArgs.length; i++) {
|
||||
selectionArgs[i] = String.valueOf(songs.get(i).idInPlayList);
|
||||
}
|
||||
String selection = MediaStore.Audio.Playlists.Members._ID + " in (";
|
||||
for (String selectionArg : selectionArgs) selection += "?, ";
|
||||
selection = selection.substring(0, selection.length() - 2) + ")";
|
||||
|
||||
context.getContentResolver().delete(uri, selection, selectionArgs);
|
||||
}
|
||||
}
|
||||
BIN
app/src/main/res/drawable-hdpi/ic_queue_music_white_48dp.png
Normal file
BIN
app/src/main/res/drawable-hdpi/ic_queue_music_white_48dp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 409 B |
BIN
app/src/main/res/drawable-mdpi/ic_queue_music_white_48dp.png
Normal file
BIN
app/src/main/res/drawable-mdpi/ic_queue_music_white_48dp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 333 B |
BIN
app/src/main/res/drawable-xhdpi/ic_queue_music_white_48dp.png
Normal file
BIN
app/src/main/res/drawable-xhdpi/ic_queue_music_white_48dp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 538 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_queue_music_white_48dp.png
Normal file
BIN
app/src/main/res/drawable-xxhdpi/ic_queue_music_white_48dp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 747 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_queue_music_white_48dp.png
Normal file
BIN
app/src/main/res/drawable-xxxhdpi/ic_queue_music_white_48dp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1,005 B |
43
app/src/main/res/layout/activity_playlist_detail.xml
Normal file
43
app/src/main/res/layout/activity_playlist_detail.xml
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?colorPrimary"
|
||||
android:elevation="@dimen/toolbar_elevation"
|
||||
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:divider="@null"
|
||||
android:dividerHeight="0px"
|
||||
android:scrollbars="vertical"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="right|bottom"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<com.melnykov.fab.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
style="@style/PlayPauseFab"
|
||||
android:layout_margin="16dp"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
16
app/src/main/res/layout/fragment_playlist_view.xml
Normal file
16
app/src/main/res/layout/fragment_playlist_view.xml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
android:id="@+id/fragment_song_view"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:dividerHeight="0px"
|
||||
android:divider="@null"
|
||||
android:scrollbars="vertical"/>
|
||||
</LinearLayout>
|
||||
|
|
@ -3,29 +3,28 @@
|
|||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:descendantFocusability="blocksDescendants"
|
||||
android:background="?rect_selector"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/song_title"
|
||||
android:layout_width="0dp"
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:src="@drawable/ic_queue_music_white_24dp"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/playlist_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginRight="16dp"
|
||||
android:fontFamily="sans-serif"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body2"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/playing_indicator"
|
||||
style="@style/PlayingIndicator"
|
||||
android:layout_marginRight="-8dp"
|
||||
/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/menu"
|
||||
style="@style/OverFlowButton"
|
||||
android:layout_gravity="center_vertical"/>
|
||||
</LinearLayout>
|
||||
31
app/src/main/res/layout/item_list_playlist_song.xml
Normal file
31
app/src/main/res/layout/item_list_playlist_song.xml
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:descendantFocusability="blocksDescendants"
|
||||
android:orientation="horizontal"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/song_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_weight="1"
|
||||
android:fontFamily="sans-serif"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body2"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/playing_indicator"
|
||||
style="@style/PlayingIndicator"
|
||||
android:layout_marginRight="-8dp"
|
||||
/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/menu"
|
||||
style="@style/OverFlowButton"
|
||||
android:layout_gravity="center_vertical"/>
|
||||
</LinearLayout>
|
||||
20
app/src/main/res/menu/menu_playlist_detail.xml
Normal file
20
app/src/main/res/menu/menu_playlist_detail.xml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="com.kabouzeid.gramophone.ui.activities.PlaylistDetailActivity">
|
||||
<item
|
||||
android:id="@+id/action_current_playing"
|
||||
android:icon="@drawable/music_box"
|
||||
android:title="@string/action_current_playing"
|
||||
app:showAsAction="ifRoom"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_playing_queue"
|
||||
android:icon="@drawable/ic_queue_music_white_24dp"
|
||||
android:title="@string/action_playing_queue"
|
||||
app:showAsAction="never"/>
|
||||
<item android:id="@+id/action_settings"
|
||||
android:title="@string/action_settings"
|
||||
android:orderInCategory="100"
|
||||
app:showAsAction="never"/>
|
||||
</menu>
|
||||
40
app/src/main/res/menu/menu_playlist_song.xml
Normal file
40
app/src/main/res/menu/menu_playlist_song.xml
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/action_delete_from_playlist"
|
||||
android:title="@string/action_delete_from_playlist"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/action_play_next"
|
||||
android:title="@string/action_play_next"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/action_add_to_current_playing"
|
||||
android:title="@string/action_add_to_playing_queue"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/action_add_to_playlist"
|
||||
android:title="@string/action_add_to_playlist"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/action_go_to_album"
|
||||
android:title="@string/action_go_to_album"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/action_go_to_artist"
|
||||
android:title="@string/action_go_to_artist"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/action_tag_editor"
|
||||
android:title="@string/action_tag_editor"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/action_details"
|
||||
android:title="@string/action_details"
|
||||
app:showAsAction="never"/>
|
||||
<item
|
||||
android:id="@+id/action_delete_from_disk"
|
||||
android:title="@string/action_delete_from_disk"
|
||||
app:showAsAction="never"/>
|
||||
</menu>
|
||||
6
app/src/main/res/values-w820dp/dimens.xml
Normal file
6
app/src/main/res/values-w820dp/dimens.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<resources>
|
||||
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
|
||||
(such as screen margins) for screens with more than 820dp of available width. This
|
||||
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
|
||||
<dimen name="activity_horizontal_margin">64dp</dimen>
|
||||
</resources>
|
||||
|
|
@ -74,5 +74,7 @@
|
|||
<string name="added_title_to_playing_queue">Added 1 title to the playing queue.</string>
|
||||
<string name="added_titles_to_playing_queue_1">Added </string>
|
||||
<string name="added_titles_to_playing_queue_2"> titles to the playing queue.</string>
|
||||
<string name="title_activity_playlist_detail">PlaylistDetailActivity</string>
|
||||
<string name="action_delete_from_playlist">Delete from playlist</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue