Android Tutorial Custom Context Menu for Text Selection

Discussion in 'Tutorials & Examples' started by Erel, Jul 13, 2017.

  1. Erel

    Erel Administrator Staff Member Licensed User

    [​IMG]

    This example uses inline Java with JavaObject to allow creating custom context menus when the user selects text.

    To use it in your project you need to add the inline Java code and implement this method:
    Code:
    Sub ContextMenu_Create(ActionMode As JavaObject, FocusedView As View)
       
    Dim menu As JavaObject = ActionMode.RunMethod("getMenu"Null)
       
    menu.RunMethod("clear"Null)
       
    Dim event As Object = menu.CreateEvent("android.view.MenuItem.OnMenuItemClickListener""ContextMenuClick"True)
       
       
    For Each s As String In Array("Set As Title""Delete"'menu items here
         menu.RunMethodJO("add"Array(s)).RunMethod("setOnMenuItemClickListener"Array(event))
       
    Next
       
       
    Wait For ContextMenuClick_Event (MethodName As String, Args() As Object)
       
       
    Dim MenuItem As JavaObject = Args(0)
       
    Dim title As String = MenuItem.RunMethod("getTitle"Null)
       
    Log(title & " was clicked!"'<---- do what ever you like with the click!!!
       
       
       
    ActionMode.RunMethod("finish"Null)
    End Sub
    The menus are added in the For Each block.
    Extracting the selected text depends on the view. EditText.SelectionLength property is currently missing. It will be available in the next update.
     

    Attached Files:

  2. Star-Dust

    Star-Dust Expert Licensed User

    Really great. This method is used by Google Transale to translate pieces of text within web pages.

    I've been trying for a long time to figure out how to re-create it. Thanks @Erel.

    I modified the code for those who use Ba 6.8 or -

    Code:
    Sub Process_Globals
        
    'These global variables will be declared once when the application starts.
        'These variables can be accessed from all modules.

    End Sub

    Sub Globals
        
    'These global variables will be redeclared each time the activity is created.
        'These variables can only be accessed from this module.
        Private WebView1 As WebView
        
    Dim FocusedView As View
        
    Dim ActionMode As JavaObject
    End Sub

    Sub Activity_Create(FirstTime As Boolean)
        
    Activity.LoadLayout("1")
        WebView1.LoadUrl(
    "https://www.b4x.com")

    End Sub

    Sub ContextMenu_Create(AM As JavaObject, Fw As View)
        
    ActionMode=AM
        FocusedView=Fw
        
    Dim menu As JavaObject = ActionMode.RunMethod("getMenu"Null)
        
    menu.RunMethod("clear"Null)
        
    Dim event As Object = menu.CreateEvent("android.view.MenuItem.OnMenuItemClickListener""ContextMenuClick"True)


        
    For Each s As String In Array("Set As Title""Delete"'menu items here
            menu.RunMethodJO("add"Array(s)).RunMethod("setOnMenuItemClickListener"Array(event))
        
    Next

    End Sub
    Sub ContextMenuClick_Event (MethodName As String, Args() As Object) as boolean
        
    Dim MenuItem As JavaObject = Args(0)
        
    Dim title As String = MenuItem.RunMethod("getTitle"Null)
        
    Log(title & " was clicked!"'<---- do what ever you like with the click!!!
        If FocusedView Is EditText Then
            
    Dim et As EditText = FocusedView
            
    Dim jo As JavaObject = Me
            
    Dim selectionLength As Int = jo.RunMethod("getSelectionLength"Array(et)) 'will be available in the next version of B4A!
            Dim selectionStart As Int = et.SelectionStart
            
    Select title
                
    Case "Set As Title"
                    
    Activity.Title = et.Text.SubString2(selectionStart, selectionLength + selectionStart)
                
    Case "Delete"
                    et.Text = et.Text.SubString2(
    0, selectionStart) & _
                        et.Text.SubString(selectionStart + selectionLength)
            
    End Select
       
        
    End If

        
    ActionMode.RunMethod("finish"Null)
        
    Return True
    End Sub

    Sub Activity_Resume

    End Sub

    Sub Activity_Pause (UserClosed As Boolean)

    End Sub

    #if Java
    import android.view.*;
    import anywheresoftware.b4a.AbsObjectWrapper;
    import android.text.Selection;
    import android.widget.EditText;

        @Override
        public void onActionModeStarted(ActionMode mode) {
            processBA.raiseEvent(this, "contextmenu_create", AbsObjectWrapper.ConvertToWrapper(new anywheresoftware.b4j.object.JavaObject(), mode),
                AbsObjectWrapper.ConvertToWrapper(new anywheresoftware.b4a.objects.ConcreteViewWrapper(), getCurrentFocus()));
            super.onActionModeStarted(mode);
        }

        @Override
        public void onActionModeFinished(ActionMode mode) {
            super.onActionModeFinished(mode);
        }
        public static int getSelectionLength(EditText et) {
            return Selection.getSelectionEnd(et.getText()) - Selection.getSelectionStart(et.getText());
        }

    #End If
     

    Attached Files:

    Last edited: Jul 13, 2017
  3. bernardR

    bernardR Member Licensed User

    Good example of inline java !

    I have tried with Lenovo android 4.4.2 (ok), Oukitel android 5 (ok).

    But in a huawei Y530 android 4.3, it not ok; the contextmenu is not modified.
    The Sub ContextMenuClick_Event is not called.
     
  4. Erel

    Erel Administrator Staff Member Licensed User

    I guess that they are using a non-standard way to create this context menu.
     
  5. Star-Dust

    Star-Dust Expert Licensed User

    Is there a way to insert icons instead of a text?
     
  6. Erel

    Erel Administrator Staff Member Licensed User

    Yes, with CSBuilder:

    [​IMG]
     
  7. bernardR

    bernardR Member Licensed User

    On Lenovo A8-50 kitkat the contextemenu bar is not floating.
    Is there a way to change this ?
     
  8. Erel

    Erel Administrator Staff Member Licensed User

    Most probably no.
     
  9. bernardR

    bernardR Member Licensed User

    Is there a way to remove custom contextMenu and return standard contextMenu ?
    In some views I need the menu 'copy' only.
     
  10. Erel

    Erel Administrator Staff Member Licensed User

    It should be simple to implement a Copy button (search for clipboard library).

    Have you tried to skip this line:
    Code:
    menu.RunMethod("clear"Null)
    ?
     
  11. Star-Dust

    Star-Dust Expert Licensed User

    I meant something like that

    1.png
     
  12. Erel

    Erel Administrator Staff Member Licensed User

    It is not very different then what I posted.

    I don't think that you can change the height.
     
  13. Star-Dust

    Star-Dust Expert Licensed User

    The difference is that you can use a bitmap image. Perhaps even in the backgroud along with the text, you could create a frame or invent an icon that identifies the function. And as you have observed, you can change the size.
    You can insert text at the bottom of the view and the image in the center. The chances of multiplying.
     
  14. Phayao

    Phayao Member Licensed User

    Hi,

    well, something went wrong with my programming - I only get the standard menu like in post #11.
    Is it necessary to update to a higher Android version ?
    I'm using Samsung Note 8 and B4a version 8.0 and Android version 21.
    Any help is very appreciated.

    Chris
     
  15. Erel

    Erel Administrator Staff Member Licensed User

    It is possible that your device theme or UI doesn't support changing the text selection options.
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice