Category

Xamarin

Android

It’s very simple to set selected and unselected colors for Android devices. You can take advantage of the available platform specifics. Namely android:TabbedPage.BarItemColor  and android:TabbedPage.BarSelectedItemColor . Both can be easily set as attributes on the <TabbedPage>. For example:

The result:

Android TabbedPage colors

 

 

 

Note, to use platform specific properties, you need to define the namespace for them (i.e. xmlns:android ). It’s not part of this guide but you can see that we’re placing tabs on the bottom of the page, using another platform specific property android:TabbedPage.ToolbarPlacement="Bottom" . For more information around TabbedPage colors for android go to the official docs.

 

iOS

On iOS selected color is controlled with the BarTextColor  property. This actually controls both color of the icon and text below the icon. Unfortunately, at the moment there’s no easy way of setting the unselected color, so we will need to create an Effect or a Custom Renderer to set it. It’s always better to create an Effect rather than a Custom Renderer, as per recommendation. We will be using UnselectedItemTintColor property (available from iOS 10+) of the TabBar .

First let’s set up the effect in the platform independent project (.NET Standard library):

Next let’s create a platform specific class, that will set the color for the unselected tab item:

In the above code we retrieve the UITabBar element from the Container.Subviews  property and then we set the UnselectedItemTintColor.

The last thing to do is to add this effect to your TabbedPage :

The result:

iOS TabbedPage colors

 

 

 

You should not forget that to get the Effects working, you need to register them with Xamarin.Forms using ResolutionGroupNameAttribute. I tend to put that attribute either in the AppDelegate.cs (iOS) or in the MainActivity.cs file (Android). In this case we just need to define it for iOS:

Sample code for the above can be found in this repo: https://github.com/Progrunning/TabbedPagePlayground

I ran into an issue where my Xamarin.Forms UWP app, which uses MvvmCross and SyncFusion SfCharts stopped showing charts once I created the app package for the Windows Store (i.e. created *.appxupload package with .NET native tool chain).

I went hunting for a fix and rather quickly found a post on the SyncFusion official support forum about that problem. I also found that there’s a official Knowledge Base article:

Post: https://www.syncfusion.com/forums/127258/chart-not-rendered-in-uwp-release-mode

Knowledge Base: https://www.syncfusion.com/kb/7149/how-to-make-syncfusion-xamarin-forms-chart-to-work-in-uwp-in-release-mode-when-net-native-tool-chain

Both saying the same thing, that one should go to their App.xaml.cs file and add an extra assembly (i.e. typeof(Syncfusion.SfChart.XForms.UWP.SfChartRenderer).GetTypeInfo().Assembly)
to their Xamarin.Forms.Init() parameter in the OnLaunched() method. Basically add this code:

Unfortunately, this doesn’t work with MvvmCross 6.1.2 (probably doesn’t work with 6.2.0 as well – haven’t checked though). The charts are still not showing, even though the SfCharts assembly got included.

I can’t be 100% sure of the reason behind this problem but I suspect it’s because of the fact, that MvvmCross framework is now handling the Xamarin.Forms initialization for you. Because of that the Xamarin.Forms.Init() method is called multiple times – once in the App.xaml.cs and once inside of the framework. Another assumption, based on the results we’re seeing, is that Xamarin.Forms.Init() works in a way that the last in is the one that gets served – meaning that if the App.xaml.cs call happens before the MvvmCross one, then the SfChart assembly is not going to be included and Native tool chain compilation will strip it out.

A bit more explanation on this: Mvx framework calls the Xamarin.Forms.Init() method inside of the base Setup file – MvxFormsWindowsSetup calling Xamarin.Forms.Init(). The remedy is simple, move the code from App.xaml.cs to the GetViewAssemblies() override in your Setup.cs file. The GetViewAssemblies() method is being called at the launch of the app by MvvmCross and it is designed to retrieve additional assemblies to pass as a parameter into the Xamarin.Forms.Init() method – which is exactly what we want.

That’s it – you should see your charts again!

 

I’ve stumbled upon this issue straight after I released my app into the store…

I did a brief search on the Internet what could be causing such behaviour and majority of posts were pointing at some issues with cached data by Google Play Store and/or Google Play Services somehow breaking installation process. They were suggesting cleaning cache of these to solve the problem. Combination of clearing cached data, uninstalling the app, restarting the device and even ejecting the SD card did not help

I didn’t give up though. I was fortunate enough to have a device at home, that I was able to reproduce this with. At least it showing some errors when trying to deploy and debug the app using Visual Studio – which was a good start. Each and every time I tried to deploy the app onto the device I was getting the error

ADB0010: Unexpected install output: Failure [INSTALL_PARSE_FAILED_MANIFEST_MALFORMED: Failed parse during installPackageLI: /data/app/vmdl1021324914.tmp/base.apk (at Binary XML file line #28): <service> does not have valid android:name]

It didn’t tell me much, so I started googling it. Some of the StackOverflow posts (#1, #2) that I found were pointing me at the problem with package name capital letters. Yep, I did put some capital letters in my app name (i.e. com.progrunning.AirQuality, which ultimately became com.progrunning.airquality). I changed the name of the app in the AndroidManifest.xml but I was still getting that error…I had no choice but to check what’s actually being generated/added by Xamarin.Forms into the AndroidManifest.xml when packaging the app. I went to my bin\Debug folder, to try to unzip the generated *.apk file – *.apk is just fancy *.zip file. Unfortunately, at this stage the AndroidManifest.xml file in the *.apk is nothing but binary data. Which looks something like this when opened with Visual Studio Code:

Fortunately, thanks to this StackOverflow answer, there’s a way of reading what’s in the *.apk package. I located the aapt.exe file, where my android sdk got installed (in my case it was C:\Programming\SDK\Android\android-sdk\build-tools\27.0.3) and ran the command

aapt.exe l -a “C:\Programming\Projects\Own\AirQuality\AirQuality\AirQuality.Android\bin\Debug\com.progrunning.airquality.apk”

The above prints out quite a bit of stuff (you can probably narrow it with some pipes and grep commands – I’m no expert on these though), but we’re interested only in the AndroidManifest.xml file. From the error that I got when trying to deploy and debug the app I knew that something that prevents this from happening is located at the line 28. I finally got my answer:

I used capital letters for my background service (biggggggggggggg mistake!):

Changing it to lowercase fixed the issue

 

EDIT: The problem didn’t seem to be happening for the Android versions 8.0+. It was only affecting 6.0 and 7.0 (maybe more but these two versions are definitely confirmed)

EDIT2: I ended up with my app name having capital letters in it – that was not the problem