mirror of
https://github.com/zoriya/Opus.git
synced 2026-06-07 07:54:45 +00:00
PlaylistTrack now use a recycler, adding loading bar and an item touch handler.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
Generated
+300
-288
File diff suppressed because it is too large
Load Diff
@@ -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 >
|
||||
Reference in New Issue
Block a user