Xamarin forms – multi line label custom renderer gotcha

** UPDATE **

We expanded this and added an Effect for eveyone to use in the Xamarin Forms Community Toolkit!
It’s available here : https://github.com/FormsCommunityToolkit/FormsCommunityToolkit
The effect itself resides here : https://github.com/FormsCommunityToolkit/FormsCommunityToolkit/tree/dev/src/Effects/Effects/Label

On a project I’m working on, we needed a label that would show an ellipsis at the end. ( the 3 … indicating there is more text but not enough space on the screen to fit it all )

Having this on a label control in Xamarin forms is easy, you just add the property

this will force the ellipsis to appear if needed.

But on a specific page we wanted to show more text to the end user and even than add an ellipsis if needed. So in other words we would love to be able to tell the label control how many lines it should at least try to display.
To get this working in Xamarin forms you’ll need to add a custom renderer. Because the Xamarin forms label control doesn’t have any property available for us to manipulate to accomplish this.

This is not difficult at all to do, but there is a small gotcha with Android when you want to pull this off!

But let’s start with what you need to do to get this working.
In the Xamarin forms PCL ( so the general one, not the iOS or Android project ), we first add a class called MultiLineLabel.cs – this will be our own custom control.
It inherits from Label and we only need to add 1 dependency property called Lines, defined as an int. It looks like this:

After defining this custom control, we can use it on our XAML page, like so:

We will be using this Lines property in our custom renderers.
First up the iOS custom renderer for our MultiLineLabel. Create a class in the Xamarin forms iOS project called CustomMultiLineLabelRenderer.cs with following code:

You’ll notice that we are checking if the user specified a value for the Lines dependency property and if this is true, we pass this to the actual iOS UIKit.UILabel control by setting it’s Lines property. With this in place we get following result.

Screen Shot 2016-06-27 at 08.31.08

So iOS is done and looking great. Now add the Android renderer. Create a CustomMultiLineLabelRenderer.cs class in the Xamarin forms Android project with following code:

This doesn’t look all that different from the iOS counterpart… instead of setting a property we now use a method SetLines on the Android.Widget.TextView indicating how many lines we want it to display.
But wait, if we try this and look at the result, we’ll notice that it doesn’t work!!

Screen Shot 2016-06-27 at 08.31.05

It took me a while to figure this out ( I’m no Android expert 😉 ). But after taking a look in the Xamarin forms source code ( glad it’s open source 😉 ) I noticed they will always force a SetSingleLine(true) when setting the TailTruncation LineBreakMode…
Code can be seen here https://github.com/xamarin/Xamarin.Forms/blob/2d9288eee6e6f197364a64308183725e7bd561f9/Xamarin.Forms.Platform.Android/Renderers/LabelRenderer.cs#L179

So the fix is easy… you need to reset this Single Line forcing, the final code looks like this ( in your custom renderer ) :

With that in place we’ll get following result

Screen Shot 2016-06-27 at 08.31.31

Yeah success!
To start I’ve done a pull request on Xamarin forms to counter this SingleLine forcing, but not sure this will be added though… https://github.com/xamarin/Xamarin.Forms/pull/234
So better be safe and add the extra line in your own custom renderer for now.

As always example project up on github here…

Xamarin forms – multi line page title

On a current Xamarin forms project I’m working on, there came the question if it would be possible to show 2 lines in the title bar of our app instead of 1.
Normally this is not something you would do, seeing the default behaviour on iOS and Android, an app would only display 1 line and cut if off by adding ‘…’.

But in our case we are showing detail information on a conversation and it would help the user if we could show some more context.

The goal would be like this:

Screen Shot 2016-05-30 at 22.04.41

Screen Shot 2016-05-30 at 22.05.27

To achieve this result, you’ll need to implement a custom renderer on each platform. Both on iOS and Android of the type PageRenderer.

First iOS.
In your Xamarin Forms solution, underneath the iOS project add a folder called CustomRenderers and add a class called CustomContentPageRenderer.cs.
Here we will implement a PageRenderer with following code

Inside the WillMoveToParentViewController method we will grab the current page and see if it does contain an actual Title ( not each page needs one ).
If so, we’ll new up an UILabel because with this iOS control we can set how many lines need to be used ( if needed ) : titleLabel.Lines = 2.
We must ofcourse not forget to pass the current page title to it and only thing left afterwards is placing this UILabel in the TitleView of the current navigation page : parent.NavigationItem.TitleView = titleLabel.

By doing this we will override the normal Xamarin Forms rendering of the title in a navigation page and allowing use of 2 lines in it!

Secondly Android.
Same setup as in iOS, so a CustomRenderers folder with a CustomContentPageRenderer class file. But there is a bit more code needed for this to work now…

You’ll see now that we are using the OnElementChanged method to do almost the same as in iOS. So again check if the actual page does have a title or not and when it does, create a new TextView element.
On this Android control we can also indicate that we want to use 2 lines is needed : title.SetMaxLines(2).
And also here we need to pass in the actual page title and adjust the default Xamarin forms rendering view : actionBar.SetCustomView (title, new ActionBar.LayoutParams (LayoutParams.MatchParent, LayoutParams.MatchParent)).

What is different on Android, is that the ActionBar ( where the title is shown ) is shared across all pages. Thus once you’ve manipulated it, it will be fixed for all.
Meaning that when you have navigation and go back in the navigation stack, you’ll see that the set title will no longer change!
To counter this, we’ll need to hook into another event to keep track of this back stack navigation and if needed reapply the title.
This is done by monitoring the Element.Appearing event and when we enter this, reset the page title : ((TextView)actionBar.CustomView).Text = page.Title.

Hope this makes some sense and can help those out there that do need this feature 🙂

As always all the code can be found on my github right here… https://github.com/Depechie/XamarinFormsMultiLineTitle

MvvmCross UWP SplitView

With the new UWP platform to create universal windows app, we now also have a new control called the SplitView.

This control allows us to ‘split’ a page in 2 parts, a left part that is a pane, mostly used for showing a navigation menu. And a right part where we will be loading our content pages.

Microsoft has created a nice demo app on how you could set this up! To be able to load views in only the right part of the SplitView, we need to use a Frame.
Complete demo can be found here https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/XamlNavigation/cs

All good and well, but what when we want to use this setup in our cross platform environment? In other words what do we need to do in our UWP project when we are building it using Xamarin and MvvmCross? For reference we are talking about using a PCL project ( for cross platform use ) and a UWP native project using that PCL, all wired up with MvvmCross.
The basis of this setup came from this blogpost: http://stephanvs.com/implementing-a-multi-region-presenter-for-windows-10-uwp-and-mvvmcross/

We’ll only be focussing on the UWP part, because setting up MvvmCross should be ok for people who know MvvmCross 🙂
When your project is created, we’ll set up a main page where we implement our SplitView.
I’ve added a FirstView and it inherits from MvxWindowsPage, it contains the SplitView with a Frame in the content part. Import thing to note here is that we are providing a name for the Frame, called FrameContent, this will define our MultiRegion.

Nothing fancy so far. But in the code behind of this View we need to add a property called AppFrame, because that will be used later on to enable the page loading in the defined frame. So just add the following in the code behind:

Now for the actual page loading, we will need to override the View Presenter creation of MvvmCross, this is done in the Setup.cs of the UWP project. Because instead of creating normal MvvmCross views, we need a MultiRegionView.
So add the following override in your Setup.cs file:

Last thing to do is indicate what views need to be loaded inside the frame, you do this by adding a MvvmCross attribute above your View definition. So if I want SecondView to be loaded in the region, I just add the following above the class definition of the view in code behind:

This will tell MvvmCross to load the complete view in a Region called FrameContent and like we said earlier, this is the name of our Frame we definied in our FirstView.
Now each time when you navigate to this view by using the MvvmCross viewmodel navigation, it will be shown inside the frame of your SplitView!

That’s it, not that hard actually 😉
A complete demo app of this can be found on my GitHub here https://github.com/Depechie/MvvmCrossUWPSplitView