I have a Windows Store app written in C# that has some popups. These are Popup objects that work like modal dialog boxes. Mine are displayed as a band across the middle of the screen.
The standard built-in on-screen keyboard (OSK) handling does not alter the position of popups, only of the regular user interface of the app. I know this because my page, seen behind the popup, moved up when the OSK appears.
A little research led me to various bits of code that add up to handle this quite well. Ok, so I have no idea if this is the best way to do this, but it works.
sealed partial class App : Application
{
public App()
{
this.InitializeComponent();
}
private void _OnInputPaneShowing(InputPane sender, InputPaneVisibilityEventArgs eventArgs)
{
eventArgs.EnsuredFocusedElementInView = false;
FrameworkElement focusedControl = FocusManager.GetFocusedElement() as FrameworkElement;
if( focusedControl != null )
{
GeneralTransform transform = focusedControl.TransformToVisual( null );
Point screenPoint = transform.TransformPoint( new Point( 0, 0 ) );
double Bottom = screenPoint.Y + focusedControl.ActualHeight;
double TopAdjust = Bottom - ( eventArgs.OccludedRect.Top - 20 );
if( TopAdjust >= 0 )
TopAdjust += 20;
else
TopAdjust = 0;
if( TopAdjust > 0 )
{
while( focusedControl.Parent != null && focusedControl.Parent is FrameworkElement )
{
if( focusedControl.Parent is Popup )
{
((UIElement)focusedControl.Parent).RenderTransform = new TranslateTransform() { Y = -TopAdjust };
break;
}
focusedControl = (FrameworkElement)focusedControl.Parent;
}
}
}
}
private void _OnInputPaneHiding(InputPane sender, InputPaneVisibilityEventArgs eventArgs)
{
eventArgs.EnsuredFocusedElementInView = false;
FrameworkElement focusedControl = FocusManager.GetFocusedElement() as FrameworkElement;
if( focusedControl != null )
{
while( focusedControl.Parent != null && focusedControl.Parent is FrameworkElement )
{
if( focusedControl.Parent is Popup )
{
((UIElement)focusedControl.Parent).RenderTransform = new TranslateTransform() { Y = 0 };
break;
}
focusedControl = (FrameworkElement)focusedControl.Parent;
}
}
}
protected override async void OnLaunched(LaunchActivatedEventArgs args)
{
Frame rootFrame = Window.Current.Content as Frame;
// Grab the input pane for the main application window and attach
// touch keyboard event handlers.
InputPane.GetForCurrentView().Showing += new TypedEventHandler<InputPane,InputPaneVisibilityEventArgs>( _OnInputPaneShowing );
InputPane.GetForCurrentView().Hiding += new TypedEventHandler<InputPane,InputPaneVisibilityEventArgs>( _OnInputPaneHiding );
[Remaining code snipped because it is not meaningful]
The first thing to look at is the code at the bottom. I’m not sure yet if I need to deal with any other InputPane besides the one that is returned by GetForCurrentView(). I just don’t know enough about these things yet to be sure, so use this at your own risk.
Anyhow, an event handler is installed for when the OSK appears and disappears. The rest fo the code above that last bit is all the event hander functions. the second one can be ignored because everything in it is explained in the first function.
When the _OnInputPaneShowing() handler is called, I first tell it that I am not handling the adjustments to the UI. This is to keep the normal screen positions working on the normal pages. This is seemingly ignored for popups. I then get the object that has the focus and get the transition from that to the screen. Passing null to TransformToVisual() gets me that transformation. I get a Point for the transformation by calling TransformPoint().
Now that I know where the focus object is on the screen, it is simple to get a distance between the bottom of that and the top of the OSK. if there is overlap then I iterate through the parents of the focus element until I find the popup and I just set an offset transform o the popup to move it up on the screen.
When the OSK is hidden, I set that offset transform Y value to zero to put the popup back into its normal position.
The code above is my first draft. it still has leading underscores that were in some code that I copied. I’ll clean it up a bit later, but it works fine as-is for me.
Since I am always frustrated by people showing code online without showing the namespaces used in that code, here are my "using" statements for the file that contains the code above. These are not all used by this code but at least you should not have to good looking up methods and classes to find the important ones:
using System;
using AirMobility.Common;
using UserControls;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.UI.ApplicationSettings;
using Windows.UI.Core;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
That’s it. now I just need to figure out how to hide that dang keyboard when the popup is closed.
Dave