This post is a continuation of building gesture based “easter eggs” into your Xamarin apps (native or Forms).
In this post, we are going to continue from these posts:
– Xamarin.Tip – Add Easter Eggs to UWP with Key Combos
– Xamarin.Tip – Add Easter Eggs on Shake
to talk about how we can use these gestures in Debug mode to give ourselves some shortcuts for testing and moving through our application quicker.
To breakdown the process setup – we added shake handlers (and keyboard shortcuts for UWP) that can invoke any contextual code in our application. We talked about using this for funny easter eggs, but this functionality can be made into something super useful for us.
I call this “Contextual Developer Options”. The idea is take that easter egg handler and use it to display some contextual options that can be controlled page by page or view by view. This can be toggling some UI updates, auto-navigating through the app, testing different scenarios, etc.
In this example we’ll be using MVVM and Xamarin.Forms to demonstrate the possibilities, but the same idea can be applied to any other pattern or practice. Basically we need to:
- Register dev options to whatever context we want
- Determine what context we are in
- Display the actionable dev options
Before starting, I suggest looking at something like Allan Ritchie’s incredibly useful UserDialogs package https://github.com/aritchie/userdialogs
We’ll use it in our examples.
Setting Up Developer Options
First things first, let’s define our developer options.
DevelopmentOption.cs
public class DevelopmentOption
{
public string Title { get; set; }
public Action Action { get; set; }
}
Now, like I said, our example will be doing this in MVVM and we can use the current page the user is on as the context we want to apply.
I’ll start by creating a BasePageViewModel
that we can use to set up our developer options and execute the action
BasePageViewModel.cs
public abstract class BasePageViewModel : ViewModelBase
{
protected List<DevelopmentOption> _developerOptions;
private bool _isShowingDeveloperOptions = false;
public BasePageViewModel()
{
_developerOptions = new List<DevelopmentOptions>();
}
/// <summary>
/// Shows the developer options. This should be called after a native easter egg such as a shake.
/// </summary>
public virtual async Task ShowDeveloperOptionsAsync()
{
if (_developerOptions.Any() && !_isShowingDeveloperOptions)
{
var titles = _developerOptions.Select(d => d.Title);
_isShowingDeveloperOptions = true;
var actionResult = await UserDialogs.Instance.ActionSheetAsync("Developer Options", "Cancel", null, null, titles.ToArray());
_isShowingDeveloperOptions = false;
// see if an option was selected
if (titles.Contains(actionResult))
{
// call it if we find it.
var option = _developerOptions.FirstOrDefault(d => d.Title == actionResult);
option?.Action();
}
}
}
/// <summary>
/// Sets up the developer options.
/// </summary>
protected virtual void SetupDeveloperOptions()
{
_developerOptions.Add(new DevelopmentOption()
{
Title = "Go to debug page",
Action = () => UserDialogs.Instance.Toast("Not implemented")
});
}
/// <summary>
/// Adds the developer option.
/// </summary>
/// <param name="title">Title.</param>
/// <param name="action">Action to perform when selected.</param>
protected void AddDeveloperOption(string title, Action action)
{
_developerOptions.Add(new DevelopmentOption()
{
Title = title,
Action = action
});
}
}
Alright let’s breakdown what’s going on here.
Our BasePageViewModel
has a List
that represents our different options for the given page. Then we have some protected methods we can use in our extended PageViewModels
to setup different options.
In our SetupDeveloperOptions
method, we can setup any option we want for the page, and we put a universal “Go to debug page” example action that is there on every page.
So here’s an example of a useful ViewModel
that sets up a login page developer option.
LoginPageViewModel.cs
public class LoginPageViewModel : BasePageViewModel
{
public string Email { get; set; }
public string Password { get; set; }
protected override void SetupDeveloperOptions()
{
AddDeveloperOption("Use test user", () =>
{
Email = "mytestuser@mydomain.com";
Password = "myP@ssw0rd";
});
}
}
So what we want on this login page is to be able to shake the device and see the Action Sheet that shows “Use test user” and when selected, it should fill out the fields on the page automatically.
Now that our setup is done, let’s wire up accessing these developer options.
Wiring It Up
We need to be able to access our Page’s ViewModel in order to execute the developer options when the shake happens. To do this, we can access the current page via the Xamarin.Forms.Application.Current
static accessor. Then use the MainPage
property to get around.
I like to add a simple helper property getter
on my App
class for this:
App.xaml.cs
public class App : Application
{
// ...
// assuming MainPage is a NavigationPage. You can do some extra logic if it isn't
public ContentPage CurrentPage => (MainPage as NavigationPage)?.Navigation?.NavigationStack?.Last()
// ...
}
Now in our native app logic, where we were executing the easter egg we can call:
// we don't want developer options in production 🙂
#if DEBUG
await ((App.Current as App)?.CurrentPage?.BindingContext as BasePageViewModel)?.ShowDeveloperOptionsAsync();
#endif
So now if we are in our LoginPage
and our BindingContext
is set to our LoginPageViewModel
, our shake should reveal the action sheet!
Conclusion
We can make our lives a whole lot easier when testing and running through our app by giving ourselves easier and contextual options throughout the entire application.
I’ve personally used this for some pretty awesome and intense stuff like:
- Filling out forms with different values
- Changing styles/themes of the app to easily compare 2 different UIs
- Test different states of a page such as if a user is logged in or not
- Test error scenarios
- Build a page that shows logs of all interactions and background tasks in the app and use the developer options to navigate to that page whenever to see those custom logs live (even when not attached to the debugger)
- Execute custom native code to make debugging easier
- Navigate quickly to the page deep in the app I am currently working on
Remember to still write unit and UI tests for your app too! This is meant to be something to make real hands-on testing even easier too.
It has saved me hundreds of hours easily. Let me know if you end up implementing something like this too!
For now, I don’t have any complete open source project to demo this, but if enough of you want to see a full example and screenshots and different scenarios, I’ll consider putting a full project together. Let me know in the comments or on twitter!
If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!
Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.
Like this:
Like Loading...