新しいノートパソコン超快適で幸せです。
UWP の入力フォームなどで、タッチキーボード*1を表示すると、隠れてしまう要素があります。
しかしながら、ガイドラインにもあるように、常に表示しておくのが良い要素もあります。
私が探した限りでは、標準で楽に実装できるものがなさそうだったので、
やり方をメモしておきます。
キーボードに隠れると困る要素というのは、例えば、送信フォームの「送信」ボタンだとか。
Twitter で言えば、画像添付だとか、そういうのは隠れると、ちょっと不便になってしまいます。
ちょうど、 Twitter 公式アプリも、そういった要素はキーボードで隠れないようにされています。
ということで、早速実装。
<Page x:Class="UniversalApp10.Views.Pages.TweetPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mvvm="using:Prism.Windows.Mvvm" xmlns:vm="using:UniversalApp10.ViewModels.Pages" d:DataContext="{d:DesignInstance vm:TweetPageViewModel}" d:DesignHeight="300" d:DesignWidth="400" mvvm:ViewModelLocator.AutoWireViewModel="True" mc:Ignorable="d"> <RelativePanel x:Name="Root" VerticalAlignment="Stretch"> <RelativePanel x:Name="Header" RelativePanel.AlignLeftWithPanel="True" RelativePanel.AlignRightWithPanel="True" RelativePanel.AlignTopWithPanel="True"> <Grid x:Name="TweetCounter" Height="64" RelativePanel.AlignRightWithPanel="True"> <TextBlock Margin="0,0,10,0" VerticalAlignment="Center" FontSize="15" Text="{x:Bind ViewModel.WhisperCount, Mode=TwoWay}" /> </Grid> <StackPanel Height="64" RelativePanel.AlignLeftWithPanel="True" RelativePanel.LeftOf="TweetCounter" Orientation="Horizontal"> <Image Width="48" Height="48" Source="{x:Bind ViewModel.User.Icon}" /> <StackPanel Margin="10,0"> <TextBlock FontSize="16" Text="{x:Bind ViewModel.User.Name}" /> <TextBlock FontSize="14" Foreground="Silver" Text="{x:Bind ViewModel.User.ScreenName}" /> </StackPanel> </StackPanel> </RelativePanel> <Grid x:Name="Footer" Height="32" RelativePanel.AlignBottomWithPanel="True" RelativePanel.AlignLeftWithPanel="True" RelativePanel.AlignRightWithPanel="True"> <Grid.ColumnDefinitions> <ColumnDefinition Width="1*" /> <ColumnDefinition Width="1*" /> <ColumnDefinition Width="1*" /> <ColumnDefinition Width="1*" /> </Grid.ColumnDefinitions> <Button Grid.Column="0" HorizontalAlignment="Stretch" Content="@" /> <Button Grid.Column="1" HorizontalAlignment="Stretch" Content="#" /> <Button Grid.Column="2" HorizontalAlignment="Stretch"> <Button.Content> <FontIcon Glyph="" /> </Button.Content> </Button> <Button Grid.Column="3" HorizontalAlignment="Stretch" Background="{StaticResource SystemControlHighlightAccentBrush}" Content="Tweet" /> </Grid> <TextBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch" AcceptsReturn="True" RelativePanel.Above="Footer" RelativePanel.AlignLeftWithPanel="True" RelativePanel.AlignRightWithPanel="True" RelativePanel.Below="Header" TextWrapping="Wrap" /> </RelativePanel> </Page>
長いですが、なんとなく公式 Twitter アプリのツイート画面っぽいレイアウトになっています。
次は、コードビハインド側です。
using Windows.UI.ViewManagement; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Navigation; using UniversalApp10.ViewModels.Pages; // The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236 namespace UniversalApp10.Views.Pages { public sealed partial class TweetPage : Page { private readonly InputPane _inputPane; private double? _rootHeight; public TweetPage() { InitializeComponent(); _inputPane = InputPane.GetForCurrentView(); _rootHeight = null; } public TweetPageViewModel ViewModel => DataContext as TweetPageViewModel; private void OnKeyboardShowing(InputPane sender, InputPaneVisibilityEventArgs args) { _rootHeight = !_rootHeight.HasValue ? Root.ActualHeight : _rootHeight; Root.Height = _rootHeight.Value- sender.OccludedRect.Height; // * Root.VerticalAlignment = VerticalAlignment.Top; } private void OnKeyboardHiding(InputPane sender, InputPaneVisibilityEventArgs args) { if (!_rootHeight.HasValue) return; Root.Height = _rootHeight.Value; Root.VerticalAlignment = VerticalAlignment.Stretch; } #region Overrides of Page protected override void OnNavigatedTo(NavigationEventArgs e) { _inputPane.Hiding += OnKeyboardHiding; _inputPane.Showing += OnKeyboardShowing; } protected override void OnNavigatedFrom(NavigationEventArgs e) { _inputPane.Hiding -= OnKeyboardHiding; _inputPane.Showing -= OnKeyboardShowing; } #endregion Overrides of Page } }
ガイドラインにあるとおり、 InputPane
のイベントで処理を行います。
OnKeyboardShowing
では、元の高さの保存と、キーボード分の高さの調節を行っています。
また、なぜか、 OnKeyboardHiding
が呼ばれずに、再度 OnKeyboardShowing
が
呼ばれることがあったので、一応元の高さを使って計算しています。
OnKeyboardHiding
では、キーボードがない状態へと、要素の高さを復元しています。
上の通り、たまに呼ばれません。イミフです。
これで、タッチキーボードの上に、何らかの要素(今回の場合は、 Footer
) が表示されます。
なお、 CommandBar
を一番下に表示しているなどで、
Root.Height != Window.Current.Bounds.Height
な場合は、
*
が付いてるところで調節を行えば、うまい具合に表示することが可能です。
ということで、ではでは~。(他に実装方法があったら教えて下さい)
*1:ソフトウェアキーボードやスクリーンキーボードともいう