Avoiding hard times with the soft keyboard

Developers who submit a Windows 8 XAML-based Store app that involves data entry, should always test their app on a real touch device. Otherwise they might see their app rejected because of the soft keyboard blocking the screen. This article illustrates some of my personal experiences and issues regarding the behavior of the soft keyboard in Windows 8 Store apps. Don’t worry: none of these issues is really blocking, and I’ll show you some workarounds.

When and why the soft keyboard opens and closes, is described in this white paper. If you’re building Windows 8 Store apps that have data entry pages, this white paper is a must read. The behavior of the soft keyboard is well documented and justified, at least in theory. In practice however, I came across some issues. Here they are:

The soft keyboard never closes automatically

The keyboard cannot be opened programmatically. That’s a good thing. The keyboard opens only when the user taps on a text entry control (mostly a TextBox). Unfortunately the only way to indicate that he’s finished entering data, is to ‘tap somewhere else on the screen’. Depending on that ‘somewhere else on the screen’ the soft keyboard will remain open, or it will disappear. Now some controls know very well when data entry is finished and should not require that extra tap. E.g. a box to enter a year or birth could (and in my opinion should) leave edit mode automatically when four digits are entered. In other controls, hitting the ‘Enter’ key would be an intuitive action to indicate the end of data input. I implemented the latter behavior in my EnhancedSlider, that’s a slider that comes with an extra TextBox to allow direct input. That TextBox becomes disabled when the user hits the ‘Enter’ key in it.  I believe that tapping that key on the keyboard is a lot more user friendly than letting the user search for a safe spot on the semi-obscured screen (remember: the soft keyboard covers half the screen) to close the keyboard.

The ‘tap outside the control’ philosophy also makes it impossible to make a full-screen text input control. Here's what happens if the screen is entirely filled by one or more textboxes: 

The user can enter some tekst, but he can't close the keyboard anymore. If the Windows8 App store testers get stuck in this scenario, they will not approve your app.

The next edit control is automatically focused

When the TextBox in the EnhancedSlider becomes disabled, the keyboard remains open if there are other text input controls on the page. I’m OK with that: we’re in edit mode, so it doesn’t make sense to distract our user by constantly flipping the keyboard up and down. But not all screens require the use to enter the data in a specific order. Allow me to illustrate this with an example. This is a screenshot of a user changing the weight of some business object through an EnhancedSlider (middle of the screen):

Here’s what happens by default when the user finishes editing by hitting ‘Enter’. The keyboard remains open with the focus on the category ComboBox (I’m complaining about the focus here, not the ugly blue color – the inappropriate color is clearly my fault):

There are no relationships between the fields, so there’s no required input order. The user just modifies what he needs to modify in any chosen order. There’s absolutely no need to automatically give the focus to any of the controls. It’s not like the user is going to use the soft keyboard to tab through the controls on the page. On the other hand: a user with a real keyboard may just want to tab through the screen, so setting the IsTabStop property to false is not a viable solution. I believe that it should be possible for a developer to specify that the keyboard may remain open without a particular control getting the focus. I have the impression that the soft keyboard paradigm in Windows 8 is based on archaic fill-out form logic.

Up until now, you could say: “Hey, it’s your own fault. You’re using a custom control that violates the UX standards”. OK, I agree with that. But here’s an issue that has nothing to do with me trying to deliver user friendly controls:

The keyboard remains open on ListBoxItem

When the soft keyboard is open and the focus moves to another text input control, the keyboard remains open. I already mentioned that I’m OK with that. I just have a problem with the definition of ‘text input control’. This is the list from the mentioned white paper: Check box, Combo box, Radio button, Scroll bar, Tree, Tree item, Menu, Menu bar, Menu item, Toolbar, List, List item.

That last control is the one that bothers me. In a tile-based store app –and that’s the large majority- everything is hosted inside a ListItem. A lot of pages do nothing more than displaying a collection of business objects in an ItemsControl (ListView, VariableSizedGridView, SemanticZoom, etc.) The main navigation hub of single page apps (like the finance and weather app) uses a GridView as main navigation panel. Here’s another example of a real app that has a horizontally scrolling page with several topics. That's a very common concept. Unfortunately, things go wrong when you request the user to type in some tekst in such an app. I just wrote something in the text box at the bottom of the page, and tapped inside the border:

There’s nothing special to see, except a blinking cursor in the text box (and the screenshot does not even show that). The app looks fully operational. But that’s only because I took the screenshot when a physical keyboard was attached to the tablet. This is how the same screen looks like in full touch mode:

The keyboard remains open because the controls are hosted in a GridViewItem, which is a ListItem, which is in the keep-the-keyboard-open list. Tapping on the page does not close the keyboard, and the main navigation buttons are off-screen. The UI is blocked now, the app will be rejected. #FAIL

Easy work arounds

OK, here’s the good news: all these issues can be solved by adding one or two simple XAML controls on your data entry page. When fighting with the soft keyboard, you just give one of these controls programmatically the focus, and the keyboard will obey your will.

The first problem solver is a focusable control of the text input kind, without a user interface. When you give this one the focus, the keyboard will open without focusing one of the visible controls. That sounds easy: just create a text box with Visibility set to Collapsed, or Height or Width at zero. Unfortunately that does not the trick: the runtime will not give the focus to a control that does not consume screen infrastructure. But we know that templatability is a key concept in XAML, so let’s leverage it. The next control successfully fools the Windows RT runtime:

<!-- Opens the soft keyboard when it gets the focus -->
<TextBox x:Name="KeyboardOpener">
    <TextBox.Template>
        <ControlTemplate />
    </TextBox.Template>
</TextBox>

You can give this control the focus programmatically like this:

this.KeyboardOpener.Focus(FocusState.Programmatic);

 Or you could just place it at the right position. In the above screen I just added a KeyboardOpener next to the Enhanced Slider:

<local:EnhancedSlider Value="{Binding GrainGift.Weight.Value, Mode=TwoWay}"
                        Header="Weight"
                        ValueSuffix="{Binding GrainGift.Weight.UnitMeasure.Name, Converter={StaticResource StringFormatConverter}, ConverterParameter=' {0}'}"
                        Minimum="0"
                        Maximum="{Binding GrainGift.MaxWeight}"
                        StepSize="5" />
<TextBox x:Name="FocusGrabber">
    <TextBox.Template>
        <ControlTemplate />
    </TextBox.Template>
</TextBox>

The Combo box does not turn blue anymore.

If for some reason you want to programmatically close the soft keyboard, give this control the focus:

<!-- Closes the soft keyboard when it gets the focus -->
<Slider x:Name="KeyboardCloser">
    <Slider.Template>
        <ControlTemplate />
    </Slider.Template>
</Slider>

In the above example, I set the focus to this control in the Tapped event of the GridViewItem:

<GridView SelectionMode="None">
    <GridView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </GridView.ItemsPanel>
    <Grid Tapped="Page_Unfocus">
        <!-- Content, including edit controls -->
    </Grid>
    <!-- Other pages -->
</GridView>
private void Page_Unfocus(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
    this.FocusGrabber.Focus(Windows.UI.Xaml.FocusState.Programmatic);
}

A Close-the-keyboard Button

The problem in the first screenshot of this article can only be solved by adding a button to the page, a button to close the soft keyboard when it's open. That's exacly what I did. Here's the XAML:

<Button x:Name="KeyboardCloser"
        Visibility="Collapsed"
        Style="{StaticResource HideKeyboardAppBarButtonStyle}" />

By default it is invisible. It should only appear when the soft keyboard is open. To achieve this, just register to the InputPane.Showing event. Here's the code from the constructor of the page:

var inputPane = InputPane.GetForCurrentView();
inputPane.Showing += InputPane_Showing;
inputPane.Hiding += InputPane_Hiding;

And here are the two event handlers:

private void InputPane_Showing(InputPane sender, InputPaneVisibilityEventArgs args)
{
    this.KeyboardCloser.Visibility = Visibility.Visible;
}

private void InputPane_Hiding(InputPane sender, InputPaneVisibilityEventArgs args)
{
    this.KeyboardCloser.Visibility = Visibility.Collapsed;
}

That's it. When soft keyboard pops open, we show a button to close it. The button itself does not require a click event handler. Tapping it gives it the focus, and that's enough to close the keyboard:

Demo time

As usual, I built a small sample project to illustrate these focus-and-keyboard issues. It shows that you can easily open and close the soft keyboard, and that not every ListboxItem keeps the keyboard open. Just check the comments in the code. Here are some screenshots:

If you're not on a touch device, run the code in the simulator. Otherwise there's really not much to observe...

Code

Here’s the full code of the sample. It was written with the free Visual Studio 2012 Express Edition: U2UConsult.Keyboard.Sample.V2.zip (391.60 kb)

Enjoy!

Diederik