-
-
Save xmesaj2/411f2a4ab224727a5f8ad6b7fc025685 to your computer and use it in GitHub Desktop.
Custom fragment handling in MvvmCross and Xamarin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CustomFragmentsPresenter : MvxFragmentsPresenter | |
{ | |
public interface IMvxFragmentHostEx : IMvxFragmentHost | |
{ | |
void Close(IMvxViewModel viewModel); | |
void ChangePresentation (MvxPresentationHint hint); | |
} | |
private IMvxNavigationSerializer _serializer; | |
private IMvxNavigationSerializer Serializer | |
{ | |
get | |
{ | |
if (_serializer != null) | |
return _serializer; | |
_serializer = Mvx.Resolve<IMvxNavigationSerializer>(); | |
return _serializer; | |
} | |
} | |
public override void Show (MvxViewModelRequest request) | |
{ | |
var fragmentHost = Activity as IMvxFragmentHost; | |
if (fragmentHost != null) { | |
var bundle = new Bundle (); | |
var serializedRequest = Serializer.Serializer.SerializeObject (request); | |
bundle.PutString (ViewModelRequestBundleKey, serializedRequest); | |
fragmentHost.Show (request, bundle); | |
} | |
else | |
{ | |
var bundle = new Bundle(); | |
var serializedRequest = Serializer.Serializer.SerializeObject(request); | |
bundle.PutString(ViewModelRequestBundleKey, serializedRequest); | |
var intentFor = new Intent (Activity.ApplicationContext, typeof(MainActivity)); | |
intentFor.PutExtra ("request", bundle); | |
base.Show(intentFor); | |
} | |
} | |
public override void ChangePresentation (MvxPresentationHint hint) | |
{ | |
if (hint != null) { | |
var fragmentHost = Activity as IMvxFragmentHost as IMvxFragmentHostEx; | |
if (fragmentHost != null) { | |
fragmentHost.ChangePresentation (hint); | |
} | |
} | |
base.ChangePresentation (hint); | |
} | |
public override void Close (IMvxViewModel viewModel) | |
{ | |
var fragmentHost = Activity as IMvxFragmentHost as IMvxFragmentHostEx; | |
if (fragmentHost != null) { | |
fragmentHost.Close (viewModel); | |
} | |
base.Close (viewModel); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Activity( | |
Label = "Menu", | |
Theme = "@style/AppTheme", | |
LaunchMode = LaunchMode.SingleTop, | |
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | |
)] | |
public class MainActivity : MvxActionBarFragmentActivity, IMvxFragmentHost, CustomFragmentsPresenter.IMvxFragmentHostEx, FragmentManager.IOnBackStackChangedListener | |
{ | |
public DrawerLayout drawerLayout; | |
private MvxActionBarDrawerToggle drawerToggle; | |
private FragmentManager fragmentManager; | |
private IMvxNavigationSerializer _serializer; | |
protected IMvxNavigationSerializer Serializer | |
{ | |
get | |
{ | |
if (_serializer != null) | |
return _serializer; | |
_serializer = Mvx.Resolve<IMvxNavigationSerializer>(); | |
return _serializer; | |
} | |
} | |
protected override void OnCreate(Bundle bundle) | |
{ | |
base.OnCreate(bundle); | |
fragmentManager = FragmentManager; | |
fragmentManager.AddOnBackStackChangedListener (this); | |
SetContentView(Resource.Layout.activity_main); | |
Toolbar toolbar = FindViewById<Toolbar>(Resource.Id.toolbar); | |
if (toolbar != null) | |
{ | |
SetSupportActionBar(toolbar); | |
SupportActionBar.SetDisplayHomeAsUpEnabled(true); | |
} | |
drawerLayout = (DrawerLayout)FindViewById(Resource.Id.drawer); | |
drawerToggle = new MvxActionBarDrawerToggle( | |
this, /* host Activity */ | |
drawerLayout, /* DrawerLayout object */ | |
toolbar, /* nav drawer icon to replace 'Up' caret */ | |
Resource.String.drawer_open, /* "open drawer" description */ | |
Resource.String.drawer_close /* "close drawer" description */ | |
); | |
drawerToggle.DrawerOpened += (o, args) => | |
{ | |
HideSoftKeyboard(); | |
}; | |
drawerLayout.SetDrawerListener(drawerToggle); | |
Bundle request = Intent.GetBundleExtra ("request"); | |
var requestMain = new MvxViewModelRequest(typeof(MenuViewModel), null, null, null); | |
Show(requestMain, request); | |
if (request != null) { | |
var deserializedRequest = Serializer.Serializer.DeserializeObject<MvxViewModelRequest>(request.GetString(CustomFragmentsPresenter.ViewModelRequestBundleKey)); | |
Show (deserializedRequest, request); | |
} | |
} | |
public override void OnBackPressed () | |
{ | |
//TODO: This is a fix to get the back button working. Don't know if it is a good one. | |
var currentFragment = fragmentManager.FindFragmentById(Resource.Id.content_frame) as MvxFragment; | |
if (currentFragment != null && fragmentManager.BackStackEntryCount > 1) { | |
fragmentManager.PopBackStackImmediate (); | |
return; | |
} else if (drawerLayout.IsDrawerOpen (GravityCompat.Start)) | |
drawerLayout.CloseDrawers (); | |
else | |
base.OnBackPressed (); | |
} | |
public override void OnConfigurationChanged(Configuration newConfig) | |
{ | |
base.OnConfigurationChanged(newConfig); | |
drawerToggle.OnConfigurationChanged(newConfig); | |
} | |
protected override void OnPostCreate(Bundle savedInstanceState) | |
{ | |
base.OnPostCreate(savedInstanceState); | |
drawerToggle.SyncState(); | |
} | |
public void HideSoftKeyboard() | |
{ | |
InputMethodManager manager = (InputMethodManager)GetSystemService(Context.InputMethodService); | |
manager.HideSoftInputFromWindow(CurrentFocus.WindowToken, 0); | |
} | |
public void ShowSoftKeyboard() | |
{ | |
InputMethodManager manager = (InputMethodManager)GetSystemService(Context.InputMethodService); | |
manager.ShowSoftInputFromInputMethod(CurrentFocus.WindowToken, 0); | |
} | |
public bool Show (MvxViewModelRequest request, Bundle bundle) | |
{ | |
if (request.ViewModelType == typeof(MenuViewModel)) { | |
ShowFragment (request, Resource.Id.left_drawer, bundle); | |
return true; | |
} | |
else if (request.ViewModelType == typeof(MiniPlayerViewModel)) | |
{ | |
ShowFragment(request, Resource.Id.player_frame, bundle); | |
return true; | |
} | |
else if (request.ViewModelType == typeof(LoginViewModel)) | |
{ | |
ChangePresentation(new ClearNavBackStackHint()); | |
ShowFragment(request, Resource.Id.content_frame, bundle); | |
return true; | |
} | |
else { | |
ShowFragment(request, Resource.Id.content_frame, bundle, true); | |
return true; | |
} | |
} | |
public void ShowFragment(MvxViewModelRequest request, int contentId, Bundle bundle = null, bool addToBackStack = false) | |
{ | |
MvxFragment fragment = null; | |
IMvxViewsContainer viewContainer = Mvx.Resolve<IMvxViewsContainer>(); | |
Type viewType = viewContainer.GetViewType(request.ViewModelType); | |
Fragment currentContentFragment = FragmentManager.FindFragmentById(contentId); | |
if (currentContentFragment != null && currentContentFragment.GetType () == viewType && (request.ParameterValues == null || (request.ParameterValues != null && request.ParameterValues.Count == 0))) { | |
drawerLayout.CloseDrawers(); | |
return; | |
} | |
SupportActionBar.Show(); | |
drawerLayout.SetDrawerLockMode(DrawerLayout.LockModeUnlocked); | |
fragment = (MvxFragment)Activator.CreateInstance(viewType); | |
var loaderService = Mvx.Resolve<IMvxViewModelLoader>(); | |
var viewModel = loaderService.LoadViewModel(request, null); | |
fragment.ViewModel = viewModel; | |
var contentManager = fragmentManager.BeginTransaction(); | |
contentManager.Replace(contentId, fragment); | |
if(addToBackStack) | |
contentManager.AddToBackStack(fragment.GetType().Name); | |
contentManager.Commit(); | |
drawerLayout.CloseDrawers(); | |
} | |
public void OnBackStackChanged () | |
{ | |
Fragment currentPlayerFragment = fragmentManager.FindFragmentById(Resource.Id.player_frame); | |
Fragment currentContentFragment = FragmentManager.FindFragmentById (Resource.Id.content_frame); | |
if (currentPlayerFragment != null && currentContentFragment != null) { | |
var contentManager = fragmentManager.BeginTransaction(); | |
if (currentContentFragment.GetType () == typeof(PlayerFragment) || currentContentFragment.GetType () == typeof(QueueFragment) || currentContentFragment.GetType () == typeof(LoginFragment)) | |
contentManager.Hide (currentPlayerFragment); | |
else | |
contentManager.Show (currentPlayerFragment); | |
contentManager.Commit (); | |
} | |
} | |
public void ChangePresentation (MvxPresentationHint hint) | |
{ | |
//TODO: Ignore this on Android for now | |
//if (hint is ClearNavBackStackHint) | |
//fragmentManager.PopBackStackImmediate(null, PopBackStackFlags.Inclusive); | |
} | |
public void Close (IMvxViewModel viewModel) | |
{ | |
var currentFragment = fragmentManager.FindFragmentById (Resource.Id.content_frame) as MvxFragment; | |
if (currentFragment != null && currentFragment.ViewModel == viewModel) { | |
fragmentManager.PopBackStackImmediate (); | |
return; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ActionBarDrawerEventArgs : EventArgs | |
{ | |
public View DrawerView { get; set; } | |
public float SlideOffset { get; set; } | |
public int NewState { get; set; } | |
} | |
public delegate void ActionBarDrawerChangedEventHandler(object s, ActionBarDrawerEventArgs e); | |
public class MvxActionBarDrawerToggle : Android.Support.V7.App.ActionBarDrawerToggle | |
{ | |
public MvxActionBarDrawerToggle(Activity activity, | |
DrawerLayout drawerLayout, | |
int openDrawerContentDescRes, | |
int closeDrawerContentDescRes) | |
: base(activity, | |
drawerLayout, | |
openDrawerContentDescRes, | |
closeDrawerContentDescRes) | |
{ | |
} | |
public MvxActionBarDrawerToggle(Activity activity, | |
DrawerLayout drawerLayout, | |
Toolbar toolbar, | |
int openDrawerContentDescRes, | |
int closeDrawerContentDescRes) | |
: base(activity, | |
drawerLayout, | |
toolbar, | |
openDrawerContentDescRes, | |
closeDrawerContentDescRes) | |
{ | |
} | |
public event ActionBarDrawerChangedEventHandler DrawerClosed; | |
public event ActionBarDrawerChangedEventHandler DrawerOpened; | |
public event ActionBarDrawerChangedEventHandler DrawerSlide; | |
public event ActionBarDrawerChangedEventHandler DrawerStateChanged; | |
public override void OnDrawerClosed(View drawerView) | |
{ | |
if (null != this.DrawerClosed) | |
this.DrawerClosed(this, new ActionBarDrawerEventArgs { DrawerView = drawerView }); | |
base.OnDrawerClosed(drawerView); | |
} | |
public override void OnDrawerOpened(View drawerView) | |
{ | |
if (null != this.DrawerOpened) | |
this.DrawerOpened(this, new ActionBarDrawerEventArgs { DrawerView = drawerView }); | |
base.OnDrawerOpened(drawerView); | |
} | |
public override void OnDrawerSlide(View drawerView, float slideOffset) | |
{ | |
if (null != this.DrawerSlide) | |
this.DrawerSlide(this, new ActionBarDrawerEventArgs | |
{ | |
DrawerView = drawerView, | |
SlideOffset = slideOffset | |
}); | |
base.OnDrawerSlide(drawerView, slideOffset); | |
} | |
public override void OnDrawerStateChanged(int newState) | |
{ | |
if (null != this.DrawerStateChanged) | |
this.DrawerStateChanged(this, new ActionBarDrawerEventArgs | |
{ | |
NewState = newState | |
}); | |
base.OnDrawerStateChanged(newState); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment