Xamarin AutoComplete Input – Customization

Merhaba,

Bu yazımda geliştirmeye başladığımız AutoComplete Input kontrolünün özelleştirilmesiyle ilgili ihtiyaçlarımızı çıkartıp, kontrolümüze ek özellikler eklemeye çalışacağım.

İhtiyaçlar

  • Sadece List<String> tipinde değil, AutoComplete Input’a istediğim tipte liste gönderebilmeliyim.
  • Aramaya başlamasını istediğim karakterden sonra başlatabilmeliyim.
  • Seçili objenin değerine ulaşabilmeliyim.

Temel ihtiyaç listemizi çıkarttığımıza göre kodlamaya başlayabiliriz 🙂

        public static readonly BindableProperty DataProperty =
            BindableProperty.Create(nameof(Data), typeof(IList), typeof(AutoCompleteEntry),
                null, BindingMode.Default, null, OnDataChanged);

        public IList Data
        {
            get { return (IList)GetValue(DataProperty); }
            set { SetValue(DataProperty, value); }
        }

        static void OnDataChanged(BindableObject bindable, object oldvalue, object newvalue)
        {
            //todo
        }

Hızlı bir refactoring ile IList<String> olan tipimizi IList olarak değiştirdik ve artık istersek IList<String>, IList<Student> veya IList<Product> gönderebiliriz.

OnDataChanged : İhtiyaçlarımıza göre geliştirdiğimiz BindableProperty’lerde herhangi bir property değişikliği yakalayabilmek için eklediğimiz yardımcı static method.

Neden BindableProperty.Create<> kullanmadın? [Obsolete(“Create<> (generic) is obsolete as of version 2.1.0 and is no longer supported.”)]

CreateAttached<> , CreateAttachedReadOnly<> ve CreateReadOnly<> için de geçerli.

 

namespace AutoCompleteSample.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public override string ToString()
        {
            return Name;
        }
    }
}

Product sınıfımızı override etmek zorundayız. Çünkü ArrayAdapter içerisinde kullandığımız ListItem xml’i içerisinde görüntülenecek olan property’i bu şekilde belirleyebiliyoruz.

OnElementChanged methodundaki ArrayAdapter instance’ini da var adapter = new ArrayAdapter(_context, Resource.Layout.ListItem, data); bu şekilde değiştirmemiz

İlk ihtiyacımızı tamamladık 🙂

Kullanmak istediğimiz kontrollerin tüm özelliklerine (property, method, event vs) hakim olamayabiliriz. Bu yüzden ben kontrolleri kullanmadan önce “Go To Definition” (F12) yapar ve kontrol üzerinde neler yapabileceğimi bir incelerim. Sizlere de tavsiyem bu yönde olacaktır. AutoCompleteTextView için de bunu yaptım fakat 2. ihtiyacımızı karşılayacak bir property veya method göremedim. Kesin ben bulamamışımdır diyip, tekrar Android dökümanlarına yöneldim ve tabii ki gözümden kaçırmışım 🙂

The list of suggestions is obtained from a data adapter and appears only after a given number of characters defined by the threshold

Xamarin’in %100 API desteğiyle Threshold propertysini kullanabiliriz.

        public static readonly BindableProperty ThresoldProperty =
            BindableProperty.Create(nameof(Thresold), typeof(int), typeof(AutoCompleteEntry),
                3);

        public int Thresold
        {
            get { return (int)GetValue(ThresoldProperty); }
            set { SetValue(ThresoldProperty, value); }
        }

Default value 3 olarak belirttim.

autoComplete.Threshold = this.Element.Thresold;

AutoCompleteTextView sınıfında dolaşırken ItemClick event’i direkt gözüme çarptı 🙂 ItemClickEventArgs içerisinde istediğim her şey var! o halde kullanalım..

        autoComplete.ItemClick += AutoComplete_ItemClick;

        private void AutoComplete_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
        {
            var selectedItem = e.Parent.GetItemAtPosition(e.Position);
        }

Forms tarafına nasıl taşıyacağız? 3. ihtiyacımızı yapmanın çok yolu var fakat ben Bidable bir Command yazacağım.

        public static readonly BindableProperty SelectedCommandProperty =
        BindableProperty.Create(nameof(SelectedCommand), typeof(ICommand), typeof(AutoCompleteEntry),
            null);

        public ICommand SelectedCommand
        {
            get { return (ICommand)GetValue(SelectedCommandProperty); }
            set { SetValue(SelectedCommandProperty, value); }
        }

            auto.SelectedCommand = new Command((o) =>
            {
                if (o != null && o is Product p)
                {
                    DisplayAlert("Selected Product: ", o.ToString(), "Ok");
                }
            });

Renderer sınıfımızdaki ItemClick event’imizi değiştirelim.

        private void AutoComplete_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
        {
            var selectedItem = e.Parent.GetItemAtPosition(e.Position);
            this.Element.SelectedCommand?.Execute(selectedItem.ToString());
        }

Yiğit ÖZAKSÜT

MVP, MCT, Xamarin Developer, Consultant & Architect

Yorum Gönder