Search code examples
c#xamarin.iosxamarin.androidxamarin.formsxamarin.uwp

Xamarin Forms: custom entry with inline tag support


I'm trying to build a XF app which will allow users to enter text and tag a list of places (similar to how you would tag someone on WhatsApp, Outlook app, or even Twitter's hashtag). I'm still starting out with XF. Could anyone point me in the correct direction? The most I've found is the TagEntryView Plugin, which is great but I need to be able to tag "places" in-line.

Example: I want to see @Paris, @Chennai tomorrow.


Solution

  • I want to provide some ideas about creating such a control by our self with XF, not directly using a third-part lib. (By the way, I don't know any third-party lib which support this function.)

    As we always say: implement a Custom Renderers to use the native controls of the target platform from PCL.

    So here for your request, we can try to customize a Entry.

    In PCL create our entry like this:

    public class TagEntry : Entry
    {
    }
    

    Then, for Android platform:

    [assembly: ExportRenderer(typeof(TagEntry), typeof(TagEntryRenderer))]
    
    namespace YourNameSpace.Droid
    {
        public class TagEntryRenderer : EntryRenderer
        {
            protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
            {
                base.OnElementChanged(e);
    
                if (e.NewElement != null)
                    Control.AfterTextChanged += Control_AfterTextChanged;
    
                if (e.OldElement != null)
                    Control.AfterTextChanged -= Control_AfterTextChanged;
            }
    
            private void Control_AfterTextChanged(object sender, AfterTextChangedEventArgs e)
            {
                //detect if '@' is entered.
                if (e.Editable.LastOrDefault() == '@')
                {
                    //show a popup list for selection.
                    //I here use a simple menu for testing, you should be able to change it to your list popup.
                    PopupMenu popup = new PopupMenu(Xamarin.Forms.Forms.Context, Control);
                    popup.MenuInflater.Inflate(Resource.Menu.testmenu, popup.Menu);
                    popup.Show();
                    popup.MenuItemClick += (ss, ee) =>
                    {
                        var item = ee.Item.TitleFormatted;
                        e.Editable.Delete(e.Editable.Length() - 1, e.Editable.Length());
                        SpannableString spannable = new SpannableString("@" + item);
                        spannable.SetSpan(new ForegroundColorSpan(Android.Graphics.Color.Blue), 0, item.Length() + 1, SpanTypes.ExclusiveExclusive);
                        e.Editable.Append(spannable);
                        popup.Dismiss();
                    };
                }
            }
        }
    }
    

    Rendering image:

    enter image description here

    It's the idea to subscribe the TextChanged event of native control, if you're also interest in the implementation on UWP platform, it's similar, you can give a try. For iOS platform? Sorry, I'm not familiar too...