Thursday, November 6, 2014

Using MapFragment inside ScrollView

I have an app where I need to put a Map inside a ScrollView, doing so will make the ScrollView intercept all the touch events. So the solution is to call RequestDisallowInterceptTouchEvent(true) whenever you need the Map to scroll around, pinching it etc. The problem is that MapFragment or its properties do not expose any touch events, so it makes it a bit harder to find out when it is touched.

I found a nice little code snippet, Lorensius Londa posted on his blog, for Java Android, which overlays the MapFragment with a FrameLayout and using the FrameLayout touch event. Using this exact technique help me achieve my goal as well. Here is the code I used.

So as you see in the code there is a TouchableWrapper which simply fires some Actions whenever it was touched or the touch was released. This is grabbed by the TouchableMapFragment which subsequently fires the equivalent events.
The Fragment is used as follows in a AXML layout.
Then you can use the events in your Activity like so.
Now you should be able to navigate your Map when it is nested in a ScrollView.

Friday, October 31, 2014

Some experiences with the new Support packages on NuGet

I spent some time moving over to the new Support packages Xamarin released on NuGet, instead of using the versions from the Component store.

Jonathan Dick made a nice post about what makes the packages on NuGet a bit more smarter than they were previously, which I find very interesting. However, it is not all happy times as there seems to be some caveats by using these packages.

Hence, here are some findings that you might encounter when using them.

I have some Android Library projects, each updated to the new NuGet packages. The Android Library projects seem all to have $(TargetFrameworkVersion) defined in the .csproj file, which comes from the setting in the project properties in the Application tab called Compile using Android version. This sets the $(TargetFrameworkVersion) in the project file. However in my Android Application projects, I previously had that same option set to Use Latest Platform. The problem with this, is that it does not seem to explicitly set that in the csproj file. This gives some problems when fetching the NuGet for the Application project, where NuGet might tell you that it is incompatible and simply not install it (not cool :( ).

Another problem is that, say you have an Android Library project using Google Play services, this is also a NuGet package, which additionally brings in a lot of Support packages (including v4, v7, v13 (whoa!)). Now you do all your stuff with the Play services inside of the library, so you think you can suffice with simply adding the needed Support packages in your Android Application project. Lets say you only need Fragment backwards compatibility and you just pull in Support v4. This will give you a headache and throw a bunch of errors telling you that you have duplicate managed types.
The solution seems to match the packages you added in the Android Library project. So if you are using Google Play services in your Android Library project, you need the exact same packages in your Android Application project.

Apart from these couple of things, it seems that the new packages work pretty well. It also seems that additional Support v7 packages have made it into NuGet and more are to come!

I've switched the MvvmCross "3.5" branch and my own MvxPlugins "threeandahalf" branch to use this new stuff.

Friday, October 3, 2014

Getting User Location to work in iOS8

There were some minor changes to how iOS8 works with core location. Previously when requesting the user's location on the MapView with ShowsUserLocation a nice pop-up would automagically show up asking the user if this was ok. Apple decided to make this a bit more flexible, allowing the developers to enter their own message. So if you compile your pre-iOS 8 app with the new SDK this might break, since you now have to manually call a method to get that pop-up to show.

So the quick fix is to do the following:

1. In your info.plist file add one of the following key/value pairs:

2. I then have a Extensions.cs where I keep my various extensions, for this case I've just made a couple of checks to whether the selectors are available on the platform, so the code won't crash on previous versions of iOS.

3. Remove your previous call to mapView.ShowsUserLocation and do the following instead:

Now you respond to the AuthorizationChanged Event and set the ShosUserLocation flag accordingly.

Edit (3/10/2014 17:00):
Now that I have had the chance to play a bit more with it, I have a couple of observations that might help you. First don't let go of the CLLocationManager instance, i.e. have it as a class field otherwise the dialog will disappear pretty quickly and it won't let you get location updates.

I didn't mention that you will have to do some checks on what iOS version you run at now and only call this code when on iOS 8 and higher, to do this you can do something as follows.

Saturday, July 5, 2014

Port of Floating Action Button

Android L has introduced something called a Floating Action Button (FAB), which is basically a circle overlayed on top your application. This FAB can be clicked to do an action. In the Google+ application this is used to persistently allow the user to create a new post.

It basically looks like in the screenshot above, where you can see a circle with a play icon at the bottom of the screen. Faiz Malkani backported this from Android L to work on JellyBean and KitKat, and I took the liberty to port it to Xamarin.Android.

You can find the repository on GitHub along with a sample application, which the screenshot above is from.

Tuesday, July 1, 2014

Xamarin.Forms and MvvmCross

As promised during the Xamarin 3 webinar, I have made a small sample showing how to use Xamarin.Forms along with MvvmCross.

What I did was look at the code Stuart Lodge already had made in another private repository, and adapted this to use it with Xamarin.Forms. What it basically does is implement custom Presenter implementations, which work with the way Xamarin.Forms navigates its Pages, which is through a NavigationPage and simple Push and Pop methods. This is wrapped in a PageNavigationProvider in MvvmCross which is in turn leveraged by the custom presenter.

Right now the sample has these presenters and MvvmCross specific classes built in, but will most likely in the future be pulled out and made into a plugin, which you can use in your own applications.

So the sample itself is a very simple application, which allows you to search TMDB for movies, it then fetches similar movies based on your search query and displays them. In turn you can then press an item in the list presenting the search results and get detailed information about the movie.

The sample actually covers a lot of MvvmCross by using:

  • ViewModels
  • Services
  • Custom Presenters
  • Bindings
  • Commands
  • Converters
  • Nuget
You can get the sample on Github

Thursday, May 22, 2014

Noise Sentinel at Microsoft Case studies

Microsoft just recently released a case study regarding one of the products I work on at Brüel & Kjær, namely Noise Sentinel. This case study is based on the usage of Microsoft Azure and the services Microsoft provides and how they have helped innovating the product.

You can read the case study here: Microsoft Case Study

Tuesday, April 29, 2014

FoldingLayout ported to Xamarin.Android

I found this little cute library, called Folding-Android, which implements a fun type of layout, which adds a folding effect to any layout you nest inside of it. I have ported this for Xamarin.Android for everyone to enjoy.

Find it in Xamarin Component Store and fork it on GitHub!

Here are some sample screenshots showing what it can do:

Folding Horizontally with 2 folds
Folding Vertically

It also has implementations which sub-classes DrawerLayout and SlidingPaneLayout, from Support v4, which adds the effect to their drawer/pane.

DrawerLayout implementation
SlidingPaneLayout implementation

Wednesday, April 2, 2014

SlidingUpPanel port for Xamarin Android!

I spent some of my time yesterday on a bit of porting Java to C#, instead of sitting in the sun and drinking beer. I found this pretty neat little library, AndroidSlidingUpPanel, which adds a panel to your app, which slides up from either the bottom or top of your screen. The code itself is very inspired by the innards of SlidingPaneLayout from Support v4.

Anyways, here is a GIF of what it looks like:

Adding to your project is pretty simple. Simply grab it from the Xamarin Component store or if you prefer, you can clone or download it from GitHub, which also has the component, but also the source code. There is a nice sample which will show you how to use this library, but if you just want to get started quickly. Simply add the following code to the AXML layout file you want this panel in:

So the SlidingUpPanelLayout should be the root of your layout, and then it will have two children. First child is your content layout, what your originally had in your layout. The second child is the contents of the panel. Now you are good to go! For more info look at the docs on either the component store or on GitHub!

Sunday, March 30, 2014

Filtering ListView with SearchView in Xamarin.Android

I recently made a video describing how to add a SearchView to your ActionBar, using the Support v7 package to provide backwards support, all this done in Xamarin.Android! I posted it on the Xamarin Forum's, University section, which I have access to, since I am attending Xamarin University. There were some interesting questions, which I found solutions for and I simply wanted to share them, so I am writing this blog post to do so. For background knowledge take a look at this video, which started this, and I am going to use that as a starting point for this blog post.

So the video, shows a very simple implementation of SearchView, which filters simple string elements feeded into the ArrayAdapter, which already has a nice simple Filter implementation, which simply matches the search query to see if it is contained in the items in the ListView. Now this simple implementation might not be sufficient enough for you, because as soon as you need to show something more complicated in a ListView, you will need to implement your own Adapter. Doing so will also require you to implement your own Filter as the Adapter you implement yourself cannot know what arbitrary data you will present.

SearchView filtering ArrayAdapter

Anyways, enough talk, let us dive into the code. So easy mode as described in the video and gist:

So here the magic happens in the OnCreateOptionsMenu method line 39-58, where we find the ActionBar MenuItem and subscribe to the SearchView's ActionView query changes, which invokes the default Filter in the ArrayAdapter.

Reacting on SearchView Expand/Collapse

One of the questions that popped up was, when having the back Action enabled in the ActionBar when using the SearchView, how do you react to the Expand and Collapse events? This is pretty simple, but might not be that super obvious.

You have to create a class implementing IOnActionExpandListener. In this example I am going to remove the filter from the Adapter when collapsing the SearchView.

To hook it up to the SearchView you have to use the helper class MenuItemCompat, to attach it to the MenuItem which you do in the OnCreateOptionsMenu:

Filtering in custom Adapters

Now the other question was, how do I filter my custom Adapter? Very good question if you ask me. As already mentioned, for that you have to implement your own Filter, as the nature of a custom Adapter is that you present custom stuff. Hence the default Filter implementation cannot know how to filter that. I am just going to replicate what the default Filter does on a string property of the model I am going to present in the ListView.

The final solution can be found on → GitHub

So before we begin I have to warn you that FilterResult which is used to store the filtered values temporarily, expects that the object stored is a Java type. So either your model which you populate your Adapter with has to implement Java.Lang.Object or you will have to wrap your values. I will show you the latter, as it will apply to the more use cases, as you probably cannot and probably do not want to implement Java.Lang.Object in your contracts or whatever you are using to store data in, especially when you are communicating and sharing code between platforms.

To wrap up .NET types with a Java type I am using modified code from this monodroid mailing list thread, which looks like this:

The main difference is that the Java holder object is disposed of immediately when it is converted to a .NET object. Also the comparison in the original source, whether the value was null is unsafe, as it does not take value types into consideration. The object disposal is very useful to keep GREF references down to a minimum. I really don't want the app to run high on memory.

Now with that covered, let us get to the actual Adapter and Filter. I have created a class called Chemical, which has Name and DrawableId property. Which are going to be assigned to a custom view, in the Adapter. Not going to cover View creation here, but this one is pretty simple, really.

So Chemical looks like this:

And the Adapter looks like this:

So I am just going to describe what happens in the custom ChemicalFilter, as the rest of the Adapter is pretty trivial. So first thing is that I have to pop in the reference to the ChemicalsAdapter, because I want to store both the original list of Chemicals and the filtered version in the Adapter, so we always can go back to the state we started at. So I always look for matches in the _originalData field, which is looped and matched, lower case, if the Chemical contains anything in the ICharSequence which is passed into the PerformFiltering method. The ICharSequence is just a spartan Java interface providing some simple methods such as lenght, getting a char at at specific position and a sub sequence of chars, nothing too fancy. I simply convert that to a string and match against the Chemical Name property. So the results of that matching is transformed into an array of Java objects, with help of the modifier .NET to Java wrapper I described above using a bit of LINQ. This is done since FilterResults expects an array of Java objects. I also call Dispose on the ICharSquence, as it seems like not doing so builds up the GREF count.

Now in PublishResults the values are converted back to the Chemical .NET type also using a bit of LINQ. The results are set in the Adapter's _item field and the Adapter is notified of the changes in the data set. Both arguments are Disposed of.

So, this is pretty simple stuff. It is just the conversion from Java to .NET and the other way around that can cause some troubles. So just keep in mind, that if your GREF count is rising, then you should probably look into Disposing of some of your stuff.

Again the final solution can be found on → GitHub

Tuesday, January 21, 2014

Matching UIKeyboard speed and curve to your animation

I have a ViewController in my Xamarin.iOS application, where i scale the View Frame when the keyboard shows. However, I had some trouble with matching the speed and curve of the animation to the keyboards animation. Though I found a pretty good solution, which takes the values from the keyboard itself, through the UIKeyboardWillShowNotification.

Friday, January 17, 2014

Disabling ActionBar menu items

I have some use cases where I want to temporarily disable ActionBar menu items, such that they are not clickable, but also so they are a different color from the active ones. The default SetEnabled method on IMenuItem does not do this for you. Sure it disables the item, however the visual state does not change. Hence, I found a nifty way to change this and made my own SetEnabled extension method.

Using this extension method can grey out menu items, so they appear disabled from a UX perspective. The method takes some more parameters, as it needs to get the resource id of the Drawable you want to use for the greyed out item and the current Context, such that it can get it from the application resources.