Entrada de texto con la vista de escritura a mano

Nota:

La vista de escritura a mano no es compatible con los controles de texto del SDK de aplicaciones para Windows. En este artículo solo se hace referencia a las aplicaciones para UWP.

El cuadro de texto se amplía cuando se pulsa con el lápiz

Personalice la vista de escritura a mano (para la Entrada de lápiz a texto en texto) que está integrada en los controles de entrada de texto UWP, como TextBox, RichEditBox y AutoSuggestBox.

Información general

Los controles de entrada de texto UWP admiten la entrada manuscrita mediante Windows Ink transformándose en una superficie de escritura a mano cuando un usuario pulsa en un cuadro de entrada de texto con un lápiz.

El texto se reconoce a medida que el usuario escribe en cualquier lugar de la superficie de escritura a mano mientras una ventana alternativa muestra los resultados del reconocimiento. El usuario puede pulsar un resultado para elegirlo o seguir escribiendo para aceptar al candidato propuesto. Los resultados del reconocimiento literal (letra por letra) se incluyen en la ventana de candidatos, por lo que el reconocimiento no se restringe a las palabras de un diccionario. Conforme el usuario escribe, la entrada de texto aceptada se convierte en una fuente de script que se parece mucho a la escritura natural.

Nota:

La vista de escritura a mano está habilitada de forma predeterminada, pero puede deshabilitarla por control y volver al panel de entrada de texto en su lugar.

Cuadro de texto con entrada de lápiz y sugerencias

Un usuario puede editar su texto con gestos y acciones estándar:

  • strike through o scratch out: dibujar atravesando una palabra o parte de ella para eliminarla
  • join: dibujar un arco entre las palabras para eliminar el espacio entre ellas
  • insert: dibujar un símbolo de intercalación para insertar un espacio
  • overwrite: escribir sobre texto existente para sustituirlo

Cuadro de texto con corrección de entrada de lápiz

Deshabilitar la vista de escritura a mano

La vista integrada de escritura a mano está habilitada de forma predeterminada.

Es posible que quieras deshabilitar la vista de escritura a mano si ya ofreces una funcionalidad equivalente de entrada de lápiz a texto en la aplicación o tu experiencia de entrada de texto se basa en algún tipo de formato o carácter especial (por ejemplo, un tabulador) no disponible a través de la escritura a mano.

En este ejemplo, desactivamos la vista de escritura a mano al establecer la propiedad IsHandwritingViewEnabled del control TextBox a falso. Todos los controles de texto que admiten la vista de escritura a mano admiten una propiedad similar. ​

<TextBox Name="SampleTextBox"​
    Height="50" Width="500" ​
    FontSize="36" FontFamily="Segoe UI" ​
    PlaceholderText="Try taping with your pen" ​
    IsHandwritingViewEnabled="False">​
</TextBox>​

Especificar la alineación de la vista de escritura a mano

La vista de escritura a mano se sitúa sobre el control de texto subyacente y su tamaño se adapta a las preferencias de escritura a mano del usuario (consulte Configuración -> Bluetooth y dispositivos -> Lápiz y Windows Ink -> Escritura a mano -> Tamaño de fuente). La vista también se alinea automáticamente en relación con el control de texto y su ubicación dentro de la aplicación.

La UI de la aplicación no se reajusta para acomodar el control más grande, que podría ocluir UI importante.

En el fragmento de código siguiente se muestra cómo usar la propiedad PlacementAlignment de un control HandwritingView de TextBox para especificar qué delimitador del control de texto subyacente se usa para alinear la vista de escritura a mano. ​

<TextBox Name="SampleTextBox"​
    Height="50" Width="500" ​
    FontSize="36" FontFamily="Segoe UI" ​
    PlaceholderText="Try taping with your pen">​
        <TextBox.HandwritingView>​
            <HandwritingView PlacementAlignment="TopLeft"/>​
        </TextBox.HandwritingView>​
</TextBox>​

Deshabilitar los candidatos de finalización automática

La ventana emergente de sugerencia de texto está habilitada de manera predeterminada. Proporciona una lista de los principales candidatos de reconocimiento de entrada de lápiz entre los que el usuario puede seleccionar en caso de que el candidato principal sea incorrecto.

Si la aplicación ya proporciona una funcionalidad de reconocimiento sólida y personalizada, puede usar la propiedad AreCandidatesEnabled para deshabilitar las sugerencias incorporadas, como se muestra en el siguiente ejemplo.

<TextBox Name="SampleTextBox"​
    Height="50" Width="500" ​
    FontSize="36" FontFamily="Segoe UI" ​
    PlaceholderText="Try taping with your pen">​
        <TextBox.HandwritingView>​
            <HandwritingView AreCandidatesEnabled="False"/>​
        </TextBox.HandwritingView>​
</TextBox>

Usar las preferencias de fuente de escritura a mano

Un usuario puede elegir entre una colección predefinida de fuentes basadas en la escritura a mano para usar cuando renderiza texto basado en el reconocimiento de entrada de lápiz (consulte Configuración -> Bluetooth y dispositivos -> Lápiz y Windows Ink -> Escritura a mano -> Tipo de letra).

La aplicación puede acceder a esta opción y usar la fuente seleccionada para el texto reconocido en el control de texto.

En este ejemplo, escuchamos el evento TextChanged de un TextBox y aplicamos el tipo de letra seleccionado por el usuario si el cambio de texto se originó en la HandwritingView (o una fuente predeterminada, si no). ​

private void SampleTextBox_TextChanged(object sender, TextChangedEventArgs e)​
{​
    ((TextBox)sender).FontFamily = 
        ((TextBox)sender).HandwritingView.IsOpen ?
            new FontFamily(PenAndInkSettings.GetDefault().FontFamilyName) : 
            new FontFamily("Segoe UI");​
}​

Acceder al control HandwritingView en controles compuestos

Los controles compuestos que usan el control TextBox o RichEditBox (como AutoSuggestBox), también admiten una HandwritingView.

Para acceder al control HandwritingView de un control compuesto, usa la VisualTreeHelper API.

El fragmento de código XAML siguiente muestra un control AutoSuggestBox.

<AutoSuggestBox Name="SampleAutoSuggestBox"​ 
    Height="50" Width="500"​ 
    PlaceholderText="Auto Suggest Example"​ 
    FontSize="16" FontFamily="Segoe UI" ​ 
    Loaded="SampleAutoSuggestBox_Loaded">​
</AutoSuggestBox>​

En el correspondiente código subyacente, se muestra cómo deshabilitar HandwritingView en el control compuesto AutoSuggestBox.

  1. Primero, manejamos el evento Loaded del elemento y llamamos a la función FindInnerTextBoxpara iniciar el recorrido de árbol visual.

    private void SampleAutoSuggestBox_Loaded(object sender, RoutedEventArgs e)​
    {​
        if (FindInnerTextBox((AutoSuggestBox)sender))​
            autoSuggestInnerTextBox.IsHandwritingViewEnabled = false;​
    }​
    
  2. En la función FindInnerTextBox, iteramos a través del árbol visual (comenzando en un AutoSuggestBox) llamando a una función FindVisualChildByName.

    private bool FindInnerTextBox(AutoSuggestBox autoSuggestBox)​
    {​
        if (autoSuggestInnerTextBox == null)​
        {​
            // Cache textbox to avoid multiple tree traversals. ​
            autoSuggestInnerTextBox = 
                (TextBox)FindVisualChildByName<TextBox>(autoSuggestBox);​
        }​
        return (autoSuggestInnerTextBox != null);​
    }​
    ​```
    
    
  3. Finalmente, la función FindVisualChildByName itera a través del árbol visual hasta recuperar el TextBox.

    private FrameworkElement FindVisualChildByName<T>(DependencyObject obj)​
    {​
        FrameworkElement element = null;​
        int childrenCount = 
            VisualTreeHelper.GetChildrenCount(obj);​
        for (int i = 0; (i < childrenCount) && (element == null); i++)​
        {​
            FrameworkElement child = 
                (FrameworkElement)VisualTreeHelper.GetChild(obj, i);​
            if ((child.GetType()).Equals(typeof(T)) || (child.GetType().GetTypeInfo().IsSubclassOf(typeof(T))))​
            {​
                element = child;​
            }​
            else​
            {​
                element = FindVisualChildByName<T>(child);​
            }​
        }​
        return (element);​
    }​
    ​```
    
    

Cambiar la posición del control HandwritingView

En algunos casos, puede que debas asegurarte de que el HandwritingView abarque elementos de la interfaz de usuario que, de lo contrario, tal vez no incluiría.

En este caso, se crea un TextBox que admite el dictado (que se implementa colocando un TextBox y un botón de dictado en un StackPanel).

Captura de pantalla de un TextBox que admite dictado.

Como el StackPanel es ahora más grande que el TextBox, el HandwritingView podría no ocluir todo el control compuesto.

Captura de pantalla de un control HandwritingView que obstruye parcialmente un TextBox, y otro que se reposiciona para ocluir completamente el TextBox.

Para solucionar este problema, establece la propiedad PlacementTarget del HandwritingView en el elemento de la interfaz de usuario con el que se debe alinear.

<StackPanel Name="DictationBox" 
    Orientation="Horizontal" ​
    VerticalAlignment="Top" 
    HorizontalAlignment="Left" ​
    BorderThickness="1" BorderBrush="DarkGray" ​
    Height="55" Width="500" Margin="50">​
    <TextBox Name="DictationTextBox" 
        Width="450" BorderThickness="0" ​
        FontSize="24" VerticalAlignment="Center">​
        <TextBox.HandwritingView>​
            <HandwritingView PlacementTarget="{Binding ElementName=DictationBox}"/>​
        </TextBox.HandwritingView>​
    </TextBox>​
    <Button Name="DictationButton" 
        Height="48" Width="48" 
        FontSize="24" ​
        FontFamily="Segoe MDL2 Assets" 
        Content="&#xE720;" ​
        Background="White" Foreground="DarkGray" ​    Tapped="DictationButton_Tapped" />​
</StackPanel>​

Cambiar el tamaño del control HandwritingView

También puedes establecer el tamaño del HandwritingView, lo que puede resultar útil cuando tengas que asegurarte de que la vista no obstruye una interfaz de usuario importante.

En este caso, se crea un TextBox que admite el dictado (que se implementa colocando un TextBox y un botón de dictado en un StackPanel).

Captura de pantalla de un TextBox que admite dictado.

En este caso, queremos asegurarnos cambiar el tamaño de HandwritingView para asegurar que el botón de dictado esté visible.

Captura de pantalla de un control HandwritingView que obstruye el botón dictado, y otro cuyo tamaño se cambia para asegurar que el botón de dictado esté visible.

Para ello, enlazamos la propiedad MaxWidth del HandwritingView al ancho del elemento de interfaz de usuario que debe obstruir.

<StackPanel Name="DictationBox" 
    Orientation="Horizontal" ​
    VerticalAlignment="Top" 
    HorizontalAlignment="Left" ​
    BorderThickness="1" 
    BorderBrush="DarkGray" ​
    Height="55" Width="500" 
    Margin="50">​
    <TextBox Name="DictationTextBox" 
        Width="450" 
        BorderThickness="0" ​
        FontSize="24" 
        VerticalAlignment="Center">​
        <TextBox.HandwritingView>​
            <HandwritingView 
                PlacementTarget="{Binding ElementName=DictationBox}"​
                MaxWidth="{Binding ElementName=DictationTextBox, Path=Width"/>​
        </TextBox.HandwritingView>​
    </TextBox>​
    <Button Name="DictationButton" 
        Height="48" Width="48" 
        FontSize="24" ​
        FontFamily="Segoe MDL2 Assets" 
        Content="&#xE720;" ​
        Background="White" Foreground="DarkGray" ​
        Tapped="DictationButton_Tapped" />​
</StackPanel>​

Cambiar la posición de la UI personalizada

Si tienes una interfaz de usuario personalizada que aparece en respuesta a la entrada de texto, como un elemento emergente informativo, has de cambiar la posición de esa interfaz de usuario para que no obstruya la vista de escritura a mano.

TextBox con interfaz de usuario personalizada

El siguiente ejemplo muestra cómo escuchar los eventos Opened, Closed y SizeChanged del HandwritingView para establecer la posición de un Popup.

private void Search_HandwritingViewOpened(
    HandwritingView sender, HandwritingPanelOpenedEventArgs args)​
{​
    UpdatePopupPositionForHandwritingView();​
}​
​
private void Search_HandwritingViewClosed(
    HandwritingView sender, HandwritingPanelClosedEventArgs args)​
{​
    UpdatePopupPositionForHandwritingView();​
}​
​
private void Search_HandwritingViewSizeChanged(
    object sender, SizeChangedEventArgs e)​
{​
    UpdatePopupPositionForHandwritingView();​
}​
​
private void UpdatePopupPositionForHandwritingView()​
{​
if (CustomSuggestionUI.IsOpen)​
    CustomSuggestionUI.VerticalOffset = GetPopupVerticalOffset();​
}​
​
private double GetPopupVerticalOffset()​
{​
    if (SearchTextBox.HandwritingView.IsOpen)​
        return (SearchTextBox.Margin.Top + SearchTextBox.HandwritingView.ActualHeight);​
    else​
        return (SearchTextBox.Margin.Top + SearchTextBox.ActualHeight);​    ​
}​

Volver a planificar el control HandwritingView

Como con todos los controles del marco de trabajo XAML, puedes personalizar la estructura visual y el comportamiento visual de un HandwritingView para tus requisitos específicos.

Para ver un ejemplo completo de la creación de una plantilla personalizada, consulte la guía Crear controles de transporte personalizados o el ejemplo Control de edición personalizado. ​ ​ ​ ​ ​ ​ ​ ​