Skip to content

Commit

Permalink
Merge pull request #6 from starkos/fix-autofocus
Browse files Browse the repository at this point in the history
Fix page transition hitches when setting focus with AutoFocusBehavior
  • Loading branch information
starkos authored Dec 1, 2019
2 parents 53464e1 + af1ebf2 commit a03d452
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 14 deletions.
37 changes: 24 additions & 13 deletions Industrious.Forms/AutoFocusBehavior.cs
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
using System;
using System.Threading.Tasks;
using System.ComponentModel;
using Xamarin.Forms;

namespace Industrious.Forms
{
/// <summary>
/// Automatically set the input focus when a condition becomes true.
/// An <see cref="https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/behaviors/attached">
/// attached behavior</see> which automatically set the input focus to a view when the provided condition
/// becomes true.
/// </summary>
/// <example>
/// Sets the focus to attached <see cref="Entry"/> when the binding condition
/// resolves to <c>true</c>.
/// Sets the focus to attached <see cref="Entry"/> when the binding condition resolves to <c>true</c>.
/// <code>
/// &lt;Entry
/// Text="{Binding Title}"
/// local:AutoFocusBehavior.FocusWhen="{Binding ShouldFocusTitle}" /&gt;
/// forms:AutoFocusBehavior.FocusWhen="{Binding ShouldFocusTitle}" /&gt;
/// </code>
/// </example>
/// <example>
/// To set the focus automatically when the form is loaded, set <c>When</c>
/// to <c>true</c>.
/// To set the focus automatically when the form is loaded, set <c>When</c> to <c>true</c>.
/// <code>
/// &lt;Entry
/// Text="{Binding Title}"
/// local:AutoFocusBehavior.FocusWhen="True" /&gt;
/// forms:AutoFocusBehavior.FocusWhen="True" /&gt;
/// </code>
/// </example>
public class AutoFocusBehavior : Behavior<InputView>
public static class AutoFocusBehavior
{
public static readonly BindableProperty FocusWhenProperty = BindableProperty.CreateAttached(
"FocusWhen",
Expand All @@ -41,6 +41,7 @@ public static Boolean GetFocusWhen(BindableObject bindable)
return (value);
}


public static void SetFocusWhen(BindableObject bindable, Boolean value)
{
bindable.SetValue(FocusWhenProperty, value);
Expand All @@ -51,15 +52,25 @@ private static void OnFocusWhenChanged(BindableObject bindable, Object oldValue,
{
if ((Boolean)newValue)
{
_ = SetFocus((InputView)bindable);
// if view is visible, set focus, else wait until it is
var view = (View)bindable;
if (view.Width >= 0)
view.Focus();
else
view.PropertyChanged += OnViewPropertyChanged;
}
}


private static async Task SetFocus(InputView bindable)
private static void OnViewPropertyChanged(Object sender, PropertyChangedEventArgs e)
{
await Task.Delay(1); // control isn't ready to receive focus when first attached
bindable.Focus();
if (e.PropertyName == "Renderer")
{
// view is now visible enough, go ahead and set focus
var view = (View)sender;
view.PropertyChanged -= OnViewPropertyChanged;
view.Focus();
}
}
}
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ See [Industrious.ToDo](https://github.com/industrious/industrious-todo) for usag

### AutoFocusBehavior

Automatically set the input focus to a particular control when a condition becomes true.
Automatically set the input focus to a particular view when a condition becomes true.

```xml
<?xml version="1.0" encoding="UTF-8"?>
Expand Down

0 comments on commit a03d452

Please sign in to comment.