Android Tutorial Custom Context Menu for Text Selection

Status
Not open for further replies.
SS-2017-07-13_10.43.43.png


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

  • CustomContextMenu.zip
    8.4 KB · Views: 1,496

Star-Dust

Expert
Licensed User
Longtime 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

  • Custom ContextMenu 2.zip
    8.6 KB · Views: 1,039
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.
 

Star-Dust

Expert
Licensed User
Longtime User
Is there a way to insert icons instead of a text?
 

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.
 

Star-Dust

Expert
Licensed User
Longtime 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

Active Member
Licensed User
Longtime 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
 

bsnqt

Active Member
Licensed User
Longtime User
Dear Erel and all,

Sorry I post in this old thread. I have 2 quick questions related to this topic.
1) Can we change the color of the shadow of the highlight text in Webview? (please see attached image)
2) Can we change the method of selecting any text on Webview (for example by double-click on text, not long-click as by default)?

Sorry if I missed any past thread about this topic, please just let me know the link, I will dig into it by myself. Thanks a lot.

Highlight text.jpeg
 
Status
Not open for further replies.
Top