Tuesday, May 10, 2016

A very small pub/sub solution for Xamarin Forms

I've created a small project called TinyPubSub that only does one thing at the moment. It's made especially for use with MVVM and Xamarin Forms.

DISCLAIMER: This is a very early version of the library.

Short version: 



Long version:


I'm a big fan of vanilla MVVM. That means that I don't like to add other frameworks on top of what's already possible to achieve using only Xamarin Forms. 

A very common scenario is that I have a main page that are supposed to display some kind of data, let's say a list of ducks. I then navigate down a couple of pages in the app and find a page where I can add a duck. This should then update the first page. I could do this update in the OnAppearing event of the page but that breaks two nice rules of mine:
  1. The page should not start to load data when it is resurfaced. It should have already done that.
  2. The view is starting to handle logic. We don't want that.
So I created a small (tiny one might call it) library that solves this in the most simple way I can think of. It also handles dereferencing in a nice way. As long as you don't use Navigation.PopToRoot(); for the time being.

The features being:
  1. Simple usage
  2. Automatic un-subscription


The code

This is the structure of the project in the sample supplied with the source code (available at github).

Initialization

To initialize TinyPubSubs automatic dereference magic, just add this code to each NavigationPage you create. I'm looking at creating a forms library that adds an Init-method instead. But for now, do this.

        public App ()
        {
            // The root page of your application
            var navPage = new NavigationPage(new MainView());

            navPage.Popped += (object sender, NavigationEventArgs e) => TinyPubSub.Unsubscribe(e.Page.BindingContext);
            
            MainPage = navPage;
        }

Usage in the ViewModels

In the constructor of the ViewModels, add subscriptions like this

        public MainViewModel ()
        {
            TinyPubSub.Subscribe (this, "update-ducks", () => 
                { 
                     // Get data and update the GUI
                });    
        }

The "update-ducks" string is just a arbitrary name and you can select what ever you want. Note that I don't pass any data (yet), but that might be the next step in destroying this library by bloating it.

Publish events

In another ViewModel we then decide to add a duck. 

        public ICommand AddDuck
        {
            get {
                return new Command (async () => {
                    // Do logic and add stuff

                    // Publish an event
                    TinyPubSub.Publish ("update-ducks");
                    await Navigation.PopAsync();
                });
            }
        }

This will fire the actions (synchronous at the moment) and then pop this view. The cool part is that when we pop the view, the subscriptions will be unsubscribed (remember the code in the beginning of the post) and the memory will be cleaned up.

Summary

This is a simple way to solve a common problem. There is a built in Messaging Center in Xamarin Forms that I personally find a bit messy to use.

Future features might be async actions and passing of simple data.

Tuesday, May 3, 2016

Enabling multitouch using CocosSharp

It's been a long time since my last blog post due to personal and professional reasons. Anyhow, now I'm planning to get back in the saddle and start blogging on a regular basis again. Also, this happens to be blog post number 100. Yay!

Short version


To enable multitouch in CocosSharp (Forms version) you must create a custom renderer to set the MultipleTouchEnabled on the CCGameView (platform specific code) and then you must inherit from the CocosSharpView in order to make the registration of the custom renderer work. Code in the bottom of the post.

Long version


I've started a little secret project of my own that required two things:

  1. A simple framework for drawing stuff
  2. A simple input scheme for multitouch

So I checked out the available frameworks out there for Xamarin (especially for Xamarin Forms) and I decided to give CocosSharp a run for its money. I've done some small CocosSharp projects before and it fits my needs for the prototyping of this app.

I'm using the Forms version of CocosSharp since I'm a big Xamarin Forms fan.

The issue


One of the first things I noticed was that the multitouch simply didn't work as I expected. No matter what properties I set there was no multitouch going on. After some google-fu I found out that you have to set the MultipleTouchEnabled to true on the CCGameView instance. Well, the CCGameView is platform specific and there is no exposure of this property in the platform agnostic CocosSharpView that you use in the forms project.

Custom renderer to the rescue


Well, that's a simple fix I figured. Simply create a custom renderer and set the property directly.

    protected override void OnElementChanged (ElementChangedEventArgs<CocosSharpView> e)
    {
        base.OnElementChanged (e);

        if (Control != null) {
            Control.MultipleTouchEnabled = true;
        }
    }

That didn't work. In fact, the method is never called. (Yes, I registered the renderer! :) ).

Create a custom control (the work around)


So the simple work around for this was to create a custom control.

    public class MyCocosSharpView : CocosSharpView 
    {
    }

And then use MyCocosSharpView instead of CocosSharpView. I'm not sure why it behaves this way, but its got to have something to do with the registration of the custom renderer. Hopefully I'll get some time to drill down in the source code and find out why.

What I would like


The MultpleTouchEnabled property should be visible from the CocosSharpView class. That is at least what I'll suggest to the CocosSharp team.

The code


These are the interesting parts of the code.