Skip to content

Commit

Permalink
feat: added inputextensions returntype property (#1128)
Browse files Browse the repository at this point in the history
* feat: added inputextensions returntype property

* chore: refactoring returntype
  • Loading branch information
rajamatt committed May 13, 2024
1 parent 1dd4b2c commit bb68c6a
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 9 deletions.
18 changes: 11 additions & 7 deletions doc/helpers/Input-extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ Provides various attached properties for _input controls_, such as `TextBox` and

## Attached Properties

| Property | Type | Description |
|------------------------|-----------|--------------------------------------------------------------------------------------------|
| `AutoDismiss` | `bool` | Whether the soft-keyboard will be dismissed when the enter key is pressed. |
| `AutoFocusNext` | `bool` | Whether the focus will move to the next focusable element when the enter key is pressed.\* |
| `AutoFocusNextElement` | `Control` | Sets the next control to focus when the enter key is pressed.\* |
| Property | Type | Description |
|------------------------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------|
| `AutoDismiss` | `bool` | Whether the soft keyboard will be dismissed when the enter key is pressed. |
| `AutoFocusNext` | `bool` | Whether the focus will move to the next focusable element when the enter key is pressed.\* |
| `AutoFocusNextElement` | `Control` | Sets the next control to focus when the enter key is pressed.\* |
| `ReturnType` | `ReturnType` | The type of return button on a soft keyboard for Android/iOS. It can be one of the following options: __Default, Done, Go, Next, Search, Send__. |

`AutoFocusNext` and `AutoFocusNextElement`\*: Having either or both of the two properties set will enable the focus next behavior. `AutoFocusNextElement` will take precedences over `AutoFocusNext` when both are set.
`AutoFocusNext` and `AutoFocusNextElement`\*: Having either or both of the two properties set will enable the focus next behavior. `AutoFocusNextElement` will take precedence over `AutoFocusNext` when both are set.

### Remarks

Expand All @@ -35,6 +36,9 @@ xmlns:utu="using:Uno.Toolkit.UI"
<TextBox x:Name="Input3" utu:InputExtensions.AutoFocusNextElement="{Binding ElementName=Input1}" />
<TextBox x:Name="Input4" utu:InputExtensions.AutoFocusNextElement="{Binding ElementName=Input3}" />

<!-- Dismiss soft-keyboard on enter -->
<!-- Dismiss soft keyboard on enter -->
<TextBox utu:InputExtensions.AutoDismiss="True" />

<!-- Soft keyboard with send as return button -->
<TextBox utu:InputExtensions.ReturnType="Send" />
```
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,20 @@
</StackPanel>

<StackPanel Spacing="8">
<TextBlock Text="Dismiss soft-keyboard on enter" />
<TextBlock Text="Dismiss soft keyboard on enter" />
<TextBox utu:InputExtensions.AutoDismiss="True" />
</StackPanel>

<StackPanel Spacing="8">
<TextBlock Text="Soft keyboards of different return types" />
<TextBox Text="Default" utu:InputExtensions.ReturnType="Default" />
<TextBox Text="Done" utu:InputExtensions.ReturnType="Done" />
<TextBox Text="Go" utu:InputExtensions.ReturnType="Go" />
<TextBox Text="Next" utu:InputExtensions.ReturnType="Next" />
<TextBox Text="Search" utu:InputExtensions.ReturnType="Search" />
<TextBox Text="Send" utu:InputExtensions.ReturnType="Send" />
</StackPanel>

</StackPanel>
</DataTemplate>
</sample:SamplePageLayout.DesignAgnosticTemplate>
Expand Down
92 changes: 91 additions & 1 deletion src/Uno.Toolkit.UI/Behaviors/InputExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
using Windows.System;
using Windows.UI.ViewManagement;

#if __ANDROID__
using Android.Views.InputMethods;
#elif __IOS__
using UIKit;
#endif

#if IS_WINUI
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
Expand All @@ -27,10 +33,36 @@ public static class InputExtensions
{
private static readonly ILogger _logger = typeof(InputExtensions).Log();

public enum ReturnType {
Default,
Done,
Go,
Next,
Search,
Send
}

#region DependencyProperty: ReturnType

/// <summary>
/// Backing property for what type of return the soft keyboard will show.
/// </summary>
public static DependencyProperty ReturnTypeProperty { [DynamicDependency(nameof(GetReturnType))] get; } = DependencyProperty.RegisterAttached(
"ReturnType",
typeof(ReturnType),
typeof(InputExtensions),
new PropertyMetadata(ReturnType.Default, OnReturnTypeChanged));

[DynamicDependency(nameof(SetReturnType))]
public static ReturnType GetReturnType(DependencyObject obj) => (ReturnType)obj.GetValue(ReturnTypeProperty);
[DynamicDependency(nameof(GetReturnType))]
public static void SetReturnType(DependencyObject obj, ReturnType value) => obj.SetValue(ReturnTypeProperty, value);

#endregion
#region DependencyProperty: AutoDismiss

/// <summary>
/// Backing property for whether the soft-keyboard will be dismissed when the enter key is pressed.
/// Backing property for whether the soft keyboard will be dismissed when the enter key is pressed.
/// </summary>
public static DependencyProperty AutoDismissProperty { [DynamicDependency(nameof(GetAutoDismiss))] get; } = DependencyProperty.RegisterAttached(
"AutoDismiss",
Expand Down Expand Up @@ -109,6 +141,40 @@ internal static bool IsEnterCommandSupportedFor(DependencyObject host)
return host is TextBox || host is PasswordBox;
}

private static void OnReturnTypeChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if (sender is TextBox || sender is PasswordBox)
{
if (e.NewValue is not ReturnType returnType)
{
returnType = ReturnType.Default;
}
#if __ANDROID__
ImeAction imeAction = GetImeActionFromReturnType(returnType);

if (sender is TextBox textBox)
{
textBox.ImeOptions = imeAction;
}
else if (sender is PasswordBox passwordBox)
{
passwordBox.ImeOptions = imeAction;
}
#elif __IOS__
UIReturnKeyType returnKeyType = GetReturnKeyTypeFromReturnType(returnType);

if (sender is TextBox textBox)
{
textBox.ReturnKeyType = returnKeyType;
}
else if (sender is PasswordBox passwordBox)
{
passwordBox.ReturnKeyType = returnKeyType;
}
#endif
}
}

private static void OnAutoDismissChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) => UpdateSubscription(sender);
private static void OnAutoFocusNextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) => UpdateSubscription(sender);
private static void OnAutoFocusNextElementChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) => UpdateSubscription(sender);
Expand Down Expand Up @@ -177,5 +243,29 @@ private static void OnUIElementKeyUp(object sender, KeyRoutedEventArgs e)
_ => default,
};
}

#if __ANDROID__
private static ImeAction GetImeActionFromReturnType(ReturnType returnType) => returnType switch
{
ReturnType.Next => ImeAction.Next,
ReturnType.Go => ImeAction.Go,
ReturnType.Search => ImeAction.Search,
ReturnType.Send => ImeAction.Send,
ReturnType.Done => ImeAction.Done,
ReturnType.Default or _ => ImeAction.Unspecified
};
#endif

#if __IOS__
private static UIReturnKeyType GetReturnKeyTypeFromReturnType(ReturnType returnType) => returnType switch
{
ReturnType.Next => UIReturnKeyType.Next,
ReturnType.Go => UIReturnKeyType.Go,
ReturnType.Search => UIReturnKeyType.Search,
ReturnType.Send => UIReturnKeyType.Send,
ReturnType.Done => UIReturnKeyType.Done,
ReturnType.Default or _ => UIReturnKeyType.Default
};
#endif
}
}

0 comments on commit bb68c6a

Please sign in to comment.