Monday 15 August 2016

How to dismiss keyboard with cancellation token after certain duration

Mobile: How to dismiss keyboard with cancellation token after certain duration

The concept is very simple:
I started with static variable: CancellationTokenSource.
Instantiate the variable outside the 'TextChanged' event.
Within the 'text changed' event,  cancel the token every time when user enter a text.
Reinitialise the cancellationTokenSource, because you need it for the delay task, a task to dismiss the keyboard.


Before that, I have a custom search view, which is a view that consists of an entry field with a magnifying glass, plus a binding to activity indicator (loading spinner).

Instead of using the normal element 'entry',  I have a custom element here:
public class SearchEntry : Entry {}

And, here is my custom search view:
public class SearchView : StackLayout
    {
        public event EventHandler<TextChangedEventArgs> TextChanged;

        public static readonly BindableProperty IndicatorRunningProperty =
            BindableProperty.Create("IndicatorRunning", typeof(bool), typeof(SearchView), false);

        public bool IndicatorRunning
        {
            get { return (bool)GetValue(IndicatorRunningProperty); }
            set { SetValue(IndicatorRunningProperty, value); }
        }

        private ActivityIndicator indicator;
        public Entry entry;

        public new event EventHandler<FocusEventArgs> Focused;
        public new event EventHandler<FocusEventArgs> Unfocused;

        public SearchView() {
            entry = new SearchEntry () {
                HorizontalOptions = LayoutOptions.FillAndExpand,
                VerticalOptions = LayoutOptions.Center,
                BackgroundColor = Color.White,
                Placeholder = string.Format ("Search for someone"),
            };
            entry.TextChanged += (object sender, TextChangedEventArgs e) => {
                if (TextChanged != null) {
                    TextChanged (this, e);
                }
            };
            entry.Focused += (object sender, FocusEventArgs e) => {
                if(Focused != null) {
                    Focused(this, e);
                }
            };
            entry.Unfocused += (object sender, FocusEventArgs e) => {
                if(Unfocused != null) {
                    Unfocused(this, e);
                }
            };
            indicator = new ActivityIndicator () {
                WidthRequest = 27,
                HeightRequest = 27,
                VerticalOptions = LayoutOptions.CenterAndExpand,
            };
            indicator.SetBinding (ActivityIndicator.IsRunningProperty, new Binding("IndicatorRunning", BindingMode.TwoWay,source:this));


            var image = new Image () {
                Source = "ic_search.png",
                HeightRequest = 24,
                WidthRequest = 24
            };
            var searchEntryStack = new RoundedStackLayout () {
                BackgroundColor = Color.White,
                CornerRadius = 5f,
                HeightRequest = 27,
                HorizontalOptions = LayoutOptions.FillAndExpand,
                Orientation = StackOrientation.Horizontal,
                Padding = new Thickness (10, 0, 10, 0),
                Spacing = Device.OnPlatform (10, 0, 0),
                Children = { image, entry, indicator }
            };
            HorizontalOptions = LayoutOptions.FillAndExpand;
            BackgroundColor = StyleHelpers.NavigationPageBgColor;
            Padding = new Thickness (20, 10, 20, 10);
            Spacing = 0;
            HeightRequest = 47;
            Orientation = StackOrientation.Horizontal;
            Children.Add (searchEntryStack);
        }

        new public void Unfocus() {
            entry.Unfocus ();
        }

        public void Clear() {
            entry.Text = string.Empty;
        }
    }
 



Cool, over here is the core of how to use the token cancellation source to dismiss keyboard after certain interval or duration:

Declare a static variable first:
public static CancellationTokenSource tokenSource;


tokenSource = new CancellationTokenSource();
            searchView.TextChanged += (sender, e) => {    

                //Do something here....                 //Everytime when user press, then cancel the token. Then Re-init the token. 
                //Create a task that will complete after time delay with the cancellation token.
                tokenSource.Cancel();
                tokenSource = new CancellationTokenSource();
                var unfocusTask = Task.Delay(3000, tokenSource.Token);
                unfocusTask.ContinueWith(t=>{
                    if (!t.IsCanceled){
                        Device.BeginInvokeOnMainThread(()=>{
                        searchView.Unfocus();
                        });
                    }
                });
            };

How to run unit test for your Xamarin Application in AppCenter?

How to run unit test for your Xamarin application in AppCenter?  When we talk about Building and Distributing your Xamarin app, you m...