Soft keyboard covers text fields and makes them inaccessible

How can I reach the input field in ScrollViewer when the input field is overlapped using the soft keyboard?

This script is easy to reproduce:

  • Create a new page using a ScrollViewer containing some text fields. Create as many text fields as you need until you need to scroll through the page to get to the last three text fields.

    <ScrollViewer>
      <StackPanel Orientation="Vertical">
        <TextBox Margin="20" />
        <TextBox Margin="20" />
        <TextBox Margin="20" />
        ..
        <TextBox Margin="20" />
        <TextBox Margin="20" />
        <TextBox Margin="20" PlaceholderText="3" />
        <TextBox Margin="20" PlaceholderText="2" />
        <TextBox Margin="20" PlaceholderText="1" />
      </StackPanel>
    </ScrollViewer>
    
  • Launch the application and click "Placeholder 3". The keyboard pops up and overlaps "Paceholder 2" and "Placeholder 1".

How can I improve the layout so that I can reach these TextBoxes ("1" and "2") without closing and reopening the keyboard all the time?

, , WindowsPhone: = > VPN = > VPN = > = > , , , .

+4
2

, , , .

, scrollviewer , .

Xaml

<ScrollViewer x:Name="scrlvwrKBScroll" VerticalScrollMode="Enabled">
  <StackPanel Orientation="Vertical">
    <TextBox Margin="20" />
    <TextBox Margin="20" />
    <TextBox Margin="20" />
    ..
    <TextBox Margin="20" />
    <TextBox Margin="20" />
    <TextBox Margin="20" PlaceholderText="3" />
    <TextBox Margin="20" PlaceholderText="2" />
    <TextBox Margin="20" PlaceholderText="1" />
  </StackPanel>
</ScrollViewer>

#

public Constructor()
{
  this.InitializeComponent()
  InputPane.GetForCurrentView().Showing += Keyboard_OnShow;
  InputPane.GetForCurrentView().Hiding += Keyboard_OnHide;
}

private void Keyboard_OnShow(InputPane sender, InputPaneVisibilityEventArgs args)
{
  this.scrllvwrKBScroll.Height = this.ActualHeight - args.OccludedRect.Height - 50;
}

private void Keyboard_OnHide(InputPane sender, InputPaneVisibilityEventArgs args)
{
  this.scrllvwrKBScroll.height = this.ActualHeight;
}

, , , , , .

+3

, Page BottomAppBar . Margin Padding .

:

  • Window.Current.Content Frame
    • Border 1px Margin
      • ContentPresenter
        • Page BottomAppBar

" " , ScrollViewer . . UWPMobileScrollIssue .

// ...snip...
namespace UWPFocusTestApp
{
    sealed partial class App : Application
    {
        // ...snip...
        protected override void OnLaunched(LaunchActivatedEventArgs e)
        {
            // ...snip...
            if (rootFrame == null)
            {
                // ...snip...

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;

                #region WORKAROUND
                if (AnalyticsInfo.VersionInfo.DeviceFamily == "Windows.Mobile")
                {
                    InputPane.GetForCurrentView().Showing += InputPane_Showing;
                }
                #endregion
            }

            // ...snip...
        }

        #region WORKAROUND
        private void InputPane_Showing(InputPane sender, InputPaneVisibilityEventArgs args)
        {
            // we only need to hook once
            InputPane.GetForCurrentView().Showing -= InputPane_Showing;

            var frame = (Frame)Window.Current.Content;

            // Find root ScrollViewer
            DependencyObject cNode = frame;
            while (true)
            {
                var parent = VisualTreeHelper.GetParent(cNode);
                if (parent == null)
                {
                    break;
                }
                cNode = parent;
            }
            var rootScrollViewer = (ScrollViewer)cNode;

            // Hook ViewChanged to update scroll offset
            bool hasBeenAdjusted = false;
            rootScrollViewer.ViewChanged += (_1, svargs) =>
            {
                // once the scroll is removed, clear flag
                if (rootScrollViewer.VerticalOffset == 0)
                {
                    hasBeenAdjusted = false;
                    return;
                }
                // if we've already adjusted, bail.
                else if (hasBeenAdjusted)
                {
                    return;
                }

                var appBar = ((Page)frame.Content)?.BottomAppBar;
                if (appBar == null)
                {
                    return;
                }

                hasBeenAdjusted = true;
                rootScrollViewer.ChangeView(null, rootScrollViewer.VerticalOffset + appBar.ActualHeight, null);
            };
        }
        #endregion

        // ...snip...
    }
}
0

All Articles