PlaylistTrack now use a recycler, adding loading bar and an item touch handler.

This commit is contained in:
Anonymous Raccoon
2018-08-28 00:30:19 +02:00
parent b1723852fa
commit e989262f83
9 changed files with 829 additions and 461 deletions
+1 -1
View File
@@ -1270,7 +1270,7 @@ namespace MusicApp
parseProgress.Visibility = ViewStates.Gone;
}
int DpToPx(int dx)
public int DpToPx(int dx)
{
float scale = Resources.DisplayMetrics.Density;
return (int) (dx * scale + 0.5f);
+8
View File
@@ -262,6 +262,8 @@
<Compile Include="Resources\Portable Class\Browse.cs" />
<Compile Include="Resources\Portable Class\ChannelAdapter.cs" />
<Compile Include="Resources\Portable Class\CircleTransformation.cs" />
<Compile Include="Resources\Portable Class\PlaylistItemTouch.cs" />
<Compile Include="Resources\Portable Class\PlaylistTrackAdapter.cs" />
<Compile Include="Resources\Portable Class\SearchableActivity.cs" />
<Compile Include="Resources\Portable Class\Downloader.cs" />
<Compile Include="Resources\Portable Class\DownloadFragment.cs" />
@@ -699,6 +701,12 @@
<ItemGroup>
<AndroidResource Include="Resources\drawable\History.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\layout\PlaylistSong.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\Delete.xml" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<Import Project="..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.Animated.Vector.Drawable.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.Animated.Vector.Drawable.targets')" />
<Import Project="..\packages\Xamarin.Android.Support.v7.Preference.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.v7.Preference.targets" Condition="Exists('..\packages\Xamarin.Android.Support.v7.Preference.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.v7.Preference.targets')" />
@@ -0,0 +1,91 @@
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Support.V7.Widget;
using Android.Support.V7.Widget.Helper;
using Android.Widget;
using Square.Picasso;
using System;
using System.Threading.Tasks;
namespace MusicApp.Resources.Portable_Class
{
public class PlaylistItemTouch : ItemTouchHelper.Callback
{
private IItemTouchAdapter adapter;
private int from = -1;
private int to = -1;
public override bool IsItemViewSwipeEnabled => true;
public override bool IsLongPressDragEnabled => true;
private Bitmap drawable;
private Paint paint;
public PlaylistItemTouch(IItemTouchAdapter adapter)
{
this.adapter = adapter;
drawable = BitmapFactory.DecodeResource(MainActivity.instance.Resources, Resource.Drawable.MusicIcon);
Console.WriteLine("&Drawable: " + drawable);
paint = new Paint();
paint.SetColorFilter(new PorterDuffColorFilter(Color.Argb(255, 33, 33, 33), PorterDuff.Mode.SrcIn));
}
public override int GetMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)
{
int dragFlag = ItemTouchHelper.Up | ItemTouchHelper.Down;
int swipeFlag = ItemTouchHelper.Left | ItemTouchHelper.Right;
return MakeMovementFlags(dragFlag, swipeFlag);
}
public override bool OnMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target)
{
if (from == -1)
from = source.AdapterPosition;
to = target.AdapterPosition;
adapter.ItemMoved(source.AdapterPosition, target.AdapterPosition);
return true;
}
public override void OnSwiped(RecyclerView.ViewHolder viewHolder, int direction)
{
//adapter.ItemDismissed(viewHolder.AdapterPosition);
}
public override void OnChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, bool isCurrentlyActive)
{
if (actionState == ItemTouchHelper.ActionStateSwipe)
{
viewHolder.ItemView.TranslationX = dX;
ColorDrawable background = new ColorDrawable(Color.Red);
background.SetBounds(viewHolder.ItemView.Right + (int)dX, viewHolder.ItemView.Top, viewHolder.ItemView.Right, viewHolder.ItemView.Bottom);
background.Draw(c);
c.DrawBitmap(drawable, viewHolder.ItemView.Left + MainActivity.instance.DpToPx(16), viewHolder.ItemView.Top + (viewHolder.ItemView.Bottom - viewHolder.ItemView.Top - drawable.Height) / 2, paint);
c.DrawBitmap(drawable, viewHolder.ItemView.Right + drawable.Width - 20, (viewHolder.ItemView.Top + viewHolder.ItemView.Bottom) / 2, paint);
MainActivity.instance.contentRefresh.SetEnabled(false);
//adapter.DisableRefresh(true);
}
else
base.OnChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
//public override void OnSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState)
//{
// if (actionState != ItemTouchHelper.ActionStateIdle)
// {
// if (viewHolder is IItemTouchHolder)
// ((IItemTouchHolder)viewHolder).ItemSelected();
// }
// base.OnSelectedChanged(viewHolder, actionState);
//}
public override void ClearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)
{
DefaultUIUtil.ClearView(viewHolder.ItemView);
}
}
}
@@ -0,0 +1,168 @@
using Android.App;
using Android.Content;
using Android.Graphics;
using Android.Support.V7.Widget;
using Android.Views;
using Android.Widget;
using MusicApp.Resources.values;
using Square.Picasso;
using System;
using System.Collections.Generic;
namespace MusicApp.Resources.Portable_Class
{
public class PlaylistTrackAdapter : RecyclerView.Adapter, IItemTouchAdapter
{
public List<Song> songList;
private bool refreshDisabled = true;
public event EventHandler<int> ItemClick;
public event EventHandler<int> ItemLongClick;
public int listPadding;
public PlaylistTrackAdapter(List<Song> songList)
{
this.songList = songList;
}
public void AddToList(List<Song> songList)
{
int positionStart = this.songList.Count;
this.songList.AddRange(songList);
NotifyItemRangeInserted(positionStart, songList.Count);
}
public void Remove(Song song)
{
int position = songList.IndexOf(song);
songList.Remove(song);
NotifyItemRemoved(position);
}
public override int ItemCount => songList.Count + (PlaylistTracks.instance.fullyLoadded ? 0 : 1);
public override void OnBindViewHolder(RecyclerView.ViewHolder viewHolder, int position)
{
if(position >= songList.Count)
return;
RecyclerHolder holder = (RecyclerHolder)viewHolder;
holder.Title.Text = songList[position].Title;
holder.Artist.Text = songList[position].Artist;
if (songList[position].AlbumArt == -1 || songList[position].IsYt)
{
var songAlbumArtUri = Android.Net.Uri.Parse(songList[position].Album);
Picasso.With(Application.Context).Load(songAlbumArtUri).Placeholder(Resource.Drawable.MusicIcon).Resize(400, 400).CenterCrop().Into(holder.AlbumArt);
}
else
{
var songCover = Android.Net.Uri.Parse("content://media/external/audio/albumart");
var songAlbumArtUri = ContentUris.WithAppendedId(songCover, songList[position].AlbumArt);
Picasso.With(Application.Context).Load(songAlbumArtUri).Placeholder(Resource.Drawable.MusicIcon).Resize(400, 400).CenterCrop().Into(holder.AlbumArt);
}
holder.more.Tag = position;
if (!holder.more.HasOnClickListeners)
{
holder.more.Click += (sender, e) =>
{
int tagPosition = (int)((ImageView)sender).Tag;
PlaylistTracks.instance.More(songList[tagPosition], tagPosition);
};
}
float scale = MainActivity.instance.Resources.DisplayMetrics.Density;
if (MainActivity.Theme == 1)
{
holder.more.SetColorFilter(Color.White);
holder.Title.SetTextColor(Color.White);
holder.Artist.SetTextColor(Color.White);
holder.Artist.Alpha = 0.7f;
}
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
if(viewType == 0)
{
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.SongList, parent, false);
return new RecyclerHolder(itemView, OnClick, OnLongClick);
}
else
{
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.smallLoading, parent, false);
return new UslessHolder(itemView);
}
}
public override int GetItemViewType(int position)
{
if (position >= songList.Count)
return 1;
return 0;
}
void OnClick(int position)
{
ItemClick?.Invoke(this, position);
}
void OnLongClick(int position)
{
ItemLongClick?.Invoke(this, position);
}
public void ItemMoved(int fromPosition, int toPosition)
{
//Enable this only if the user is editing the playlist
//if (fromPosition < toPosition)
//{
// for (int i = fromPosition; i < toPosition; i++)
// songList = Swap(songList, i, i + 1);
//}
//else
//{
// for (int i = fromPosition; i > toPosition; i--)
// songList = Swap(songList, i, i - 1);
//}
//NotifyItemMoved(fromPosition, toPosition);
}
public void ItemMoveEnded(int fromPosition, int toPosition)
{
//if (MusicPlayer.CurrentID() == fromPosition)
// MusicPlayer.currentID = toPosition;
//MusicPlayer.instance.UpdateQueueSlots();
}
//List<T> Swap<T>(List<T> list, int fromPosition, int toPosition)
//{
// T item = list[fromPosition];
// list[fromPosition] = list[toPosition];
// list[toPosition] = item;
// return list;
//}
public void ItemDismissed(int position)
{
//Queue.RemoveFromQueue(songList[position]);
//NotifyItemRemoved(position);
}
public bool RefreshDisabled()
{
return refreshDisabled;
}
public void DisableRefresh(bool disable)
{
refreshDisabled = disable;
}
}
}
@@ -18,15 +18,18 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static Android.Provider.MediaStore.Audio;
using RecyclerView = Android.Support.V7.Widget.RecyclerView;
namespace MusicApp.Resources.Portable_Class
{
public class PlaylistTracks : ListFragment, PopupMenu.IOnMenuItemClickListener, AppBarLayout.IOnOffsetChangedListener
public class PlaylistTracks : Fragment, PopupMenu.IOnMenuItemClickListener, AppBarLayout.IOnOffsetChangedListener
{
public static PlaylistTracks instance;
public string playlistName;
public Adapter adapter;
public RecyclerView ListView;
public PlaylistTrackAdapter adapter;
public View emptyView;
private Android.Support.V7.Widget.Helper.ItemTouchHelper itemTouchHelper;
public List<Song> result;
public long playlistId;
public string ytID;
@@ -36,6 +39,7 @@ namespace MusicApp.Resources.Portable_Class
private bool hasWriteAcess;
private bool forked;
private string nextPageToken = null;
public bool fullyLoadded = false;
public bool isEmpty = false;
public bool lastVisible = false;
private bool useHeader = true;
@@ -45,113 +49,14 @@ namespace MusicApp.Resources.Portable_Class
private List<string> ytTracksIDs = new List<string>();
private List<string> ytTracksIdsResult;
private string[] actions = new string[] { "Play", "Play Next", "Play Last", "Remove Track from playlist", "Add To Playlist" };
private bool loading;
public override void OnActivityCreated(Bundle savedInstanceState)
{
base.OnActivityCreated(savedInstanceState);
emptyView = LayoutInflater.Inflate(Resource.Layout.NoPlaylist, null);
ListView.EmptyView = emptyView;
ListView.Scroll += MainActivity.instance.Scroll;
ListView.ScrollStateChanged += ListView_ScrollStateChanged;
ListView.NestedScrollingEnabled = true;
MainActivity.instance.contentRefresh.Refresh += OnRefresh;
MainActivity.instance.OnPaddingChanged += OnPaddingChanged;
MainActivity.instance.DisplaySearch(1);
#pragma warning disable CS4014
PopulateList();
if (useHeader)
{
Activity.FindViewById<RelativeLayout>(Resource.Id.playlistHeader).Visibility = ViewStates.Visible;
((AppBarLayout.LayoutParams)Activity.FindViewById<CollapsingToolbarLayout>(Resource.Id.collapsingToolbar).LayoutParameters).ScrollFlags = AppBarLayout.LayoutParams.ScrollFlagScroll | AppBarLayout.LayoutParams.ScrollFlagExitUntilCollapsed | AppBarLayout.LayoutParams.ScrollFlagSnap;
Activity.FindViewById<AppBarLayout>(Resource.Id.appbar).AddOnOffsetChangedListener(this);
Activity.FindViewById<TextView>(Resource.Id.headerTitle).Text = playlistName;
Activity.FindViewById<ImageButton>(Resource.Id.headerPlay).Click += (sender, e0) => { PlayInOrder(0, false); };
Activity.FindViewById<ImageButton>(Resource.Id.headerShuffle).Click += (sender, e0) =>
{
if (playlistId != 0)
Playlist.RandomPlay(playlistId, Activity);
else
YoutubeEngine.RandomPlay(ytID);
};
Activity.FindViewById<ImageButton>(Resource.Id.headerMore).Click += (sender, e0) =>
{
PopupMenu menu = new PopupMenu(MainActivity.instance, MainActivity.instance.FindViewById<ImageButton>(Resource.Id.headerMore));
if (playlistId == 0 && hasWriteAcess)
menu.Inflate(Resource.Menu.ytplaylist_header_more);
else if (playlistId == 0 && forked)
menu.Inflate(Resource.Menu.ytplaylistnowrite_header_more);
else if (playlistId == 0)
menu.Inflate(Resource.Menu.ytplaylist_nowrite_nofork_header_more);
else
menu.Inflate(Resource.Menu.playlist_header_more);
menu.SetOnMenuItemClickListener(this);
menu.Show();
};
if (playlistId != 0)
{
Activity.FindViewById<TextView>(Resource.Id.headerAuthor).Text = MainActivity.account == null ? "by me" : "by " + MainActivity.account.DisplayName;
}
else if (ytID != null && ytID != "")
{
Activity.FindViewById<TextView>(Resource.Id.headerAuthor).Text = author;
Activity.FindViewById<TextView>(Resource.Id.headerNumber).Text = count.ToString() + " songs";
if (count == -1)
Activity.FindViewById<TextView>(Resource.Id.headerNumber).Text = "NaN songs";
Picasso.With(Android.App.Application.Context).Load(thumnailURI).Placeholder(Resource.Drawable.noAlbum).Resize(1080, 1080).CenterCrop().Into(Activity.FindViewById<ImageView>(Resource.Id.headerArt));
}
}
else
{
View header = LayoutInflater.Inflate(Resource.Layout.PlaylistSmallHeader, null, false);
ListView.AddHeaderView(header);
header.FindViewById<TextView>(Resource.Id.headerNumber).Text = tracks.Count + " songs";
header.FindViewById<ImageButton>(Resource.Id.headerPlay).Click += (sender, e0) => { PlayInOrder(0, false); };
header.FindViewById<ImageButton>(Resource.Id.headerShuffle).Click += (sender, e0) =>
{
if (tracks[0].IsYt)
{
System.Random r = new System.Random();
Song[] songs = tracks.OrderBy(x => r.Next()).ToArray();
YoutubeEngine.PlayFiles(songs);
}
else
{
List<string> tracksPath = new List<string>();
foreach (Song song in tracks)
tracksPath.Add(song.Path);
Intent intent = new Intent(MainActivity.instance, typeof(MusicPlayer));
intent.PutStringArrayListExtra("files", tracksPath);
intent.SetAction("RandomPlay");
MainActivity.instance.StartService(intent);
Intent inte = new Intent(MainActivity.instance, typeof(Player));
MainActivity.instance.StartActivity(inte);
}
};
header.FindViewById<ImageButton>(Resource.Id.headerMore).Click += (sender, e0) =>
{
PopupMenu menu = new PopupMenu(Activity, header.FindViewById<ImageButton>(Resource.Id.headerMore));
menu.Inflate(Resource.Menu.playlist_smallheader_more);
menu.SetOnMenuItemClickListener(this);
menu.Show();
};
if(MainActivity.Theme != 1)
{
header.SetBackgroundColor(Color.Argb(255, 255, 255, 255));
header.FindViewById<ImageButton>(Resource.Id.headerPlay).ImageTintList = ColorStateList.ValueOf(Color.Black);
header.FindViewById<ImageButton>(Resource.Id.headerShuffle).ImageTintList = ColorStateList.ValueOf(Color.Black);
header.FindViewById<ImageButton>(Resource.Id.headerMore).ImageTintList = ColorStateList.ValueOf(Color.Black);
}
}
}
public bool OnMenuItemClick(IMenuItem item)
@@ -163,6 +68,7 @@ namespace MusicApp.Resources.Portable_Class
break;
case Resource.Id.fork:
#pragma warning disable CS4014
YoutubeEngine.ForkPlaylist(ytID);
break;
@@ -279,15 +185,6 @@ namespace MusicApp.Resources.Portable_Class
MainActivity.instance.SupportFragmentManager.PopBackStack();
}
private void ListView_ScrollStateChanged(object sender, AbsListView.ScrollStateChangedEventArgs e)
{
if (lastVisible && e.ScrollState == ScrollState.Idle)
{
lastVisible = false;
LoadMore();
}
}
public void OnPaddingChanged(object sender, PaddingChange e)
{
if (MainActivity.paddingBot > e.oldPadding)
@@ -333,10 +230,13 @@ namespace MusicApp.Resources.Portable_Class
if (YoutubeEngine.instances[i].focused)
selectedTab = i;
}
MainActivity.instance.SupportFragmentManager.BeginTransaction().Attach(YoutubeEngine.instances[selectedTab]).Commit();
MainActivity.instance.SupportFragmentManager.BeginTransaction().Remove(instance).Commit();
if (Player.instance == null)
{
MainActivity.instance.SupportFragmentManager.BeginTransaction().Attach(YoutubeEngine.instances[selectedTab]).Commit();
MainActivity.instance.SupportFragmentManager.BeginTransaction().Remove(instance).Commit();
}
}
else
else if (Player.instance == null)
MainActivity.instance.SupportFragmentManager.PopBackStack();
base.OnStop();
@@ -345,11 +245,121 @@ namespace MusicApp.Resources.Portable_Class
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = base.OnCreateView(inflater, container, savedInstanceState);
View view = inflater.Inflate(Resource.Layout.RecyclerFragment, container, false);
view.SetPadding(0, 0, 0, MainActivity.defaultPaddingBot);
ListView = view.FindViewById<RecyclerView>(Resource.Id.recycler);
ListView.SetLayoutManager(new Android.Support.V7.Widget.LinearLayoutManager(MainActivity.instance));
ListView.SetAdapter(new PlaylistTrackAdapter(new List<Song>()));
ListView.ScrollChange += ListView_ScrollChange;
Android.Support.V7.Widget.Helper.ItemTouchHelper.Callback callback = new PlaylistItemTouch(adapter);
itemTouchHelper = new Android.Support.V7.Widget.Helper.ItemTouchHelper(callback);
itemTouchHelper.AttachToRecyclerView(ListView);
PopulateList();
CreateHeader();
return view;
}
private void ListView_ScrollChange(object sender, View.ScrollChangeEventArgs e)
{
if (((Android.Support.V7.Widget.LinearLayoutManager)ListView.GetLayoutManager()).FindLastVisibleItemPosition() == adapter.ItemCount - 1)
LoadMore();
}
void CreateHeader()
{
if (useHeader)
{
Activity.FindViewById<RelativeLayout>(Resource.Id.playlistHeader).Visibility = ViewStates.Visible;
((AppBarLayout.LayoutParams)Activity.FindViewById<CollapsingToolbarLayout>(Resource.Id.collapsingToolbar).LayoutParameters).ScrollFlags = AppBarLayout.LayoutParams.ScrollFlagScroll | AppBarLayout.LayoutParams.ScrollFlagExitUntilCollapsed;
Activity.FindViewById<AppBarLayout>(Resource.Id.appbar).AddOnOffsetChangedListener(this);
Activity.FindViewById<TextView>(Resource.Id.headerTitle).Text = playlistName;
Activity.FindViewById<ImageButton>(Resource.Id.headerPlay).Click += (sender, e0) => { PlayInOrder(0, false); };
Activity.FindViewById<ImageButton>(Resource.Id.headerShuffle).Click += (sender, e0) =>
{
if (playlistId != 0)
Playlist.RandomPlay(playlistId, Activity);
else
YoutubeEngine.RandomPlay(ytID);
};
Activity.FindViewById<ImageButton>(Resource.Id.headerMore).Click += (sender, e0) =>
{
PopupMenu menu = new PopupMenu(MainActivity.instance, MainActivity.instance.FindViewById<ImageButton>(Resource.Id.headerMore));
if (playlistId == 0 && hasWriteAcess)
menu.Inflate(Resource.Menu.ytplaylist_header_more);
else if (playlistId == 0 && forked)
menu.Inflate(Resource.Menu.ytplaylistnowrite_header_more);
else if (playlistId == 0)
menu.Inflate(Resource.Menu.ytplaylist_nowrite_nofork_header_more);
else
menu.Inflate(Resource.Menu.playlist_header_more);
menu.SetOnMenuItemClickListener(this);
menu.Show();
};
if (playlistId != 0)
{
Activity.FindViewById<TextView>(Resource.Id.headerAuthor).Text = MainActivity.account == null ? "by me" : "by " + MainActivity.account.DisplayName;
}
else if (ytID != null && ytID != "")
{
Activity.FindViewById<TextView>(Resource.Id.headerAuthor).Text = author;
Activity.FindViewById<TextView>(Resource.Id.headerNumber).Text = count.ToString() + " songs";
if (count == -1)
Activity.FindViewById<TextView>(Resource.Id.headerNumber).Text = "NaN songs";
Picasso.With(Android.App.Application.Context).Load(thumnailURI).Placeholder(Resource.Drawable.noAlbum).Resize(1080, 1080).CenterCrop().Into(Activity.FindViewById<ImageView>(Resource.Id.headerArt));
}
}
else
{
View header = LayoutInflater.Inflate(Resource.Layout.PlaylistSmallHeader, null, false);
//ListView.AddHeaderView(header);
header.FindViewById<TextView>(Resource.Id.headerNumber).Text = tracks.Count + " songs";
header.FindViewById<ImageButton>(Resource.Id.headerPlay).Click += (sender, e0) => { PlayInOrder(0, false); };
header.FindViewById<ImageButton>(Resource.Id.headerShuffle).Click += (sender, e0) =>
{
if (tracks[0].IsYt)
{
System.Random r = new System.Random();
Song[] songs = tracks.OrderBy(x => r.Next()).ToArray();
YoutubeEngine.PlayFiles(songs);
}
else
{
List<string> tracksPath = new List<string>();
foreach (Song song in tracks)
tracksPath.Add(song.Path);
Intent intent = new Intent(MainActivity.instance, typeof(MusicPlayer));
intent.PutStringArrayListExtra("files", tracksPath);
intent.SetAction("RandomPlay");
MainActivity.instance.StartService(intent);
Intent inte = new Intent(MainActivity.instance, typeof(Player));
MainActivity.instance.StartActivity(inte);
}
};
header.FindViewById<ImageButton>(Resource.Id.headerMore).Click += (sender, e0) =>
{
PopupMenu menu = new PopupMenu(Activity, header.FindViewById<ImageButton>(Resource.Id.headerMore));
menu.Inflate(Resource.Menu.playlist_smallheader_more);
menu.SetOnMenuItemClickListener(this);
menu.Show();
};
if (MainActivity.Theme != 1)
{
header.SetBackgroundColor(Color.Argb(255, 255, 255, 255));
header.FindViewById<ImageButton>(Resource.Id.headerPlay).ImageTintList = ColorStateList.ValueOf(Color.Black);
header.FindViewById<ImageButton>(Resource.Id.headerShuffle).ImageTintList = ColorStateList.ValueOf(Color.Black);
header.FindViewById<ImageButton>(Resource.Id.headerMore).ImageTintList = ColorStateList.ValueOf(Color.Black);
}
}
}
public static Fragment NewInstance(List<Song> songs, string playlistName)
{
instance = new PlaylistTracks { Arguments = new Bundle() };
@@ -423,17 +433,17 @@ namespace MusicApp.Resources.Portable_Class
musicCursor.Close();
}
adapter = new Adapter(Android.App.Application.Context, Resource.Layout.SongList, tracks)
{
listPadding = MainActivity.paddingBot - MainActivity.defaultPaddingBot
};
ListAdapter = adapter;
ListView.Adapter = adapter;
ListView.TextFilterEnabled = true;
ListView.ItemClick += ListView_ItemClick;
ListView.ItemLongClick += ListView_ItemLongClick;
//adapter = new PlaylistTrackAdapter(tracks)
//{
// listPadding = MainActivity.paddingBot - MainActivity.defaultPaddingBot
//};
adapter.AddToList(tracks);
adapter.listPadding = MainActivity.paddingBot - MainActivity.defaultPaddingBot;
adapter.ItemClick += ListView_ItemClick;
adapter.ItemLongClick += ListView_ItemLongClick;
ListView.SetAdapter(adapter);
if (adapter == null || adapter.Count == 0)
if (adapter == null || adapter.ItemCount == 0)
{
isEmpty = true;
Activity.AddContentView(emptyView, View.LayoutParameters);
@@ -465,17 +475,17 @@ namespace MusicApp.Resources.Portable_Class
}
nextPageToken = ytPlaylist.NextPageToken;
adapter = new Adapter(Android.App.Application.Context, Resource.Layout.SongList, tracks)
{
listPadding = MainActivity.paddingBot - MainActivity.defaultPaddingBot
};
ListAdapter = adapter;
ListView.Adapter = adapter;
ListView.TextFilterEnabled = true;
ListView.ItemClick += ListView_ItemClick;
ListView.ItemLongClick += ListView_ItemLongClick;
//adapter = new PlaylistTrackAdapter(tracks)
//{
// listPadding = MainActivity.paddingBot - MainActivity.defaultPaddingBot
//};
adapter.AddToList(tracks);
adapter.listPadding = MainActivity.paddingBot - MainActivity.defaultPaddingBot;
adapter.ItemClick += ListView_ItemClick;
adapter.ItemLongClick += ListView_ItemLongClick;
ListView.SetAdapter(adapter);
if (adapter == null || adapter.Count == 0)
if (adapter == null || adapter.ItemCount == 0)
{
isEmpty = true;
Activity.AddContentView(emptyView, View.LayoutParameters);
@@ -483,17 +493,17 @@ namespace MusicApp.Resources.Portable_Class
}
else if(tracks.Count != 0)
{
adapter = new Adapter(Android.App.Application.Context, Resource.Layout.SongList, tracks)
{
listPadding = MainActivity.paddingBot - MainActivity.defaultPaddingBot
};
ListAdapter = adapter;
ListView.Adapter = adapter;
ListView.TextFilterEnabled = true;
ListView.ItemClick += ListView_ItemClick;
ListView.ItemLongClick += ListView_ItemLongClick;
//adapter = new PlaylistTrackAdapter(tracks)
//{
// listPadding = MainActivity.paddingBot - MainActivity.defaultPaddingBot
//};
adapter.AddToList(tracks);
adapter.listPadding = MainActivity.paddingBot - MainActivity.defaultPaddingBot;
adapter.ItemClick += ListView_ItemClick;
adapter.ItemLongClick += ListView_ItemLongClick;
ListView.SetAdapter(adapter);
if (adapter == null || adapter.Count == 0)
if (adapter == null || adapter.ItemCount == 0)
{
isEmpty = true;
Activity.AddContentView(emptyView, View.LayoutParameters);
@@ -509,9 +519,10 @@ namespace MusicApp.Resources.Portable_Class
public async Task LoadMore()
{
if (nextPageToken == null)
if (nextPageToken == null || loading)
return;
loading = true;
var ytPlaylistRequest = YoutubeEngine.youtubeService.PlaylistItems.List("snippet, contentDetails");
ytPlaylistRequest.PlaylistId = ytID;
ytPlaylistRequest.MaxResults = 50;
@@ -530,7 +541,10 @@ namespace MusicApp.Resources.Portable_Class
}
nextPageToken = ytPlaylist.NextPageToken;
if (nextPageToken == null)
fullyLoadded = true;
adapter.NotifyDataSetChanged();
loading = false;
}
public void Search(string search)
@@ -547,25 +561,27 @@ namespace MusicApp.Resources.Portable_Class
ytTracksIdsResult.Add(ytTracksIDs[i]);
}
}
adapter = new Adapter(Android.App.Application.Context, Resource.Layout.SongList, result)
adapter = new PlaylistTrackAdapter(result)
{
listPadding = MainActivity.paddingBot - MainActivity.defaultPaddingBot
};
ListAdapter = adapter;
adapter.ItemClick += ListView_ItemClick;
adapter.ItemLongClick += ListView_ItemLongClick;
ListView.SetAdapter(adapter);
}
private void ListView_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
private void ListView_ItemClick(object sender, int Position)
{
PlayInOrder(useHeader ? e.Position : e.Position - 1, true);
PlayInOrder(useHeader ? Position : Position - 1, true);
}
private void ListView_ItemLongClick(object sender, AdapterView.ItemLongClickEventArgs e)
private void ListView_ItemLongClick(object sender, int Position)
{
Song item = tracks[useHeader ? e.Position : e.Position - 1];
if (result != null && result.Count > (useHeader ? e.Position : e.Position - 1))
item = result[useHeader ? e.Position : e.Position - 1];
Song item = tracks[useHeader ? Position : Position - 1];
if (result != null && result.Count > (useHeader ? Position : Position - 1))
item = result[useHeader ? Position : Position - 1];
More(item, useHeader ? e.Position : e.Position - 1);
More(item, useHeader ? Position : Position - 1);
}
public void More(Song item, int position)
@@ -635,7 +651,7 @@ namespace MusicApp.Resources.Portable_Class
if (item.IsYt)
YoutubeEngine.Download(item.Title, item.Path);
else
Browse.EditMetadata(item, "PlaylistTracks", ListView.OnSaveInstanceState());
Browse.EditMetadata(item, "PlaylistTracks", ListView.GetLayoutManager().OnSaveInstanceState());
break;
default:
@@ -680,7 +696,7 @@ namespace MusicApp.Resources.Portable_Class
if (item.IsYt)
YoutubeEngine.Download(item.Title, item.Path);
else
Browse.EditMetadata(item, "PlaylistTracks", ListView.OnSaveInstanceState());
Browse.EditMetadata(item, "PlaylistTracks", ListView.GetLayoutManager().OnSaveInstanceState());
break;
default:
@@ -703,7 +719,7 @@ namespace MusicApp.Resources.Portable_Class
if (!songs[0].IsYt)
{
Browse.act = Activity;
Browse.Play(songs[0], useTransition ? ListView.GetChildAt(fromPosition - ListView.FirstVisiblePosition).FindViewById<ImageView>(Resource.Id.albumArt) : null);
Browse.Play(songs[0], useTransition ? ListView.GetChildAt(fromPosition - ((Android.Support.V7.Widget.LinearLayoutManager)ListView.GetLayoutManager()).FindFirstVisibleItemPosition()).FindViewById<ImageView>(Resource.Id.albumArt) : null);
}
else
YoutubeEngine.Play(songs[0].youtubeID, songs[0].Title, songs[0].Artist, songs[0].Album);
@@ -733,7 +749,7 @@ namespace MusicApp.Resources.Portable_Class
ytTracksIDs.Remove(ytTrackID);
ytTracksIdsResult?.Remove(ytTrackID);
adapter.Remove(item);
if (adapter == null || adapter.Count == 0)
if (adapter == null || adapter.ItemCount == 0)
{
isEmpty = true;
Activity.AddContentView(emptyView, View.LayoutParameters);
@@ -747,7 +763,7 @@ namespace MusicApp.Resources.Portable_Class
resolver.Delete(uri, MediaStore.Audio.Playlists.Members.Id + "=?", new string[] { item.Id.ToString() });
tracks.Remove(item);
adapter.Remove(item);
if (adapter == null || adapter.Count == 0)
if (adapter == null || adapter.ItemCount == 0)
{
isEmpty = true;
Activity.AddContentView(emptyView, View.LayoutParameters);
@@ -760,7 +776,7 @@ namespace MusicApp.Resources.Portable_Class
instance = this;
if (MainActivity.parcelable != null && MainActivity.parcelableSender == "PlaylistTrack")
{
ListView.OnRestoreInstanceState(MainActivity.parcelable);
ListView.GetLayoutManager().OnRestoreInstanceState(MainActivity.parcelable);
MainActivity.parcelable = null;
MainActivity.parcelableSender = null;
}
@@ -783,4 +799,4 @@ namespace MusicApp.Resources.Portable_Class
}
}
}
}
}
@@ -90,15 +90,15 @@ namespace MusicApp.Resources.Portable_Class
};
}
//if (!holder.reorder.HasOnClickListeners)
//{
// holder.reorder.Click += (sender, e) =>
// {
// Queue.instance.itemTouchHelper.StartDrag(viewHolder);
// MainActivity.instance.contentRefresh.SetEnabled(false);
// Queue.instance.adapter.DisableRefresh(true);
// };
//}
if (!holder.reorder.HasOnClickListeners)
{
holder.reorder.Touch += (sender, e) =>
{
Queue.instance.itemTouchHelper.StartDrag(viewHolder);
MainActivity.instance.contentRefresh.SetEnabled(false);
Queue.instance.adapter.DisableRefresh(true);
};
}
if (songList[position].queueSlot == MusicPlayer.CurrentID())
@@ -219,7 +219,7 @@ namespace MusicApp.Resources.Portable_Class
if (MusicPlayer.CurrentID() == fromPosition)
MusicPlayer.currentID = toPosition;
MusicPlayer.instance.UpdateQueueSlots();
MusicPlayer.instance?.UpdateQueueSlots();
}
List<T> Swap<T>(List<T> list, int fromPosition, int toPosition)
+300 -288
View File
File diff suppressed because it is too large Load Diff
+11
View File
@@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M0 0h24v24H0z"/>
<path
android:fillColor="#ffffff"
android:pathData="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/>
</vector>
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="8dp" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@android:color/holo_red_light" >
<ImageButton
android:layout_width="36dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:src="@drawable/Delete"
android:id="@+id/deleteButton"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/foreground">
<ImageView
android:id="@+id/albumArt"
android:layout_width="90dp"
android:layout_height="90dp"
android:padding="5dp"
android:gravity="center"
android:layout_alignParentLeft="true"
android:src="@drawable/MusicIcon" />
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textLayout"
android:paddingLeft="100dp">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16dip"
android:textColor="#000"
android:textStyle="bold" />
<TextView
android:id="@+id/artist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14dip"
android:textColor="#000" />
</LinearLayout>
<ImageView
android:id="@+id/moreButton"
android:layout_width="30dp"
android:layout_height="30dp"
android:padding="5dp"
android:clickable="true"
android:background="@null"
android:src="@drawable/ic_more_vert_black_24dp"
android:gravity="center_vertical"
android:layout_centerVertical="true"
android:layout_alignParentRight="true" />
</RelativeLayout>
</RelativeLayout >