Xamarin forms – iOS disable cancel button on SearchBar

When you are using Xamarin forms and add the SearchBar control, you’ll notice that there will be a Cancel button shown while you are typing text in the search entry area.

We wanted to get rid of this cancel button, to get a cleaner design…
So I looked for the iOS reference on the UISearchBar and it seems that by manipulating the ShowsCancelButton property, you can show or hide that button.

To get this working I did what any Xamarin dev would do when you need to tweak native properties that are not available in Xamarin forms itself, I created a Custom renderer for the SearchBar…

The code is fairly simpel:

BUT when trying this out in a demo app, I noticed that the Cancel button would still appear when I started typing text in the search entry!!
No idea why this could be happening, I opened the Open Source code of Xamarin forms to take a look at how the guys of Xamarin are handeling the SearchBar.

And yes, thank god it’s Open Source, because now I could see why my custom renderer has no effect!
If we take a look at https://github.com/xamarin/Xamarin.Forms/blob/74cb5c4a97dcb123eb471f6b1dffa1267d0305aa/Xamarin.Forms.Platform.iOS/Renderers/SearchBarRenderer.cs#L167, we can see that the Xamarin forms base SearchBar renderer for iOS will toggle the ShowCancelButton property as soon as you change the text of the search entry… In other words, this will override my initial setting in my custom renderer.

Back to square one, how can we still hide the cancel button in this scenario?
Well if you look further in the code of Xamarin Forms, we will see that the cancel button is being updated each time the TextProperty and the CancelButtonColor property are changed.
So we need to override that behavior instead…

To do this, we’ll change our custom renderer and only add following code:

By adding this code we will bypass the base code of OnElementPropertyChanged if one of these 2 properties change. We do still copy/paste the original Xamarin forms code for the TextProperty because this is needed.
I did not however, copy over the code for the color changing of the cancel button – because want to hide it, so no need for that code in our project!

Well still not sure why the guys at Xamarin are forcing this cancel button, but great to know the code is Open Source so we can at least act upon it 🙂

Final result ( first one is the faulty renderer, second one is the correct renderer )

screen-shot-2016-10-27-at-14-51-15

All the code up on my GitHub

UWP – Split view deep dive ( the story of desktop mode or mobile mode )

So by now most people will know that I’m ‘still’ busy creating a Strava app for UWP called Kliva ( yes it is Open Source here… ).
Now the main purpose for using UWP was the fact that we could create 1 app that can be used on desktop/tablet pc’s and mobile phones!
Thanks to the new way of using Visual States in XAML we can tweak our design like we want depending on the size of the screen real estate.

All fine and dandy, but depending on the form factor it could also be that we need to navigate in a different way, Microsoft illustrated this by defining a Stacked Pattern and a Side-by-side pattern.
Read up on all the details here…

Now how can we as devs handle this difference in navigation? Well let me show you how we handled it in Kliva.

First we defined our own ApplicationFrame ( inherits from Frame ).

You’ll notice we do 2 things here, enable a Loading mode if needed and when a page is Navigated we trigger some code in a ViewModel.
Let’s deconstuct this later, I’ll first show you the actual frame setup…

So our frame will always consist of a SplitView control and the actual pages of our app will be rendered inside the SplitView.Content part!
We are using the SplitView control for the Side-by-side pattern reason, we will however need to adjust this in mobile mode, again more on this later 🙂 ( yep going to be a long post )

More importantly, we are now able to sneak in a full app wide loading overlay control. In other words, each time when needed, we will present an overlay with a progress ring, to indicate the app is still processing. By putting it here, inside the boilerplate code of the ApplicationFrame, it is available for all pages in the app!
Remember the code in the KlivaApplicationFrame? There is a method called ShowLoading(bool isLoading), this will put the Loading Grid in the correct VisualState ensuring it is visible or not and will also trigger the progress ring ( inside the LoadingControl ) to start.
The loading control itself is a user control that is nothing more than some text and a progress ring as show below…

But the real magic is in it’s code behind

We added the IsLoading property, so we can access it in our XAML – like we do in the VisualStates of the KlivaApplicationFrame.
But we also added a static method SetLoading(bool isLoading), we need this so that we can trigger the whole process of actually showing the control to the user!
In Kliva we let all our ViewModels inherit from a BaseViewModel and inside this one, we will call upon this static SetLoading method each time we think our app will need some time processing web requests.

So from a developer standpoint, each time you manipulate the IsBusy propety on the base viewmodel, our Loading Control will be shown to the user.
If you don’t like the ‘link’ between the ViewModel and the actual control, you could also work with MVVM messaging instead. No need for a static method that way, but hey we can’t always be 100% MVVM, right? 😉

Back to solving the mobile view, because you’ll remember that our original setup uses a SplitView and on mobile we want to shift this to actually using a BottomAppBar. To achieve this we need 2 things, hide the SplitView.Pane and showing the BottomAppBar.
Showing the bottom app bar is not that hard! We just check for the correct view size in our VisualStates and if needed toggle it’s visibility property depending on how large the screen actually is. From 320 to 720 we show it, everything above 720, we hide it.

Hiding the SplitView.Pane will need some coding… First part of this was already shown in our KlivaApplicationFrame, there when we navigate to a page we call upon the ShowHide method of the SidePaneViewModel.
This ViewModel is linked to the SidePane Control that is used inside the SplitView.Pane. We use several properties of this viewmodel on our SplitView properties, like the DisplayMode and IsPaneOpen ( cfr XAML code of our KlivaApplicationFrame ).
When we don’t need the SidePane of our SplitView, we set the DisplayMode to Inline and IsPaneOpen to false, if we do need the SidePane, we put the DisplayMode into CompactOverlay. That way, if on mobile, we can hide it and on desktop show it again.
We also extended the method a bit, so that we can hide the side pane on a given type of page, if needed ( currently not used )

Last but not least, we still need to find a way to adjust for page navigation or not. In our case, our main page will show a list of activities and when selecting one, present the details of that activity.
In a side-by-side pattern the details of the activity is on the right side of the list, in a stack pattern we need to navigate to the details page.

The side-by-side way is very easy, we put 2 controls in our main page, the first one contains the lists, the second one the detail info. Each of these controls are bound to the same ViewModel. So when an user selects an item from the list we will fill in the SelectedItem property on our ViewModel and our detail control will automatically show this.
But for the stacked pattern we add a bit of extra code, first again thanks to use of the VisualStates we will hide the detail control and secondly in our SelectedItem invocation we will try to start a page navigation if we are on mobile.
Not rocket science, just a little tweaking 🙂

The complete detail code for this can be seen on our github page for Kliva right here…