András Tóth‘s professional blog
banditoth.net

Hey there 👋, I’m banditoth a .NET MAUI developer from Hungary.
I write about software development with .NET technologies.

You can find me on:
LinkedIn | Github | StackOverflow | X / Twitter | Threads

Tag: entry

  • Resizing the screen when an Entry gets focused in .NET MAUI

    This content has 7 months. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

    When an entry field gets focused, the software keyboard appears, potentially covering the entry field. To provide a better user experience, you need to adjust the screen layout so that the entry field remains visible.

    First, create a parent class for your views, deriving from ContentPage, and add a HaveKeyboardOffsetProperty.

    public class ViewBase : ContentPage
    {
        public static readonly BindableProperty HasKeyboardOffsetProperty =
            BindableProperty.Create(nameof(HasKeyboardOffset), typeof(bool), typeof(ViewBase), false);
    
        public bool HasKeyboardOffset
        {
            get => (bool)GetValue(HasKeyboardOffsetProperty);
            set => SetValue(HasKeyboardOffsetProperty, value);
        }
    }
    
    

    iOS Solution:

    Next, create the PageElementMapper class to handle the keyboard appearance and adjust the screen layout.

    public class PageElementMapper
    {
        private static double _contentOriginalHeight;
        private static Thickness _contentOriginalMargin;
    
        public static void Map(IElementHandler handler, IElement view)
        {
            if (view is ViewBase viewData)
            {
                UIKeyboard.Notifications.ObserveWillShow((sender, args) =>
                {
                    if (viewData.HasKeyboardOffset)
                    {
                        _contentOriginalHeight = viewData.Content.Height;
                        _contentOriginalMargin = viewData.Content.Margin;
                        viewData.Content.HeightRequest = _contentOriginalHeight - args.FrameEnd.Height;
                        viewData.Content.Margin = new Thickness(0, args.FrameEnd.Height, 0, 0);
                    }
                });
    
                UIKeyboard.Notifications.ObserveWillHide((sender, args) =>
                {
                    if (viewData.HasKeyboardOffset)
                    {
                        viewData.Content.HeightRequest = _contentOriginalHeight;
                        viewData.Content.Margin = _contentOriginalMargin;
                    }
                });
            }
        }
    }
    
    

    Finally, register the mapper in the MauiProgram.cs file.

    public static class MauiProgram
    {
        public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiApp<App>()
                .ConfigureMauiHandlers(handlers =>
                {
                    Microsoft.Maui.Handlers.PageHandler.ElementMapper.AppendToMapping("KeyboardOffset", (handler, view) =>
                    {
                        if (view is ViewBase)
                        {
    #if IOS
                            PageElementMapper.Map(handler, view);
    #endif
                        }
                    });
                });
    
            return builder.Build();
        }
    }
    
    

    Android solution:

    On Android, you can use a PropertyChanged method of the HasKeyboardOffset:

        private static void OnHasKeyboardOffsetPropertyChanged(BindableObject bindable, object oldValue, object newValue)
        {
    #if ANDROID
            if (bindable is ViewBase view)
            {
                if (newValue is bool hasOffset)
                    if (hasOffset == true)
                        Microsoft.Maui.Controls.Application.Current.Dispatcher.Dispatch(() =>
                        {
                            Platform.CurrentActivity?.Window?.SetSoftInputMode(Android.Views.SoftInput.AdjustResize);
                        });
                    else
                        Microsoft.Maui.Controls.Application.Current.Dispatcher.Dispatch(() =>
                        {
                            Platform.CurrentActivity?.Window?.SetSoftInputMode(Android.Views.SoftInput.StateUnspecified);
                        });
            }
    #endif
        }
    

    Remarks

    The provided solution offers a way to manage this in .NET MAUI on iOS. However, always be open to improvements and share your solutions with the community for better practices. This might not be the best solution to do it.

  • Xamarin.Forms : Focus to the entry and set the cursor after the last character

    This content has 3 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

    If you want to make the cursor in Xamarin.Forms Entry blink behind the text you have already typed, instead of in front of it, after focusing, you need to do the following:

    Subscribe to the Focused event of the Entry and modify the eventhandler as follows:

    		public void OnEntryFocused(object sender, EventArgs args)
    		{
    			EntryInstance.CursorPosition = EntryInstance?.Text?.Length ?? 0;
    		}
    

    You can find more information about the CursorPosition at: https://docs.microsoft.com/en-us/dotnet/api/xamarin.forms.entry.cursorposition?view=xamarin-forms

  • Xamarin Forms / Android: Backspace detektálása az Entrykben

    This content has 5 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

    Ahhoz, hogy a szoftveres / hardveres billentyűzeten ütött vissza gomb érzékelését detektáljuk a billentyűzeten, szükségünk lesz egy CustomRenderer-re, ahhoz pedig egy Entry száramaztatáshoz a közös kódban:

    public class CustomEntry: Entry
    {
        public delegate void BackspaceEventHandler(object sender, EventArgs e);
    
        public event BackspaceEventHandler OnBackspace;
    
        public CustomEntry() { }
    
        public void OnBackspacePressed() 
        {
            if (OnBackspace != null)
            {
                OnBackspace(null, null);
            }
        }
    }
    

    Két CustomRenderer megoldás is van Androidon. Az egyik, amelyik magát a Renderert egy InputFilter implementációvá teszi, a másik, amely egy csak egy metódust overrideol. A különbség köztük, hogy a DispatchKeyEvent override az üres entry esetén is továbbítja az eventet, míg az inputfiilter csak akkor érzékeli a visszatörlés gombnyomást, ha volt már szöveg benne.

    DispatchKeyEvent override megoldás

    public class CustomEntryRenderer: EntryRenderer
     {
        public override bool DispatchKeyEvent(KeyEvent e)
        {
            if (e.Action == KeyEventActions.Down)
            {
                if (e.KeyCode == Keycode.Del)
                {
                    if (string.IsNullOrWhiteSpace(Control.Text))
                    {
                        var entry = (PasswordBox)Element;
                        entry.OnBackspacePressed();
                    }
                }
            }
            return base.DispatchKeyEvent(e);
        }
    
        protected override void 
        OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);
        }
    }
    

    InputFilter implementáció

    [assembly: ExportRenderer(typeof(CustomEntry), typeof(CustomEntryRenderer))]
    namespace App.Droid.Renderers
    {
        public class CustomEntryRenderer: EntryRenderer, Android.Text.IInputFilter
        {
            protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
            {
                base.OnElementChanged(e);
    
                if (Control == null) 
                {
                    return;
                }
    
                Control.SetFilters(new IInputFilter[] { this });
    
            }
    
            ICharSequence IInputFilter.FilterFormatted(ICharSequence source, int start, int end, ISpanned dest, int dstart, int dend)
            {
                if (string.IsNullOrWhiteSpace(source.ToString()))
                {
                    var entry = (CustomEntry)Element;
                    entry.OnBackspacePressed();
                }
                return source;
            }
    
        }
    }
    
  • Xamarin iOS: Entry Unfocus event nem triggerelődik, ListView-el.

    This content has 5 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

    Ha egy Entry épp focus alatt van, és úgy választunk egy listaelemet a ListView-ből, az Entry Unfocus eventje nem fog triggerelődni. Ez azért van, mert a ListView a Touch eseményt ilyenkor elnyeli. Az én esetemben a megoldás ListView mögött egy háttérszínnel rendelkező grid volt, ami képes touch eventeket elkapni. A ListView InputTransparent tulajdonságának True-ra állításával ez a probléma megoldódott, mert az alatta lévő grid fókuszt kapott, és “mintha kikattintottunk volna” a gridből, az entry focusa megszűnt.

            <ListView
                x:Name="list"
                BackgroundColor="#393939"
                ItemTapped="list_ItemTapped"
    
                InputTransparent="True"
    
                ItemsSource="{Binding Path=AutoCompleteItems, Source={x:Reference UserControl}}"
                SelectedItem="{Binding Path=SelectedAddress, Source={x:Reference UserControl}}"
                SeparatorVisibility="None">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <usercontrols:AddressSelectorAutoCompleteItemDataTemplate />
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
    

    Próbáltam a ListView ItemSelectedjében unfocusolni az Entry Controlokat, azonban ez nem hozott sikert.

  • Xamarin Android: TextView / Entry padding eltávolítása

    This content has 5 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

    Ha az iOS Entry láthatólag nem tartalmaz margót vagy paddingot, de Androidon máshogy renderelődik ki, akkor gyanakodhatunk arra, hogy valahol nem állítottunk a Xamarin.Forms kódban margót/paddingot nullára. Azonban a Forms Paddingjával és Marginjával nem állítható az androidos TextView paddingja, ehhez customrenderer-re lesz szükség.

    [assembly: ExportRenderer(typeof(CustomEntry), typeof(CustomEntry Renderer))]
    namespace banditoth.Droid.Renderers
    {
        public class CustomEntryRenderer : EntryRenderer
        {
            protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
            {
                base.OnElementChanged(e);
    
                if (Control != null)
                {
                    // Eltávolítjuk a paddingot.
                    Control.SetPadding(0, 0, 0, 0);
                }
            }
        }
    }
    

    A Control.SetPaddinggal Custom értékeket állíthatunk be a natív TextView paddingjának. Nekem most az eltávolításra volt szükségem, ezért kinulláztam.