Windows Phone 虚拟键盘导致页面推动解决

相信几乎所有的Windows Phone开发者都会遇到这种情况:

在页面试用了可输入的控件比如TextBox,当TextBox获取到焦点时,无可厚非虚拟键盘会从屏幕底部滑动出现。有时候就会出现“诡异”的现象(做久一点的WP开发者已经习惯了)—整个页面也会向上推动,导致呢一些控件已经移动出了屏幕的显示边界。这种结果不论是开发者还是用户都会觉得在体验上不是太好。

对于这种情况,通常的做法是压缩TextBox的高度,尽量降低屏幕整体上推的可能性。这样虽然可以通过不断的调整,最终找到一个平衡的高度使页面基本不上推。但总是感觉到受制于人—有输入框页面的设计都要去考虑到这种情况。

为了最终解决此种情况,不得不使用别的小技巧去实现。废话不多说,上码:

using Microsoft.Phone.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;

namespace SinaWeibo.UserControls.CustomPage
{
    /// <summary>
    /// 需要虚拟键盘的页面.避免虚拟键盘出现的时候整个页面向上移动,导致某些区域不在可见区域.
    /// </summary>
    public class SIPPage : PhoneApplicationPage
    {
        private bool isSIPVisibleGuess = false;
        private PhoneApplicationFrame frame;

        public SIPPage()
        {
            BindingSIP();
        }

        private void BindingSIP()
        {
            frame = (App.Current as App).RootFrame;
            Binding yTransfrom = new Binding("Y");
            yTransfrom.Source = (frame.RenderTransform as TransformGroup).Children[0] as TranslateTransform;
            SetBinding(RootFrameTransformProperty, yTransfrom);
        }

        public double RootFrameTransform
        {
            get { return (double)GetValue(RootFrameTransformProperty); }
            set { SetValue(RootFrameTransformProperty, value); }
        }

        // Using a DependencyProperty as the backing store for RootFrameTransform.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty RootFrameTransformProperty =
            DependencyProperty.Register("RootFrameTransform", typeof(double), typeof(SIPPage), new PropertyMetadata(OnRootFrameTransformChanged));

        static void OnRootFrameTransformChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
        {
            double newValue = (double)e.NewValue;
            SIPPage sipView = source as SIPPage;
            if (newValue < 0.0)
            {
                sipView.isSIPVisibleGuess = true;

                if (sipView.frame != null)
                {
                    // 恢复已经移动的距离.
                    var trans = (sipView.frame.RenderTransform as TransformGroup).Children[0] as TranslateTransform;
                    trans.Y += Math.Abs(newValue);
                }
            }
            else if (newValue == 0)
            {
                sipView.isSIPVisibleGuess = false;
            }
#if DEBUG
            else
                System.Diagnostics.Debug.Assert(false, "I assumed this would never happen, let me know if it does");
#endif
        }
    }
}

可以观察得到,我们新建一个页面时。都是继承自PhoneApplicationPage,为了更加通用,这里的SIPPage也继承自PhoneApplicationPage。由于上述情况中,页面发生位置偏移,说明是触发了页面级的TranslateTransform。此段代码中首先是查找到RootFrame的TranslateTransform,并将竖直方向的偏移量绑定到一个自定义的依赖属性上。声明依赖属性的目的也是为了监听到页面界别TranslateTransform在竖直方向的偏移量。在OnRootFrameTransformChanged中就能得知竖直位移量。如果发生了位置移动,仅需此时再把偏移量给抵消掉,页面就不会再发生移动了。一开始的问题也就得到了比较好的解决。

以后只要是有输入框的页面全都继承自SIPPage就行了,记得还要修改Xaml中的页面申明:

<customPage:SIPPage
    x:Class="Any.Do.View.TestAppBar"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:customPage="clr-namespace:Any.Do.CustomPage"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d"
    shell:SystemTray.IsVisible="True">
<!--Xaml goes here-->
</phone:PhoneApplicationPage>

最后,对于此类问题,如果微软能够在系统底层彻底解决或许才是终极解决方案,可是MS的步调去总是那么慢,所以Enjoy this code!

参考文章原文地址:http://blogs.msdn.com/b/jaimer/archive/2010/11/05/guessing-if-the-sip-is-visible-in-a-windows-phone-application.aspx

原文地址:https://www.cnblogs.com/navigator/p/3030089.html