zoukankan      html  css  js  c++  java
  • Windows 8 键盘上推自定义处理

      在Windows 8 应用程序中,当TextBox控件获得焦点时,输入面板会弹出,如果TextBox控件处于页面下半部分,则系统会将页面上推是的TextBox不被输入面板盖住,但是当TextBox是在FlipView控件中时,系统不会将页面上推,所以这种情况下输入框被输入面板盖住。具体原因不清楚,不知道是不是系统bug。

      当输入面板弹出,页面上推的操作可以通过监听InputPane的Showing和Hiding事件来处理,既然当TextBox在FlipView控件时,系统没有很好的处理页面上推,那么开发者可以通过监听InputPane的事件来自己处理上推操作。

      Windows 8 的一个实例代码Responding to the appearance of the on-screen keyboard sample中介绍了如果监听处理InputPane的相关操作,参考此实例以FlipView中的TextBox控件为例并对实例代码进行简化处理。

      实例中的InputPaneHelper是对InputPane的事件处理的封装,直接拿来使用,InputPaneHelper代码如下:

     1 using System;
     2 using System.Collections.Generic;
     3 using Windows.UI.ViewManagement;
     4 using Windows.UI.Xaml;
     5 using Windows.Foundation;
     6 using Windows.UI.Xaml.Media.Animation;
     7 
     8 namespace HuiZhang212.Keyboard
     9 {
    10     public delegate void InputPaneShowingHandler(object sender, InputPaneVisibilityEventArgs e);
    11     public delegate void InputPaneHidingHandler(InputPane input, InputPaneVisibilityEventArgs e);
    12     public class InputPaneHelper
    13     {
    14         private Dictionary<UIElement, InputPaneShowingHandler> handlerMap;
    15         private UIElement lastFocusedElement = null;
    16         private InputPaneHidingHandler hidingHandlerDelegate = null;
    17 
    18         public InputPaneHelper()
    19         {
    20             handlerMap = new Dictionary<UIElement, InputPaneShowingHandler>();
    21         }
    22 
    23         public void SubscribeToKeyboard(bool subscribe)
    24         {
    25             InputPane input = InputPane.GetForCurrentView();
    26             if (subscribe)
    27             {
    28                 input.Showing += ShowingHandler;
    29                 input.Hiding += HidingHandler;
    30             }
    31             else
    32             {
    33                 input.Showing -= ShowingHandler;
    34                 input.Hiding -= HidingHandler;
    35             }
    36         }
    37 
    38         public void AddShowingHandler(UIElement element, InputPaneShowingHandler handler)
    39         {
    40             if (handlerMap.ContainsKey(element))
    41             {
    42                 throw new System.Exception("A handler is already registered!");
    43             }
    44             else
    45             {
    46                 handlerMap.Add(element, handler);
    47                 element.GotFocus += GotFocusHandler;
    48                 element.LostFocus += LostFocusHandler;
    49             }
    50         }
    51 
    52         private void GotFocusHandler(object sender, RoutedEventArgs e)
    53         {
    54             lastFocusedElement = (UIElement)sender;
    55         }
    56 
    57         private void LostFocusHandler(object sender, RoutedEventArgs e)
    58         {
    59             if (lastFocusedElement == (UIElement)sender)
    60             {
    61                 lastFocusedElement = null;
    62             }
    63         }
    64 
    65         private void ShowingHandler(InputPane sender, InputPaneVisibilityEventArgs e)
    66         {
    67             if (lastFocusedElement != null && handlerMap.Count > 0)
    68             {
    69                 handlerMap[lastFocusedElement](lastFocusedElement, e);
    70             }
    71             lastFocusedElement = null;
    72         }
    73 
    74         private void HidingHandler(InputPane sender, InputPaneVisibilityEventArgs e)
    75         {
    76             if (hidingHandlerDelegate != null)
    77             {
    78                 hidingHandlerDelegate(sender, e);
    79             }
    80             lastFocusedElement = null;
    81         }
    82 
    83         public void SetHidingHandler(InputPaneHidingHandler handler)
    84         {
    85             this.hidingHandlerDelegate = handler;
    86         }
    87 
    88         public void RemoveShowingHandler(UIElement element)
    89         {
    90             handlerMap.Remove(element);
    91             element.GotFocus -= GotFocusHandler;
    92             element.LostFocus -= LostFocusHandler;
    93         }
    94     }
    95 }
    InputPaneHelper

      InputPaneHelper代码比较容易理解,简单的说就是用一个Hash表存储所有需要监听处理键盘上推事件的UIElement(一般情况下应该是TextBox控件),并且通过监听UIElement的焦点事件来判断弹出输入面板是通过那个UIElement触发的,并且通过监听InputPane的Showing和Hiding事件来对键盘上推进行处理。

      测试页面KeyboardPage.xaml代码如下:

     1 <Page
     2     x:Class="HuiZhang212.Keyboard.KeyboardPage"
     3     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     4     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     5     xmlns:local="using:HuiZhang212.Keyboard"
     6     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     7     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     8     mc:Ignorable="d">
     9 
    10     <!--键盘上推和隐藏动画-->
    11     <Page.Resources>
    12         <Storyboard x:Name="MoveMiddleOnShowing">
    13             <DoubleAnimationUsingKeyFrames Duration="0:0:0.733" Storyboard.TargetName="MiddleTranslate" Storyboard.TargetProperty="Y">
    14                 <SplineDoubleKeyFrame x:Name="ShowingMoveSpline" KeyTime="0:0:0.733" KeySpline="0.10,0.90, 0.20,1">
    15                 </SplineDoubleKeyFrame>
    16             </DoubleAnimationUsingKeyFrames>
    17         </Storyboard>
    18 
    19         <Storyboard x:Name="MoveMiddleOnHiding">
    20             <DoubleAnimationUsingKeyFrames Duration="0:0:0.367" Storyboard.TargetName="MiddleTranslate" Storyboard.TargetProperty="Y">
    21                 <SplineDoubleKeyFrame KeyTime="0:0:0.367" KeySpline="0.10,0.90, 0.20,1" Value="0">
    22                 </SplineDoubleKeyFrame>
    23             </DoubleAnimationUsingKeyFrames>
    24         </Storyboard>
    25     </Page.Resources>
    26 
    27     <Grid x:Name="LayoutRoot" Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    28         <Grid.RenderTransform>
    29             <TranslateTransform x:Name="MiddleTranslate" />
    30         </Grid.RenderTransform>
    31         <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    32             <FlipView Margin="100">
    33                 <FlipViewItem Background="Yellow">
    34                     <TextBox  Text="自定义监听键盘上推事件" Name="textbox0"  Foreground="Black" VerticalAlignment="Bottom"  Width="300"/>
    35                 </FlipViewItem>
    36                 <FlipViewItem Background="Blue">
    37                     <TextBox  Text="系统处理键盘上推事件" Name="textbox1"  Foreground="Black" VerticalAlignment="Bottom"  Width="300"/>
    38                 </FlipViewItem>
    39                 <FlipViewItem Background="Green">
    40                     <TextBox  Text="自定义监听键盘上推事件" Name="textbox2" Foreground="Black" VerticalAlignment="Top"  Width="300"/>
    41                 </FlipViewItem>
    42             </FlipView>
    43         </Grid>
    44     </Grid>
    45 </Page>
    KeyboardPage.xaml

      MoveMiddleOnShowing和MoveMiddleOnHiding分别是定义的键盘上推和隐藏时的动画,此动画作用在Grid上,当输入面板显示和隐藏时对Grid做此两种动画偏远而达到键盘上推的效果。

      测试代码KeyboardPage.xaml.cs如下:

     1 using System;
     2 using System.Collections.Generic;
     3 using System.IO;
     4 using System.Linq;
     5 using Windows.Foundation;
     6 using Windows.Foundation.Collections;
     7 using Windows.UI.ViewManagement;
     8 using Windows.UI.Xaml;
     9 using Windows.UI.Xaml.Controls;
    10 using Windows.UI.Xaml.Controls.Primitives;
    11 using Windows.UI.Xaml.Data;
    12 using Windows.UI.Xaml.Input;
    13 using Windows.UI.Xaml.Media;
    14 using Windows.UI.Xaml.Navigation;
    15 
    16 // “空白页”项模板在 http://go.microsoft.com/fwlink/?LinkId=234238 上有介绍
    17 
    18 namespace HuiZhang212.Keyboard
    19 {
    20     /// <summary>
    21     /// 可用于自身或导航至 Frame 内部的空白页。
    22     /// 参考Responding to the appearance of the on-screen keyboard sample
    23     /// FlipView控件中放置的TextBox控件 不会上推
    24     /// </summary>
    25     public sealed partial class KeyboardPage : Page
    26     {
    27         public KeyboardPage()
    28         {
    29             this.InitializeComponent();
    30 
    31             AddInputPanelElement(textbox0);
    32             AddInputPanelElement(textbox2);
    33         }
    34 
    35 
    36         protected override void OnNavigatedFrom(NavigationEventArgs e)
    37         {
    38             RemoveInputPanelElement(textbox0);
    39             RemoveInputPanelElement(textbox2);
    40         }
    41 
    42         #region 键盘上推处理
    43         private double displacement = 0;
    44         private InputPaneHelper inputPaneHelper = new InputPaneHelper();
    45 
    46         public void AddInputPanelElement(FrameworkElement element)
    47         {
    48             inputPaneHelper.SubscribeToKeyboard(true);
    49             inputPaneHelper.AddShowingHandler(element, new InputPaneShowingHandler(CustomKeyboardHandler));
    50             inputPaneHelper.SetHidingHandler(new InputPaneHidingHandler(InputPaneHiding));
    51         }
    52 
    53         public void RemoveInputPanelElement(FrameworkElement element)
    54         {
    55             inputPaneHelper.SubscribeToKeyboard(false);
    56             inputPaneHelper.RemoveShowingHandler(element);
    57             inputPaneHelper.SetHidingHandler(null);
    58         }
    59 
    60         private void CustomKeyboardHandler(object sender, InputPaneVisibilityEventArgs e)
    61         {
    62             // Keep in mind that other elements could be shifting out of your control. The sticky app bar, for example
    63             // will move on its own. You should make sure the input element doesn't get occluded by the bar
    64             FrameworkElement element = sender as FrameworkElement;
    65             Point poppoint = element.TransformToVisual(this).TransformPoint(new Point(0, 0));
    66             displacement = e.OccludedRect.Y - (poppoint.Y + element.ActualHeight + 10);
    67             //bottomOfList = MiddleScroller.VerticalOffset + MiddleScroller.ActualHeight;
    68 
    69 
    70             // Be careful with this property. Once it has been set, the framework will
    71             // do nothing to help you keep the focused element in view.
    72             e.EnsuredFocusedElementInView = true;
    73 
    74             if (displacement > 0)
    75             {
    76                 displacement = 0;
    77             }
    78 
    79             ShowingMoveSpline.Value = displacement;
    80             MoveMiddleOnShowing.Begin();
    81         }
    82 
    83         private void InputPaneHiding(InputPane sender, InputPaneVisibilityEventArgs e)
    84         {
    85             if (displacement != 0.0)
    86             {
    87                 MoveMiddleOnShowing.Stop();
    88 
    89                 if (displacement < 0)
    90                 {
    91                     MoveMiddleOnHiding.Begin();
    92                 }
    93             }
    94         }
    95         #endregion
    96     }
    97 }
    KeyboardPage.xaml.cs

      测试用例中在FlipView的三个item中分别放置一个TextBox,其中textbox0和textbox2是自定义处理键盘上推事件,而textbox1是由系统处理,通过运行程序可以发现textbox1触发弹出键盘不会使页面上推。而textbox0触发弹出键盘有自定义处理,会使页面上推。

  • 相关阅读:
    SQL语句 分页实现
    PHPexcel入门教程
    json_decode返回null,使用echo json_last_error(); 返回4
    配置mysql可局域网内访问
    thinkphp5.0安装composer安装topthink/think-captcha
    linux下mysql忘记密码怎么办
    centos7 设置mysql账号密码开放3306端口实现远程登陆
    高级数据结构第七章A . 数列(树状数组逆序对)
    高级数据结构第六章E . 苹果树 (dfs+树状数组)
    高级数据结构第六章C . 奶牛狂欢节(两个树状数组)
  • 原文地址:https://www.cnblogs.com/huizhang212/p/Win8Keyboard.html
Copyright © 2011-2022 走看看