Search code examples
windows-phone-8.1windows-phonewin-universal-appwindows-10-universalwindows-10-mobile

InputPane does not work correctly


I'm currently developing an Universal Application, but here is a problem. I have a Frame with the TextBox for User Phone Number. Initial Page

So, I want to change the height of my LayoutRoot (GRID) so it can fits in the free space.
I'm using InputPane.GetForCurrentView().Showing and InputPane.GetForCurrentView().Hiding for that purposes. Here is my code.

public UserRegistrationAuthorization_PhoneNumber()
    {
        this.InitializeComponent();
        LayoutRootInitialHeight = LayoutRoot.ActualHeight;
        InputPane.GetForCurrentView().Showing += UserRegistrationAuthorization_PhoneNumber_Showing;
        InputPane.GetForCurrentView().Hiding += UserRegistrationAuthorization_PhoneNumber_Hiding;
    }

private void UserRegistrationAuthorization_PhoneNumber_Showing(InputPane sender, InputPaneVisibilityEventArgs args)
    {
        LayoutRoot.Height = LayoutRoot.ActualHeight - args.OccludedRect.Height;
        LayoutRoot.VerticalAlignment = VerticalAlignment.Top;
        args.EnsuredFocusedElementInView = true;
    }

private void UserRegistrationAuthorization_PhoneNumber_Hiding(InputPane sender, InputPaneVisibilityEventArgs args)
    {
        // TODO: Get rid of that shit
        LayoutRoot.Height = LayoutRootInitialHeight;
        args.EnsuredFocusedElementInView = false;
    }

When I click outside the TextBox keyboard hides and leaves after that a black hole on the screen. 2

enter image description here

But, the most interesting is that when I press that physical Back Button on my Lumia, keyboard hides normally and my LayoutRoot gets the Frame's initial height.

Is it a bug or I'm doing something wrong?


Solution

  • It happens because by the time you saving your LayoutRootInitialHeight in the constructor, LayoutRoot actually isn't loaded and it's ActualHeight == 0. Then you setting LayoutRoot.Height to 0, so it becomes not visible. So you should probably save your LayoutRootInitialHeight in LayoutRoot's Loaded event handler.

    I would also suggest you not to change LayoutRoot's height at all. It causes your whole visual tree to be rendered from scratch and it's bad practise in general. Instead, modify RenderTransform of all necessary elements so they get moved to appropriate positions. RenderTransform is the right way to handle movements and animations on the screen, and you can achieve some nice visual effects with Next button moving up same as keyboard.

    Roughly your code can look like this:

    <Button Content="Next" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center">
        <Button.RenderTransform>
            <CompositeTransform x:Name="NextButtonTransform" TranslateY="0"/>
        </Button.RenderTransform>
    </Button>
    

    ...

    private void UserRegistrationAuthorization_PhoneNumber_Showing(InputPane sender, InputPaneVisibilityEventArgs args)
    {
        NextButtonTransform.TranslateY = -300;
        EnsuredFocusedElementInView = true;
    }
    
    private void UserRegistrationAuthorization_PhoneNumber_Hiding(InputPane sender, InputPaneVisibilityEventArgs args)
    {
        NextButtonTransform.TranslateY = 0;
        args.EnsuredFocusedElementInView = false;
    }
    

    And more complicated way is to run some storyboard which makes your Next button move up and down in same speed with keyboard, always appearing on top of it. Although, since InputPane.GetForCurrentView().Showing gets fired after keyboard already shown fully, you should hook up all animations to TextBox.GotFocus and TextBox.LostFocus events. On mobile, keyboard is always shown when text box has focus, so it will work nicely.