diff --git a/MPfm/MPfm.Android/Classes/Activities/PlaylistActivity.cs b/MPfm/MPfm.Android/Classes/Activities/PlaylistActivity.cs index dc8851b1..46f64781 100644 --- a/MPfm/MPfm.Android/Classes/Activities/PlaylistActivity.cs +++ b/MPfm/MPfm.Android/Classes/Activities/PlaylistActivity.cs @@ -43,6 +43,7 @@ public class PlaylistActivity : BaseActivity, IPlaylistView CustomListView _listView; PlaylistListAdapter _listAdapter; Playlist _playlist; + string _sourceActivityType; protected override void OnCreate(Bundle bundle) { @@ -65,6 +66,9 @@ protected override void OnCreate(Bundle bundle) _listView.ItemClick += ListViewOnItemClick; _listView.ItemLongClick += ListViewOnItemLongClick; + // Save the source activity type for later (for providing Up navigation) + _sourceActivityType = Intent.GetStringExtra("sourceActivity"); + // Since the onViewReady action could not be added to an intent, tell the NavMgr the view is ready ((AndroidNavigationManager)_navigationManager).SetPlaylistActivityInstance(this); } @@ -139,8 +143,9 @@ public override bool OnOptionsItemSelected(IMenuItem item) switch (item.ItemId) { case global::Android.Resource.Id.Home: - var intent = new Intent(this, typeof (MainActivity)); - intent.AddFlags(ActivityFlags.ClearTop | ActivityFlags.SingleTop); + var type = Type.GetType(_sourceActivityType); + var intent = new Intent(this, type); + intent.AddFlags(ActivityFlags.ClearTop | ActivityFlags.SingleTop); this.StartActivity(intent); this.Finish(); return true; diff --git a/MPfm/MPfm.Android/Classes/Adapters/PlaylistListAdapter.cs b/MPfm/MPfm.Android/Classes/Adapters/PlaylistListAdapter.cs index 9f4c6e73..fdf52ea4 100644 --- a/MPfm/MPfm.Android/Classes/Adapters/PlaylistListAdapter.cs +++ b/MPfm/MPfm.Android/Classes/Adapters/PlaylistListAdapter.cs @@ -16,13 +16,9 @@ // along with MPfm. If not, see . using System; -using System.Collections.Generic; -using Android.App; -using Android.Graphics; using Android.Views; using Android.Views.Animations; using Android.Widget; -using MPfm.Library.Objects; using MPfm.Sound.AudioFiles; using MPfm.Sound.Playlists; using org.sessionsapp.android; @@ -79,17 +75,23 @@ public override View GetView(int position, View convertView, ViewGroup parent) return view; view.Tag = position; - view.SetOnTouchListener(this); + //view.SetOnTouchListener(this); var index = view.FindViewById(Resource.Id.playlistCell_lblIndex); var title = view.FindViewById(Resource.Id.playlistCell_lblTitle); var subtitle = view.FindViewById(Resource.Id.playlistCell_lblSubtitle); + var imageNowPlaying = view.FindViewById(Resource.Id.playlistCell_imageNowPlaying); //index.Text = item.AudioFile.TrackNumber.ToString(); index.Text = (position+1).ToString(); title.Text = item.AudioFile.ArtistName + " / " + item.AudioFile.Title; subtitle.Text = item.AudioFile.Length; + if (item.AudioFile != null && item.AudioFile.Id == _nowPlayingAudioFileId) + imageNowPlaying.Visibility = ViewStates.Visible; + else + imageNowPlaying.Visibility = ViewStates.Gone; + return view; } @@ -214,24 +216,24 @@ public void OnClick(View v) public bool OnTouch(View v, MotionEvent e) { - Console.WriteLine("PlaylistListAdapter - OnTouch - action: {0} buttonState: {1} downTime: {2} eventTime: {3} x: {4} y: {5}", e.Action, e.ButtonState, e.DownTime, e.EventTime, e.GetX(), e.GetY()); - - float x = e.GetX(); - float y = e.GetY(); - - // Keep cancel on top because the flag can contain both move and cancel. - if (e.Action.HasFlag(MotionEventActions.Cancel)) - { - Console.WriteLine("PlaylistListAdapter - OnTouch - Cancel - (x,y): ({0},{1})", x, y); - _listView.IsScrollable = true; - } - else if (e.Action.HasFlag(MotionEventActions.Move)) - { - Console.WriteLine("PlaylistListAdapter - OnTouch - Move - (x,y): ({0},{1})", x, y); - _listView.IsScrollable = false; - } - - //Console.WriteLine("PlaylistListAdapter - OnTouch - Current cell - height: {0} - position: {1}", v.Height, (int)v.Tag); + //Console.WriteLine("PlaylistListAdapter - OnTouch - action: {0} buttonState: {1} downTime: {2} eventTime: {3} x: {4} y: {5}", e.Action, e.ButtonState, e.DownTime, e.EventTime, e.GetX(), e.GetY()); + + //float x = e.GetX(); + //float y = e.GetY(); + + //// Keep cancel on top because the flag can contain both move and cancel. + //if (e.Action.HasFlag(MotionEventActions.Cancel)) + //{ + // Console.WriteLine("PlaylistListAdapter - OnTouch - Cancel - (x,y): ({0},{1})", x, y); + // _listView.IsScrollable = true; + //} + //else if (e.Action.HasFlag(MotionEventActions.Move)) + //{ + // Console.WriteLine("PlaylistListAdapter - OnTouch - Move - (x,y): ({0},{1})", x, y); + // _listView.IsScrollable = false; + //} + + ////Console.WriteLine("PlaylistListAdapter - OnTouch - Current cell - height: {0} - position: {1}", v.Height, (int)v.Tag); return true; } diff --git a/MPfm/MPfm.Android/Classes/Controls/CustomListView.cs b/MPfm/MPfm.Android/Classes/Controls/CustomListView.cs index a9bbcfda..77c3cb68 100644 --- a/MPfm/MPfm.Android/Classes/Controls/CustomListView.cs +++ b/MPfm/MPfm.Android/Classes/Controls/CustomListView.cs @@ -17,6 +17,7 @@ using System; using Android.Content; +using Android.Graphics; using Android.Runtime; using Android.Util; using Android.Views; @@ -30,7 +31,9 @@ namespace org.sessionsapp.android /// public class CustomListView : ListView { + public bool CanItemsBeMoved { get; set; } public bool IsScrollable { get; set; } + public bool IsMovingItem { get; private set; } protected CustomListView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { @@ -54,17 +57,98 @@ public CustomListView(Context context, IAttributeSet attrs, int defStyle) : base private void Initialize() { - Console.WriteLine("CustomListView - Initialize"); IsScrollable = true; + CanItemsBeMoved = true; + IsMovingItem = false; } - public override bool DispatchTouchEvent(Android.Views.MotionEvent e) + public override bool DispatchTouchEvent(MotionEvent e) { - // Cancel scrolling - if(!IsScrollable && e.Action.HasFlag(MotionEventActions.Move)) - return true; + //Console.WriteLine("CustomListView - DispatchTouchEvent - action: {0} buttonState: {1} downTime: {2} eventTime: {3} x,y: ({4},{5}) width: {6} density: {7} canItemsBeMoved: {8} isMovingItem: {9} isScrollable: {10}", e.Action, e.ButtonState, e.DownTime, e.EventTime, e.GetX(), e.GetY(), Width, Resources.DisplayMetrics.Density, CanItemsBeMoved, IsMovingItem, IsScrollable); + Console.WriteLine("CustomListView - DispatchTouchEvent - action: {0} x,y: ({1},{2})", e.Action, e.GetX(), e.GetY()); + + float density = Resources.DisplayMetrics.Density; + float x = e.GetX(); + float y = e.GetY(); + + if (CanItemsBeMoved && !IsMovingItem && x >= Width - 48 * density) + { + // The user is trying to move an item using the right hand 'button'. + Console.WriteLine("CustomListView - DispatchTouchEvent - Starting to move item..."); + View viewItemMove = GetChildAtPosition(x, y); + if (viewItemMove != null) + { + IsMovingItem = true; + IsScrollable = false; + int tag = -1; + if (viewItemMove.Tag != null) + tag = (int)viewItemMove.Tag; + + Console.WriteLine("CustomListView - DispatchTouchEvent - Found moving item! tag: {0}", tag); + } + else + { + Console.WriteLine("CustomListView - DispatchTouchEvent - Did NOT find moving item :-("); + } + } + + // Keep cancel on top because the flag can contain both move and cancel. + // if (e.Action.HasFlag(MotionEventActions.Cancel)) // This was cancel when using OnTouchListener on a child view + if(e.Action.HasFlag(MotionEventActions.Up)) + { + //Console.WriteLine("CustomListView - DispatchTouchEvent - Up - (x,y): ({0},{1})", x, y); + Console.WriteLine("CustomListView - DispatchTouchEvent - CANCELLING MOVE..."); + IsMovingItem = false; + IsScrollable = true; + } + else if (e.Action.HasFlag(MotionEventActions.Move)) + { + // Block scroll + if(!IsScrollable) + return true; + } + + // Try to find the item over the finger + View view = GetChildAtPosition(x, y); + if (view != null) + { + int tag = -1; + if (view.Tag != null) + tag = (int)view.Tag; + + Console.WriteLine("CustomListView - DispatchTouchEvent - Found finger over view! tag: {0}", tag); + } + else + { + Console.WriteLine("CustomListView - DispatchTouchEvent - Did NOT find finger over view :-("); + } return base.DispatchTouchEvent(e); } + + private View GetChildAtPosition(float x, float y) + { + View returnView = null; + int lastIndex = LastVisiblePosition - FirstVisiblePosition; + for (int a = 0; a < lastIndex; a++) + { + View view = GetChildAt(a); + if (view != null) + { + Rect rect = new Rect(); + view.GetHitRect(rect); + bool isOverItem = y >= rect.Top && y <= rect.Bottom; + //Console.WriteLine("CustomListView - GetChildAtPosition - Finding rects - position: {0} hitRect(x,y): ({1},{2})", a, rect.Left, rect.Top); + if (isOverItem) + { + Console.WriteLine("CustomListView - GetChildAtPosition - FOUND CHILD - position: {0} hitRect(x,y): ({1},{2})", a, rect.Left, rect.Top); + returnView = view; + break; + } + } + } + + return returnView; + } } } \ No newline at end of file diff --git a/MPfm/MPfm.Android/Classes/Navigation/AndroidNavigationManager.cs b/MPfm/MPfm.Android/Classes/Navigation/AndroidNavigationManager.cs index f9289d74..625c6a46 100644 --- a/MPfm/MPfm.Android/Classes/Navigation/AndroidNavigationManager.cs +++ b/MPfm/MPfm.Android/Classes/Navigation/AndroidNavigationManager.cs @@ -244,9 +244,15 @@ protected override void CreateMarkerDetailsViewInternal(IBaseView sourceView, Ac StartActivity(activity, typeof(MarkerDetailsActivity)); } + protected override void CreatePlaylistViewInternal(IBaseView sourceView, Action onViewReady) + { + _onPlaylistViewReady = onViewReady; + var activity = GetActivityFromView(sourceView); + StartActivity(activity, typeof(PlaylistActivity)); + } + protected override void CreateSyncViewInternal(Action onViewReady) { - // TODO: Add source view _onSyncViewReady = onViewReady; var intent = new Intent(MainActivity, typeof(SyncActivity)); MainActivity.StartActivity(intent); @@ -273,13 +279,6 @@ protected override void CreateSyncDownloadViewInternal(Action onViewR MainActivity.StartActivity(intent); } - protected override void CreatePlaylistViewInternal(Action onViewReady) - { - _onPlaylistViewReady = onViewReady; - var intent = new Intent(MainActivity, typeof(PlaylistActivity)); - MainActivity.StartActivity(intent); - } - public void SetAboutActivityInstance(AboutActivity activity) { if (_onAboutViewReady != null) diff --git a/MPfm/MPfm.Android/MPfm.Android.csproj b/MPfm/MPfm.Android/MPfm.Android.csproj index e0bc4ac5..f0d7f994 100644 --- a/MPfm/MPfm.Android/MPfm.Android.csproj +++ b/MPfm/MPfm.Android/MPfm.Android.csproj @@ -500,6 +500,10 @@ Designer + + + + diff --git a/MPfm/MPfm.Android/Resources/Layout/PlaylistCell.axml b/MPfm/MPfm.Android/Resources/Layout/PlaylistCell.axml index 87d72196..447e7ae2 100644 --- a/MPfm/MPfm.Android/Resources/Layout/PlaylistCell.axml +++ b/MPfm/MPfm.Android/Resources/Layout/PlaylistCell.axml @@ -38,13 +38,6 @@ android:textColor="@color/list_secondarytext" android:textSize="12dp" /> - + \ No newline at end of file diff --git a/MPfm/MPfm.Android/Resources/Resource.Designer.cs b/MPfm/MPfm.Android/Resources/Resource.Designer.cs index 621cef0e..371ce2c2 100644 --- a/MPfm/MPfm.Android/Resources/Resource.Designer.cs +++ b/MPfm/MPfm.Android/Resources/Resource.Designer.cs @@ -244,85 +244,88 @@ public partial class Drawable public const int icon_linux = 2130837525; // aapt resource value: 0x7f020016 - public const int icon_osx = 2130837526; + public const int icon_move = 2130837526; // aapt resource value: 0x7f020017 - public const int icon_phone = 2130837527; + public const int icon_osx = 2130837527; // aapt resource value: 0x7f020018 - public const int icon_play = 2130837528; + public const int icon_phone = 2130837528; // aapt resource value: 0x7f020019 - public const int icon_speaker = 2130837529; + public const int icon_play = 2130837529; // aapt resource value: 0x7f02001a - public const int icon_tablet = 2130837530; + public const int icon_speaker = 2130837530; // aapt resource value: 0x7f02001b - public const int icon_transparent = 2130837531; + public const int icon_tablet = 2130837531; // aapt resource value: 0x7f02001c - public const int icon_trash = 2130837532; + public const int icon_transparent = 2130837532; // aapt resource value: 0x7f02001d - public const int icon_vinyl = 2130837533; + public const int icon_trash = 2130837533; // aapt resource value: 0x7f02001e - public const int icon_windows = 2130837534; + public const int icon_vinyl = 2130837534; // aapt resource value: 0x7f02001f - public const int list_selector = 2130837535; + public const int icon_windows = 2130837535; // aapt resource value: 0x7f020020 - public const int player_close = 2130837536; + public const int list_selector = 2130837536; // aapt resource value: 0x7f020021 - public const int player_close_on = 2130837537; + public const int player_close = 2130837537; // aapt resource value: 0x7f020022 - public const int player_next = 2130837538; + public const int player_close_on = 2130837538; // aapt resource value: 0x7f020023 - public const int player_next_on = 2130837539; + public const int player_next = 2130837539; // aapt resource value: 0x7f020024 - public const int player_pause = 2130837540; + public const int player_next_on = 2130837540; // aapt resource value: 0x7f020025 - public const int player_pause_on = 2130837541; + public const int player_pause = 2130837541; // aapt resource value: 0x7f020026 - public const int player_play = 2130837542; + public const int player_pause_on = 2130837542; // aapt resource value: 0x7f020027 - public const int player_play_on = 2130837543; + public const int player_play = 2130837543; // aapt resource value: 0x7f020028 - public const int player_playlist = 2130837544; + public const int player_play_on = 2130837544; // aapt resource value: 0x7f020029 - public const int player_playlist_on = 2130837545; + public const int player_playlist = 2130837545; // aapt resource value: 0x7f02002a - public const int player_previous = 2130837546; + public const int player_playlist_on = 2130837546; // aapt resource value: 0x7f02002b - public const int player_previous_on = 2130837547; + public const int player_previous = 2130837547; // aapt resource value: 0x7f02002c - public const int player_repeat = 2130837548; + public const int player_previous_on = 2130837548; // aapt resource value: 0x7f02002d - public const int player_repeat_on = 2130837549; + public const int player_repeat = 2130837549; // aapt resource value: 0x7f02002e - public const int player_shuffle = 2130837550; + public const int player_repeat_on = 2130837550; // aapt resource value: 0x7f02002f - public const int player_shuffle_on = 2130837551; + public const int player_shuffle = 2130837551; // aapt resource value: 0x7f020030 - public const int Splash = 2130837552; + public const int player_shuffle_on = 2130837552; + + // aapt resource value: 0x7f020031 + public const int Splash = 2130837553; static Drawable() { @@ -820,17 +823,17 @@ public partial class Id // aapt resource value: 0x7f0c008a public const int player_waveFormView = 2131493002; - // aapt resource value: 0x7f0c00a0 - public const int playlistCell_imageDelete = 2131493024; - - // aapt resource value: 0x7f0c009e - public const int playlistCell_imageMove = 2131493022; + // aapt resource value: 0x7f0c009f + public const int playlistCell_imageDelete = 2131493023; // aapt resource value: 0x7f0c00a1 - public const int playlistCell_imageNowPlaying = 2131493025; + public const int playlistCell_imageMove = 2131493025; - // aapt resource value: 0x7f0c009f - public const int playlistCell_imagePlay = 2131493023; + // aapt resource value: 0x7f0c00a0 + public const int playlistCell_imageNowPlaying = 2131493024; + + // aapt resource value: 0x7f0c009e + public const int playlistCell_imagePlay = 2131493022; // aapt resource value: 0x7f0c009b public const int playlistCell_lblIndex = 2131493019; diff --git a/MPfm/MPfm.Android/Resources/drawable-hdpi/icon_move.png b/MPfm/MPfm.Android/Resources/drawable-hdpi/icon_move.png new file mode 100644 index 00000000..2c8fcb01 Binary files /dev/null and b/MPfm/MPfm.Android/Resources/drawable-hdpi/icon_move.png differ diff --git a/MPfm/MPfm.Android/Resources/drawable-mdpi/icon_move.png b/MPfm/MPfm.Android/Resources/drawable-mdpi/icon_move.png new file mode 100644 index 00000000..289efb14 Binary files /dev/null and b/MPfm/MPfm.Android/Resources/drawable-mdpi/icon_move.png differ diff --git a/MPfm/MPfm.Android/Resources/drawable-xhdpi/icon_move.png b/MPfm/MPfm.Android/Resources/drawable-xhdpi/icon_move.png new file mode 100644 index 00000000..ae300115 Binary files /dev/null and b/MPfm/MPfm.Android/Resources/drawable-xhdpi/icon_move.png differ diff --git a/MPfm/MPfm.Android/Resources/drawable-xxhdpi/icon_move.png b/MPfm/MPfm.Android/Resources/drawable-xxhdpi/icon_move.png new file mode 100644 index 00000000..df643339 Binary files /dev/null and b/MPfm/MPfm.Android/Resources/drawable-xxhdpi/icon_move.png differ diff --git a/MPfm/MPfm.MVP/Navigation/MobileNavigationManager.cs b/MPfm/MPfm.MVP/Navigation/MobileNavigationManager.cs index 7bfaa5b0..6ee98590 100644 --- a/MPfm/MPfm.MVP/Navigation/MobileNavigationManager.cs +++ b/MPfm/MPfm.MVP/Navigation/MobileNavigationManager.cs @@ -730,7 +730,7 @@ public virtual void CreateAboutView() CreateAboutViewInternal(onViewReady); } - protected virtual void CreatePlaylistViewInternal(Action onViewReady) + protected virtual void CreatePlaylistViewInternal(IBaseView sourceView, Action onViewReady) { if (_playlistView == null) _playlistView = Bootstrapper.GetContainer().Resolve(new NamedParameterOverloads() { { "onViewReady", onViewReady } }); @@ -741,7 +741,7 @@ protected virtual void CreatePlaylistViewInternal(Action onViewReady) #endif } - public virtual void CreatePlaylistView() + public virtual void CreatePlaylistView(IBaseView sourceView) { Action onViewReady = (view) => { @@ -755,7 +755,7 @@ public virtual void CreatePlaylistView() _playlistPresenter.BindView((IPlaylistView)view); }; - CreatePlaylistViewInternal(onViewReady); + CreatePlaylistViewInternal(sourceView, onViewReady); } } diff --git a/MPfm/MPfm.MVP/Presenters/PlayerMetadataPresenter.cs b/MPfm/MPfm.MVP/Presenters/PlayerMetadataPresenter.cs index 36471bda..747149eb 100644 --- a/MPfm/MPfm.MVP/Presenters/PlayerMetadataPresenter.cs +++ b/MPfm/MPfm.MVP/Presenters/PlayerMetadataPresenter.cs @@ -66,7 +66,7 @@ private void OnPlaylistIndexChanged(PlayerPlaylistIndexChangedMessage message) private void OpenPlaylist() { - _navigationManager.CreatePlaylistView(); + _navigationManager.CreatePlaylistView(View); } private void ToggleRepeat() diff --git a/MPfm/MPfm.MVP/Presenters/PlayerPresenter.cs b/MPfm/MPfm.MVP/Presenters/PlayerPresenter.cs index b8dea0c0..4930c460 100644 --- a/MPfm/MPfm.MVP/Presenters/PlayerPresenter.cs +++ b/MPfm/MPfm.MVP/Presenters/PlayerPresenter.cs @@ -163,7 +163,7 @@ private void OpenPlaylist() { // Only on mobile devices Console.WriteLine("PlayerPresenter - OpenPlaylist"); - _mobileNavigationManager.CreatePlaylistView(); + _mobileNavigationManager.CreatePlaylistView(View); } ///