Android Tutorial Custom Context Menu for Text Selection

Erel

Administrator
Staff member
Licensed User


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:
B4X:
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.
 

Attachments

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 -

B4X:
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
 

Attachments

Last edited:

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.
 

bernardR

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

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.
 

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:
B4X:
menu.RunMethod("clear", Null)
?
 

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.
 

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.
 

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
 

Erel

Administrator
Staff member
Licensed User
It is possible that your device theme or UI doesn't support changing the text selection options.
 
Top