0

Fair warning: I am new to Android, Xamarin Forms and MVVM (though I am a seasoned desktop Windows application developer). And though I have used SO as a valuable resource for years, this is my first posted question. So I know I have a lot to learn, and I would appreciate any feedback.

For my project, I need a read-only multi-line text view (Xamarin Editor) that offers selectable text. Poking around SO and other places, I saw how to implement a custom Editor Renderer. This was pretty straight forward and seems to work well:

  • a keyboard is not displayed when the Editor is focused
  • the user can select and copy text
  • the context menu (displayed when text is selected) contains only Copy and Select All

Most of the code below was taken from a medium.com post: https://medium.com/@anna.domashych/selectable-read-only-multiline-text-field-on-android-169c27c55408 (thank you Anna!)

Working in VS 2019, my shared project has a simple class derived from Editor, which is named SelectableLabel.

namespace RO_Editor
{

    public class SelectableLabel : Editor
    {
    }

}

The Android project has the custom renderer:

[assembly: ExportRenderer(typeof(SelectableLabel), typeof(SelectableLabelRenderer))]

namespace RO_Editor
{
    class SelectableLabelRenderer : EditorRenderer
    {
        public SelectableLabelRenderer(Context context) : base(context)
        {
        }


        protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
        {
            base.OnElementChanged(e);

            if (Control == null)
                return;

            Control.Background = null;
            Control.SetPadding(0, 0, 0, 0);
            Control.ShowSoftInputOnFocus = false;
            Control.SetTextIsSelectable(true);
            Control.CustomSelectionActionModeCallback = new CustomSelectionActionModeCallback();
            Control.CustomInsertionActionModeCallback = new CustomInsertionActionModeCallback();
        }

        private class CustomInsertionActionModeCallback : Java.Lang.Object, ActionMode.ICallback
        {
            public bool OnCreateActionMode(ActionMode mode, IMenu menu) => false;

            public bool OnActionItemClicked(ActionMode m, IMenuItem i) => false;

            public bool OnPrepareActionMode(ActionMode mode, IMenu menu) => true;

            public void OnDestroyActionMode(ActionMode mode) { }
        }

        private class CustomSelectionActionModeCallback : Java.Lang.Object, ActionMode.ICallback
        {
            private const int CopyId = Android.Resource.Id.Copy;
            private const int SelAllId = Android.Resource.Id.SelectAll;

            public bool OnActionItemClicked(ActionMode m, IMenuItem i) => false;

            public bool OnCreateActionMode(ActionMode mode, IMenu menu) => true;

            public void OnDestroyActionMode(ActionMode mode) { }

            public bool OnPrepareActionMode(ActionMode mode, IMenu menu)
            {
                try
                {
                    IMenuItem copyItem = menu.FindItem(CopyId);
                    var title = copyItem.TitleFormatted;

                    IMenuItem selAllItem = menu.FindItem(SelAllId);
                    var selAllTitle = selAllItem.TitleFormatted;

                    menu.Clear();
                    menu.Add(0, CopyId, 0, title);
                    menu.Add(0, SelAllId, 1, selAllTitle);
                }
                catch
                {
                    // ignored
                }

                return true;
            }
        }
    }
}

 

That's what I'm working with thus far. My next task is to offer a search function. That is, allow the user to specify a search string (via SearchBar) and to programmatically find the search string in the SelectableLabel text, and to select the search hits in the SelectableLabel view.

The Xamarin Editor maps to a native Android TextEdit view. TextEdit has a SetSelection() method, and I'd like to expose this method in my SelectableLabel control. What is a generally accepted way to do this?

Blaise
  • 21
  • 7
  • How do you want to aplit the strings? Using the space in Editor? – Wendy Zang - MSFT Jun 26 '20 at 09:36
  • Thanks @Wendy. I have no intention to split strings ... Sorry, I must have been unclear. I will present a varying amount of multi-line text in a derived Editor (SelectableLabel) - often several paragraphs. I want to be able to search that text for a user specified string, and then select the text found in the SelectableLabel. So I need to programmatically select the found text. Bottom line, I want to expose the SetSelection() method in the native Android control (TextEdit) in my SelectableLabel control. The question is, what's the best way to do that? – Blaise Jun 26 '20 at 16:13
  • You could try to split the works in a string and then use the searchbar to search the works. And then select the wrok with background color. – Wendy Zang - MSFT Jun 29 '20 at 07:11

0 Answers0