软键盘与文本框重叠,使其无法访问

本文关键字:访问 重叠 键盘 文本 | 更新日期: 2023-09-27 18:33:11

当输入字段与软键盘重叠时,如何访问 ScrollViewer 中的输入字段?

此方案很容易重现:

  1. 使用包含一些文本框的滚动查看器创建一个新页面。根据需要制作任意数量的文本框,直到需要滚动页面以到达最后三个文本框。

    <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>
    
  2. 启动应用程序并点击"占位符 3"。键盘弹出并与"起搏器 2"和"占位符 1"重叠。

如何改进布局,以便无需一直关闭并重新打开键盘即可访问这些文本框("1"和"2"),以便访问这些文本框?

可以在

每个WindowsPhone上找到显示有效解决方案的示例: 设置 => VPN => 启用VPN => 添加新配置文件 => 单击任何文本框,您将看到您可以滚动到布局的每个部分,尽管软键盘已打开。

软键盘与文本框重叠,使其无法访问

在这个问题上已经有一段时间了,但对于可能正在寻找一个好解决方案的其他人来说,这就是我所做的。

订阅键盘显示

和隐藏事件,并根据键盘显示或隐藏的时间调整滚动查看器的高度。

哈姆勒

<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>

C#

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;
}

可能有一种更好的方法可以根据您使用的容器的高度调整高度,但这是我用来让我的应用程序工作的方法。

每当具有BottomAppBarPage在布局中从根视觉对象中移位时,我也会遇到此问题。 这可能是由包装器元素上的MarginPadding引起的。

损坏的可视化树:

  • 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...
    }
}