Skip to content

Commit

Permalink
Android: Refactored how the ViewPager for the MainActivity returns th…
Browse files Browse the repository at this point in the history
…e fragments. The previous recipe wasn't working well with backstacking. The navigation manager now keeps a history of the main parameters the mobile library browser in order to be able to recreate the fragment when necessary. Will require minor changes on iOS.

Related to issue #406.
  • Loading branch information
ycastonguay committed Jul 19, 2013
1 parent 7f82bf5 commit 2d7d71b
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 143 deletions.
23 changes: 7 additions & 16 deletions MPfm/MPfm.Android/Classes/Activities/MainActivity.cs
Expand Up @@ -61,16 +61,13 @@ protected override void OnCreate(Bundle bundle)
Console.WriteLine("MainActivity - OnCreate");
base.OnCreate(bundle);

//string externalDir = global::Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
//string internalDir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);

RequestWindowFeature(WindowFeatures.ActionBar);
SetContentView(Resource.Layout.Main);

// Setup view pager
_viewPager = FindViewById<ViewPager>(Resource.Id.main_pager);
_viewPager.OffscreenPageLimit = 4;
_tabPagerAdapter = new MainTabStatePagerAdapter(FragmentManager, _viewPager, ActionBar);
_tabPagerAdapter = new MainTabStatePagerAdapter(FragmentManager, _viewPager);
_viewPager.Adapter = _tabPagerAdapter;
_viewPager.SetOnPageChangeListener(_tabPagerAdapter);

Expand Down Expand Up @@ -138,19 +135,13 @@ protected override void OnSaveInstanceState(Bundle outState)
{
base.OnSaveInstanceState(outState);

//Console.WriteLine("MainActivity - OnSaveInstanceState - Saving state...");
Console.WriteLine("MainActivity - OnSaveInstanceState - Saving state...");
outState.PutBoolean("applicationStarted", true);
}

//public override void OnConfigurationChanged(global::Android.Content.Res.Configuration newConfig)
//{
// Console.WriteLine("MainActivity - OnConfigurationChanged - newConfig: {0}", newConfig.Orientation.ToString());
// base.OnConfigurationChanged(newConfig);
//}

public void AddTab(MobileNavigationTabType type, string title, Fragment fragment)
{
//Console.WriteLine("MainActivity - OnCreate - Adding tab {0}", title);
//Console.WriteLine("MainActivity - Adding tab {0}", title);
_tabPagerAdapter.SetFragment(type, fragment);
_tabPagerAdapter.NotifyDataSetChanged();
}
Expand Down Expand Up @@ -227,14 +218,14 @@ protected override void OnDestroy()
public override void OnBackPressed()
{
// Check if the history has another tab
if (_tabPagerAdapter.CanRemoveFragmentFromStack(_tabPagerAdapter.GetCurrentTab(), _viewPager.CurrentItem))
if (_navigationManager.CanRemoveMobileLibraryBrowserFragmentFromBackstack(_tabPagerAdapter.GetCurrentTab()))
{
//Console.WriteLine("MainActivity - OnBackPressed - CanRemoveFragment");
_tabPagerAdapter.RemoveFragmentFromStack(_tabPagerAdapter.GetCurrentTab(), _viewPager.CurrentItem);
Console.WriteLine("MainActivity - OnBackPressed - CanRemoveFragment");
_navigationManager.RecreateMobileLibraryBrowserFragment(_tabPagerAdapter.GetCurrentTab());
}
else
{
//Console.WriteLine("MainActivity - OnBackPressed - CannotRemoveFragment");
Console.WriteLine("MainActivity - OnBackPressed - CannotRemoveFragment");
base.OnBackPressed();
}
}
Expand Down
45 changes: 10 additions & 35 deletions MPfm/MPfm.Android/Classes/Adapters/MainTabStatePagerAdapter.cs
Expand Up @@ -28,36 +28,30 @@ namespace MPfm.Android.Classes.Adapters
{
public class MainTabStatePagerAdapter : FragmentStatePagerAdapter, ActionBar.ITabListener, ViewPager.IOnPageChangeListener
{
private readonly List<Tuple<MobileNavigationTabType, List<Fragment>>> _fragments;
private readonly ViewPager _viewPager;
private readonly ActionBar _actionBar;
readonly List<Tuple<MobileNavigationTabType, Fragment>> _fragments;
readonly ViewPager _viewPager;

public MainTabStatePagerAdapter(IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
}

public MainTabStatePagerAdapter(FragmentManager fm, ViewPager viewPager, ActionBar actionBar)
public MainTabStatePagerAdapter(FragmentManager fm, ViewPager viewPager)
: base(fm)
{
_fragments = new List<Tuple<MobileNavigationTabType, List<Fragment>>>();
_fragments = new List<Tuple<MobileNavigationTabType, Fragment>>();
_viewPager = viewPager;
_actionBar = actionBar;
}

public void SetFragment(MobileNavigationTabType tabType, Fragment fragment)
{
//Console.WriteLine("MainTabPagerAdapter - SetFragment - tabType: {0}", tabType.ToString());
int index = _fragments.FindIndex(x => x.Item1 == tabType);
if (index == -1)
{
// This tab isn't yet in the list; add to list
_fragments.Add(new Tuple<MobileNavigationTabType, List<Fragment>>(tabType, new List<Fragment>(){ fragment }));
return;
_fragments.Add(new Tuple<MobileNavigationTabType, Fragment>(tabType, fragment));
}

var fragments = _fragments.FirstOrDefault(x => x.Item1 == tabType);
fragments.Item2.Add(fragment);
index = _fragments.FindIndex(x => x.Item1 == tabType);
_fragments[index] = new Tuple<MobileNavigationTabType, Fragment>(tabType, fragment);
NotifyDataSetChanged();
}

Expand All @@ -66,24 +60,6 @@ public MobileNavigationTabType GetCurrentTab()
return _fragments[_viewPager.CurrentItem].Item1;
}

public bool CanRemoveFragmentFromStack(MobileNavigationTabType tabType, int index)
{
var fragmentList = _fragments.FirstOrDefault(x => x.Item1 == tabType);
if (fragmentList != null)
return fragmentList.Item2.Count > 1;

return false;
}

public void RemoveFragmentFromStack(MobileNavigationTabType tabType, int index)
{
var fragmentList = _fragments.FirstOrDefault(x => x.Item1 == tabType);
if (fragmentList != null)
fragmentList.Item2.RemoveAt(fragmentList.Item2.Count - 1);

NotifyDataSetChanged();
}

public void OnTabReselected(ActionBar.Tab tab, FragmentTransaction ft)
{
}
Expand All @@ -100,16 +76,15 @@ public void OnTabUnselected(ActionBar.Tab tab, FragmentTransaction ft)

public override Fragment GetItem(int index)
{
return _fragments[index].Item2.Last();
return _fragments[index].Item2;
}

public override int GetItemPosition(Java.Lang.Object obj)
{
// If the fragment is different, tell Android to refresh this item
bool foundItem = false;
foreach (var fragmentList in _fragments)
{
bool foundItemInList = fragmentList.Item2.Last() == (Fragment) obj;
bool foundItemInList = fragmentList.Item2 == (Fragment)obj;
if (foundItemInList)
{
foundItem = true;
Expand Down Expand Up @@ -137,7 +112,7 @@ public void OnPageScrolled(int p0, float p1, int p2)

public void OnPageSelected(int position)
{
Console.WriteLine("MainTabPagerAdapter - OnPageSelected position: {0}", position);
//Console.WriteLine("MainTabPagerAdapter - OnPageSelected position: {0}", position);
//_actionBar.SetSelectedNavigationItem(position);
}

Expand Down
Expand Up @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Android.App;
using Android.OS;
using Android.Views;
using Android.Widget;
Expand All @@ -38,20 +39,24 @@ public class MobileLibraryBrowserFragment : BaseFragment, IMobileLibraryBrowserV
private MobileLibraryBrowserGridAdapter _gridAdapter;
private List<LibraryBrowserEntity> _entities = new List<LibraryBrowserEntity>();

bool _isTest = false;

// Leave an empty constructor or the application will crash at runtime
public MobileLibraryBrowserFragment() : base(null)
{
Console.WriteLine("MobileLibraryBrowserFragment - Empty ctor");
}

public MobileLibraryBrowserFragment(Action<IBaseView> onViewReady)
: base(onViewReady)
{
Console.WriteLine("MobileLibraryBrowserFragment - OnViewReady ctor");
}

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
Console.WriteLine("MLBFragment - OnCreateView");

Console.WriteLine("MLBFragment - OnCreateView - isTest: {0}", _isTest);
_isTest = true;
_view = inflater.Inflate(Resource.Layout.MobileLibraryBrowser, container, false);
_listView = _view.FindViewById<ListView>(Resource.Id.mobileLibraryBrowser_listView);
_listView.Visibility = ViewStates.Gone;
Expand Down Expand Up @@ -89,6 +94,12 @@ private void GridViewOnItemLongClick(object sender, AdapterView.ItemLongClickEve
{
}

public override void OnSaveInstanceState(Bundle outState)
{
Console.WriteLine("MLBFragment - OnSaveInstanceState");
base.OnSaveInstanceState(outState);
}

public override void OnResume()
{
Console.WriteLine("MLBFragment - OnResume");
Expand Down Expand Up @@ -125,6 +136,12 @@ public override void OnDestroyView()
base.OnDestroyView();
}

public override void OnDetach()
{
Console.WriteLine("MLBFragment - OnDetach");
base.OnDetach();
}

#region IMobileLibraryBrowserView implementation

public MobileLibraryBrowserType BrowserType { get; set; }
Expand All @@ -135,11 +152,18 @@ public override void OnDestroyView()

public void MobileLibraryBrowserError(Exception ex)
{
Activity.RunOnUiThread(() => {
AlertDialog ad = new AlertDialog.Builder(Activity).Create();
ad.SetCancelable(false);
ad.SetMessage(string.Format("An error has occured in MobileLibraryBrowser: {0}", ex));
ad.SetButton("OK", (sender, args) => ad.Dismiss());
ad.Show();
});
}

public void RefreshLibraryBrowser(IEnumerable<LibraryBrowserEntity> entities, MobileLibraryBrowserType browserType, string navigationBarTitle, string navigationBarSubtitle)
{
//Console.WriteLine("MLBF - RefreshLibraryBrowser - Count: {0}", entities.Count());
Console.WriteLine("MLBF - RefreshLibraryBrowser - Count: {0}", entities.Count());
Activity.RunOnUiThread(() => {
_entities = entities.ToList();
Expand Down
37 changes: 31 additions & 6 deletions MPfm/MPfm.Android/Classes/Navigation/AndroidNavigationManager.cs
Expand Up @@ -16,15 +16,15 @@
// along with MPfm. If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Linq;
using Android.App;
using Android.Content;
using Android.OS;
using MPfm.Android.Classes.Fragments;
using MPfm.MVP.Bootstrap;
using MPfm.Library.Objects;
using MPfm.MVP.Messages;
using MPfm.MVP.Navigation;
using MPfm.MVP.Views;
using TinyIoC;
using TinyMessenger;

namespace MPfm.Android.Classes.Navigation
Expand All @@ -42,11 +42,13 @@ public sealed class AndroidNavigationManager : MobileNavigationManager
private Action<IBaseView> _onSyncWebBrowserViewReady;
private Action<IBaseView> _onMarkerDetailsViewReady;
private Action<IBaseView> _onEqualizerPresetDetailsViewReady;
private List<Tuple<MobileNavigationTabType, List<Tuple<MobileLibraryBrowserType, LibraryQuery>>>> _tabHistory;

public MainActivity MainActivity { get; set; }

public AndroidNavigationManager(ITinyMessengerHub messageHub)
{
_tabHistory = new List<Tuple<MobileNavigationTabType, List<Tuple<MobileLibraryBrowserType, LibraryQuery>>>>();
_messageHub = messageHub;
_messageHub.Subscribe<MobileNavigationManagerCommandMessage>((m) => {
switch (m.CommandType)
Expand All @@ -62,6 +64,24 @@ public AndroidNavigationManager(ITinyMessengerHub messageHub)
});
}

public bool CanRemoveMobileLibraryBrowserFragmentFromBackstack(MobileNavigationTabType tabType)
{
var tab = _tabHistory.FirstOrDefault(x => x.Item1 == tabType);
if (tab != null)
return tab.Item2.Count > 1;
return false;
}

public void RecreateMobileLibraryBrowserFragment(MobileNavigationTabType tabType)
{
var tab = _tabHistory.FirstOrDefault(x => x.Item1 == tabType);
var tabItem = tab.Item2.Last();
tab.Item2.Remove(tabItem);
tabItem = tab.Item2.Last();
var view = CreateMobileLibraryBrowserView(tabType, tabItem.Item1, tabItem.Item2);
MainActivity.PushTabView(tabType, (Fragment) view);
}

public override void ShowSplash(ISplashView view)
{
MainActivity.ShowSplash((SplashFragment) view);
Expand All @@ -72,14 +92,19 @@ public override void HideSplash()
MainActivity.HideSplash();
}

public override void AddTab(MobileNavigationTabType type, string title, IBaseView view)
public override void AddTab(MobileNavigationTabType type, string title, MobileLibraryBrowserType browserType, LibraryQuery query, IBaseView view)
{
_tabHistory.Add(new Tuple<MobileNavigationTabType, List<Tuple<MobileLibraryBrowserType, LibraryQuery>>>(type, new List<Tuple<MobileLibraryBrowserType, LibraryQuery>>() {
new Tuple<MobileLibraryBrowserType, LibraryQuery>(browserType, query)
}));
MainActivity.AddTab(type, title, (Fragment) view);
}

public override void PushTabView(MobileNavigationTabType type, IBaseView view)
public override void PushTabView(MobileNavigationTabType type, MobileLibraryBrowserType browserType, LibraryQuery query, IBaseView view)
{
MainActivity.PushTabView(type, (Fragment) view);
var tab = _tabHistory.FirstOrDefault(x => x.Item1 == type);
tab.Item2.Add(new Tuple<MobileLibraryBrowserType, LibraryQuery>(browserType, query));
MainActivity.PushTabView(type, (Fragment)view);
}

public override void PushDialogView(string viewTitle, IBaseView sourceView, IBaseView view)
Expand Down
14 changes: 7 additions & 7 deletions MPfm/MPfm.MVP/Navigation/MobileNavigationManager.cs
Expand Up @@ -95,8 +95,8 @@ public abstract class MobileNavigationManager

public abstract void ShowSplash(ISplashView view);
public abstract void HideSplash();
public abstract void AddTab(MobileNavigationTabType type, string title, IBaseView view);
public abstract void PushTabView(MobileNavigationTabType type, IBaseView view);
public abstract void AddTab(MobileNavigationTabType type, string title, MobileLibraryBrowserType browserType, LibraryQuery query, IBaseView view);
public abstract void PushTabView(MobileNavigationTabType type, MobileLibraryBrowserType browserType, LibraryQuery query, IBaseView view);
public abstract void PushDialogView(string viewTitle, IBaseView sourceView, IBaseView view);
public abstract void PushDialogSubview(string parentViewTitle, IBaseView view);
public abstract void PushPlayerSubview(IPlayerView playerView, IBaseView view);
Expand All @@ -110,10 +110,10 @@ public virtual void Start()
var artistsView = CreateMobileLibraryBrowserView(MobileNavigationTabType.Artists, MobileLibraryBrowserType.Artists, new LibraryQuery());
var albumsView = CreateMobileLibraryBrowserView(MobileNavigationTabType.Albums, MobileLibraryBrowserType.Albums, new LibraryQuery());
var songsView = CreateMobileLibraryBrowserView(MobileNavigationTabType.Songs, MobileLibraryBrowserType.Songs, new LibraryQuery());
AddTab(MobileNavigationTabType.Playlists, "Sessions", playlistsView);
AddTab(MobileNavigationTabType.Artists, "Artists", artistsView);
AddTab(MobileNavigationTabType.Albums, "Albums", albumsView);
AddTab(MobileNavigationTabType.Songs, "Songs", songsView);
AddTab(MobileNavigationTabType.Playlists, "Sessions", MobileLibraryBrowserType.Playlists, new LibraryQuery(), playlistsView);
AddTab(MobileNavigationTabType.Artists, "Artists", MobileLibraryBrowserType.Artists, new LibraryQuery(), artistsView);
AddTab(MobileNavigationTabType.Albums, "Albums", MobileLibraryBrowserType.Albums, new LibraryQuery(), albumsView);
AddTab(MobileNavigationTabType.Songs, "Songs", MobileLibraryBrowserType.Songs, new LibraryQuery(), songsView);
// iOS has one more tab, the More tab (Options Menu equivalent on Android).
#if IOS
Expand Down Expand Up @@ -379,7 +379,7 @@ public virtual void CreatePlayerView(MobileNavigationTabType tabType, Action<IBa
else
{
onViewBindedToPresenter(_playerView);
PushTabView(tabType, _playerView);
PushTabView(tabType, MobileLibraryBrowserType.Artists, new LibraryQuery(), _playerView);
}
}

Expand Down
2 changes: 1 addition & 1 deletion MPfm/MPfm.MVP/Presenters/MobileLibraryBrowserPresenter.cs
Expand Up @@ -186,7 +186,7 @@ private void ItemClick(int index)
{
var browserType = (_browserType == MobileLibraryBrowserType.Artists) ? MobileLibraryBrowserType.Albums : MobileLibraryBrowserType.Songs;
var newView = _navigationManager.CreateMobileLibraryBrowserView(_tabType, browserType, _items[index].Query);
_navigationManager.PushTabView(_tabType, newView);
_navigationManager.PushTabView(_tabType, browserType, _items[index].Query, newView);
return;
}

Expand Down

0 comments on commit 2d7d71b

Please sign in to comment.