B4A Class Simple text editor class with text styles and colors using ONLY an EditText view

I was recently writing a project that needed to include a simple text editor for the user which was capable of displaying various styles and colors.
I tried using the SMMRichEditor library but I found it to be unreliable on some machines and also did not have all the features I desired.
SMMRichEditor I believe, also uses a Webview in the background. I tried to get answers to some of my problems with it on the forum but received no replies.
I also tried CSBuilder and the RichString library but wasn't able to achieve what I really wanted.
So I set about to create a simple text editor that didn't rely on any external libraries and so this is it.
It does not require CSBuilder, RichString, SMMRichEditor, CSS, HTML or a Webview. It is all done in a standard EditText view.

Features:
* Allows user to type text and format it in any of the shown styles and colors.
* Allows images to be inserted. They can be fixed size or automatically resize when the view is zoomed.
* Can save and read the formatted text from a custom file format. Conversion to Html is also possible.
* Can Copy/Cut/Paste formatted text.
* Has Undo/Redo functionality for formatted text.
* Class has methods to create the Color selector and Style selector as well as the Zoom bar.
* If you use the inbuilt selectors, then the class will look after most of the work for you, you will only need to call a few methods to set it up.
* Can genuinely make the EditText read only. (Sometimes 'ReadOnly' doesn't work on a standard EditText)
* Has custom Context menus.
* Comes with a range of Shortcuts if used with an external keyboard. (eg. Ctrl-B Bold, Ctrl-I Italic).
* ETEditor is a class and not a library, so it can be easily integrated into a project and can be customized to meet your individual requirements.


Demo.png


Color selector and Style selector (both of which are based on standard spinners).

Spinner menus.png


Zoom slider which is based on the ASSlider library on the forum.

Zoom control.png


The 'SetEnabled' method genuinely makes the EditText readonly by placing a transparent panel over it and setting the cursor to invisible.

Disabled.png


Custom Context menus.

Context menu.png


It is best used on a tablet with an external keyboard attached. You are then able to use all of the shortcut keys.

Shortcuts.png


Limitations:
*
Styles and Colors can only be applied to existing text. i.e you need to type the text first and then format it.
* The alignment is only 'fake'. i.e alignment is achieved by inserting or deleting spaces at the beginning of a line. (EditText is NOT in wrap mode)
* The 'SaveToFile' format is custom.
* The 'SaveToHtml' method does not support all styles (eg Relative size and ScaleX) in the html conversion.. It also does not capture the Zoom factor.
* The Zoom slider effects the text size of the entire text. Although if you do want text of different sizes then you can apply 'Relative Size'.
eg. If you set the 'RelativeSize' of some text to .5, then it will always be half the size of the main text. So if the main text is zoomed, then the relative sized text zooms with it but will still be half the size of the main text.

Example usage:
Example usage::
Sub Class_Globals
    Private Root As B4XView
    Dim Panel1 As Panel
    Dim ET As EtEditor
End Sub

Public Sub Initialize
'    B4XPages.GetManager.LogEvents = True
End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")                                    ' Which has a single panel (Panel1) on it
    ET.Initialize(Panel1,0, 10%y,100%x,90%y, 0)                    ' Initialize class with size, position and scale (normally set to 0)
    ET.CreateStyleSpinner(Panel1,100%x - 8%x,2%y,Colors.Black)     ' Create Style spinner (If using the inbuilt one)
    ET.CreateColorSpinner(Panel1,100%x - 17%x,2%y,Colors.Black)    ' Create Color spinner (If using the inbuilt one)
    ET.CreateZoomSlider(Panel1,100%x - 42%x,1%y,23%x,8%y)          ' Create Zoom slider (If using the inbuilt one)
    'ET.EditText.Text = "Welcome to ETEditor"                      ' Set a default text if required
    If File.Exists(File.DirAssets,"Sample.et") Then                ' Or read from a file
        Wait for (ET.ReadFromFile(File.DirAssets,"Sample.et")) Complete (bResult As Boolean)
    End If
End Sub

Commonly used Methods:
Public Sub Initialize (Parent As Panel, Left As Int, Top As Int, Width As Int, Height As Int, DeviceScale As Float)
'Initializes the object and specifies the EditText position and size. Pass a 0 as scale for the class to calculate the correct scale for you.
Public Sub CreateColorSpinner (Parent As Panel, Left As Int, Top As Int, BorderColor As Int)
' Creates a Color Selector from a standard spinner.
' If used, this class will handle all of the selections made automatically.
' Set BorderColor to Transparent if not required..
Public Sub CreateStyleSpinner (Parent As Panel, Left As Int, Top As Int, BorderColor As Int)
' Creates a formatted Style Selector with Edit functions from a standard spinner
' If used, this class will handle all of the selections made automatically.
Public Sub CreateZoomSlider (Parent As Panel, Left As Int, Top As Int, Width As Int, Height As Int)
' Creates a Zoom slider using the inbuilt 'Slider' pseudoclass (Code at the end)
' If used, this class will handle all of the adjustments made with the slider automatically.
Public Sub InsertImage (ImageDir As String, ImageFile As String, Width As Int, Height As Int)
' Inserts an image into the EditText. For a non-zoomable image have '[NZ]' somewhere in the file name.
' Width and Height can be in one of 4 formats;
' 0, 0 (No Width or Height specified: Will clear the EditText and fill it with the image)
' W, 0 (Width specified but no Height: Will resize the image to Width and set the Height according to the Aspect Ratio)
' 0, H (Height specified but no Width: Will resize the image to Height and set the Width according to the Aspect Ratio)
' W, H (Width and Height specified: Will resize the image to the specified size regardless of Aspect Ratio)
Public Sub ReadFromFile (Dir As String, Filename As String)
' Reads text with formatting from file and displays in EditText
Public Sub ReadFromHtml (Dir As String, Filename As String)
' Reads a html file and displays it in the EditText. Note: not all styles (eg Relative size and ScaleX) are supported by the html conversion.
Public Sub SaveToFile (Dir As String, Filename As String)
' Saves the displayed text with formatting in a custom format.
Public Sub SaveToHtml (Dir As String, Filename As String)
' Saves the displayed text with formatting as html. Note: not all styles (eg Relative size and ScaleX) are supported by the html conversion.
Public Sub SetReadOnly (ReadOnly As Boolean, BackColor As Int)
' Sets whether the EditText is in read only mode or not. Optionally pass a new Background color (or 1 to leave unchanged).
' The 'ReadFromFile' method will still work in Read Only mode.

Sometimes used methods:
Public Sub EditText
As EditText
' Returns the EditText view so the user can view or change it's properties.
' Do NOT change the Text property. Doing so will kill all the formatting.
Public Sub GetScale
' Returns the scale being used by the class
Public Sub GetSpnColorsLayout
' Get the position and dimensions of the Colors spinner
Public Sub GetSpnStylesLayout
' Get the position and dimensions of the Styles spinner
Public Sub GetZoomSliderLayout
' Get the Slider size and position
Public Sub GetReadOnly
' Returns the ReadOnly state of the EditText
Public Sub SetZoomSliderTextSize (NewSize As Int)
' Sets the textsize for the Slider (correct size should have already been selected but just in case it needs to be changed)

Rarely used methods: (Note; These Methods are not required if using the internal Color, Style selector and Zoom slider as the class will call these subs by itself)
Public Sub AddSpanToET
(ETSpanType As Int, Parameter As Float)
' Add a span (Color or Textstyle) on the currently selected text.
' Note: This is called automatically if using the inbuilt Style Spinner
Public Sub AddToUndoRedoHistory
' Add the current state (text and formatting) of the EditText to the UndoRedoHistory
' Note: This class will automatically call this sub when required.
Public Sub Align (ETAlignType As Int)
' Aligns text in the selected line by adding or deleting spaces in front. ONLY works if EditText is NOT in wrap mode.
' Note: This is called automatically if using the inbuilt Style Spinner
Public Sub Clear (ClearUndoHistoryAsWell As Boolean)
' Clears the EditText of all text and spans
Public Sub Copy
' Copies the selected text complete with formatting
' Note: Call this sub if using Custom Context Menus (Copy+)
Public Sub Cut
' Cuts the selected text complete with formatting
' Note: Call this sub if using Custom Context Menus (Cut+)
Public Sub Delete
' Deletes the selected text.
' Note: Only required when need to delete text via code. The EditText will take care of text deleted by the user.
Public Sub InsertText (NewText As String)
' Inserts text at the cursor position
' Note: Only required when need to insert text via code. The EditText will take care of text inserted by the user.
Public Sub Paste
' Pastes the copied text and it's formatting
' Note: Call this sub if using Custom Context Menus (Paste+)
Public Sub Redo
' Performs an Redo operation.
' Note: This is called automatically if using the inbuilt Style Spinner
Public Sub RemoveSpans
' Removes any spans for the selected text (i.e. turns the text back to Normal)
' Note: This is called automatically if using the inbuilt Style Spinner
Public Sub Replace (ReplacementText As String)
' Replaces the selected text with the replacement text
' Note: Only required when need to replace text via code. The EditText will take care of text replaced by the user.
Public Sub ShowShortcuts
' Displays a summary of all the shortcuts (when using an external keyboard)
' Note: Automatically called via shortcut key
Public Sub Undo
' Performs an Undo operation.
' Note: This is called automatically if using the inbuilt Style Spinner

Final note: This class is fully functional as I have supplied it but some portions of it can be tweaked to meet individual requirements.
eg. The only other class required is my 'XUIViewsBG' class (supplied in the sample project). This is just a collection of dialogs that automatically scale to a given textsize.
You can replace these with your own dialogs if you wish.
You may also wish to have the class raise events or expose other properties.
 

Attachments

  • ETEditor V2.1.zip
    39.7 KB · Views: 71
Last edited:

B G

Member
Licensed User
Longtime User
I have updated the ETEditor to V2.0.
I made some major changes internally, using more native Android methods.
I have also added two more methods.
ReadFromHtml
SaveToHtml


These use the internal Android html class to do the conversions. However some formatting styles (eg Relative size and ScaleX) are not supported by the html conversion.
 

Mehrzad238

Active Member
Hi, B G

I have tried your code and faced this error:

Log:
** Activity (main) Create (first time) **
** Activity (main) Resume **
*** Service (starter) Create ***
Error occurred on line: 588 (EtEditor)
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Class java.lang.Object.getClass()' on a null object reference
    at anywheresoftware.b4a.agraham.reflection.Reflection.runmethod(Reflection.java:205)
    at anywheresoftware.b4a.agraham.reflection.Reflection.RunMethod(Reflection.java:802)
    at b4a.ETEditor.eteditor._addtoundoredohistory(eteditor.java:2538)
    at b4a.ETEditor.eteditor._et_textchanged(eteditor.java:4786)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:351)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:157)
    at anywheresoftware.b4a.objects.EditTextWrapper$1.afterTextChanged(EditTextWrapper.java:83)
    at android.widget.TextView.sendAfterTextChanged(TextView.java:10737)
    at android.widget.TextView.setText(TextView.java:6393)
    at android.widget.TextView.setText(TextView.java:6162)
    at android.widget.EditText.setText(EditText.java:138)
    at android.widget.TextView.setText(TextView.java:6114)
    at android.widget.TextView.setTransformationMethod(TextView.java:2617)
    at android.widget.TextView.applySingleLine(TextView.java:10342)
    at android.widget.TextView.setInputType(TextView.java:6666)
    at anywheresoftware.b4a.objects.EditTextWrapper.setInputType(EditTextWrapper.java:187)
    at b4a.ETEditor.eteditor._initialize(eteditor.java:523)
    at b4a.ETEditor.b4xmainpage$ResumableSub_B4XPage_Created.resume(b4xmainpage.java:86)
    at b4a.ETEditor.b4xmainpage._b4xpage_created(b4xmainpage.java:52)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.debug.Debug.CallSub4(Debug.java:318)
    at anywheresoftware.b4a.debug.Debug.CallSubNew2(Debug.java:285)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.keywords.Common.CallSubDebug2(Common.java:1087)
    at b4a.ETEditor.b4xpagesmanager._createpageifneeded(b4xpagesmanager.java:1070)
    at b4a.ETEditor.b4xpagesmanager._showpage(b4xpagesmanager.java:427)
    at b4a.ETEditor.b4xpagesmanager._addpage(b4xpagesmanager.java:247)
    at b4a.ETEditor.b4xpagesmanager._addpageandcreate(b4xpagesmanager.java:261)
    at b4a.ETEditor.b4xpagesmanager._initialize(b4xpagesmanager.java:167)
    at b4a.ETEditor.main._activity_create(main.java:440)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:351)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at anywheresoftware.b4a.shell.Shell$1.run(Shell.java:273)
    at android.os.Handler.handleCallback(Handler.java:938)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:223)
    at android.app.ActivityThread.main(ActivityThread.java:7743)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Call B4XPages.GetManager.LogEvents = True to enable logging B4XPages events.

First I want to thank you for sharing this
And then fix this

Cheers.
 

B G

Member
Licensed User
Longtime User
Hi Mehrzad238,

Sorry for the late reply but I am in a country area for a few days with little or no internet access.
Could you please clarify your problem.

1) Are you getting the problem running the demo app or when trying to put the ETEditor class in your own code?
2) Did you get the problem straight away or when you were trying to do something (eg. Add a style or copy or paste etc)?
3) What type of device are you trying to run it on?
4) Are you running in Debug or Release mode?
5) Any other information you might see as relevant.

B.G.
 

Mehrzad238

Active Member
Sorry for the late reply but I am in a country area for a few days with little or no internet access.
No problem. No rush, take your time.

Are you getting the problem running the demo app or when trying to put the ETEditor class in your own code?
No, when running the demo.
2) Did you get the problem straight away or when you were trying to do something (eg. Add a style or copy or paste etc)?

Sometimes, straight away(on debug of course), sometimes in release mode(when I tried to add a style)

The error occurs in this line:
B4X:
SpannableStringET = refET.RunMethod("getText") ' i
4) Are you running in Debug or Release mode?
Both!
5) Any other information you might see as relevant.
Check the images I have sent in the attachment(the first one is not important because it is on Bluestacks, the second one is when I want to choose a style, and the third is for when I want to choose a color)
And as you might have noticed, the second and the third have been tested on a real phone (Xiaomi Redmi Note 11s, Android 13)

The rest of my answers were tested on both, and the results were the same.

Best of Luck B G
 

Attachments

  • Screenshot_2025.04.14_00.18.20.724.png
    Screenshot_2025.04.14_00.18.20.724.png
    92.2 KB · Views: 47
  • photo_2025-04-13_23-22-48.jpg
    photo_2025-04-13_23-22-48.jpg
    62.1 KB · Views: 50
  • photo_2025-04-13_23-22-46.jpg
    photo_2025-04-13_23-22-46.jpg
    63.6 KB · Views: 52

B G

Member
Licensed User
Longtime User
Hi Mehrzad238,
I have tried the demo project on many machines and emulators here and it works on them all. So I don't really know what's going on.
In your case it doesn't seem to initialize properly.
For the line:
B4X:
SpannableStringET = refET.RunMethod("getText")

The error seems to be that refET is not initialized. This is done in the initialize sub of the class.

B4X:
    refET.Target = ET
    refET.SetOnKeyListener("ET_OnKeyPress")
    SpannableStringET = refET.RunMethod("getText") ' includes the text with all spans

You will notice that the exact same line is in the Initialize sub and no error occurs. I would run the project in debug mode and step thru the Initialize sub to see if the above lines are actually being executed.
Have you altered the demo project in any way??

B.G.
 

B G

Member
Licensed User
Longtime User
Hi Mehrzad238,

I did find one bug in the ET class which would account for some of your issues. I have updated the demo project (which contains the updated class) to the first post. I have kept the version number the same thought (V2.0).
Hope that helps.

B.G.
 

B G

Member
Licensed User
Longtime User
I have just uploaded V 2.1 of the ETEditor.

It's main extra feature is the ability to insert images in the text. You can make an image a fixed size or have it automatically resize when the view is zoomed.
I have also made the Undo/Redo facility undo zoom changes as well.

So to summarize, the ETEditor class (which uses only a standard EditView and nothing more) has the following features.

* Allows user to type text and format it in many styles and colors.
* Allows images to be inserted. They can be fixed size or automatically resize when the view is zoomed.
* Can save and read the formatted text from the custom file format. Conversion to Html is also possible.
* Can Copy/Cut/Paste formatted text.
* Has Undo/Redo functionality for formatted text.
* Has methods to create the Color selector and Style selector as well as the Zoom bar.
* If you use the inbuilt selectors, then the class will look after most of the work for you, you will only need to call a few methods to set it up.
* Can genuinely make the EditText read only. (Sometimes 'ReadOnly' doesn't work on a standard EditText)
* Has custom Context menus.
* Comes with a range of Shortcuts if used with an external keyboard. (eg. Ctrl-B Bold, Ctrl-I Italic)
* ETEditor is a class and not a library, so it can be easily integrated into a project and can be customized to meet your individual requirements.

Demo.png
 

B G

Member
Licensed User
Longtime User
Hi Mehrzad238,

I haven't heard from you in a while, so I assume you got everything to work ok??
 

Mehrzad238

Active Member
Hello B G
Well, I was very busy with my work. I am doing Computer services (as it is my job) and teaching some B4A(RecyclerView) for a private group in Telegram with recording videos and editing them, which is very time-consuming. I will check and let you know the result.
 

Mehrzad238

Active Member
Hi B G

i tried the new version on my xiaomi redmi note 11 android 13 and here is the log, just look at it and see what is going on:


B4X:
Logger connected to:  Xiaomi 2201117SI
--------- beginning of main
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create (first time) **
Call B4XPages.GetManager.LogEvents = True to enable logging B4XPages events.
** Activity (main) Resume **
main_contextmenu_create (java line: 425)
java.lang.ClassNotFoundException: miuix.toolbar.FloatingActionMode
    at java.lang.Class.classForName(Native Method)
    at java.lang.Class.forName(Class.java:607)
    at java.lang.Class.forName(Class.java:512)
    at anywheresoftware.b4j.object.JavaObject$MethodCache.getMethod(JavaObject.java:321)
    at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:120)
    at b4a.ETEditor.main._contextmenu_create(main.java:425)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:221)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:201)
    at b4a.ETEditor.main.onActionModeStarted(main.java:592)
    at com.android.internal.policy.DecorView.startActionMode(DecorView.java:1050)
    at com.android.internal.policy.DecorView.startActionModeForChild(DecorView.java:965)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.View.startActionMode(View.java:7791)
    at android.widget.Editor.startActionModeInternal(Editor.java:2524)
    at android.widget.SelectionActionModeHelper.startActionMode(SelectionActionModeHelper.java:307)
    at android.widget.SelectionActionModeHelper.startSelectionActionMode(SelectionActionModeHelper.java:281)
    at android.widget.SelectionActionModeHelper.lambda$startSelectionActionModeWithSmartSelectAnimation$0$android-widget-SelectionActionModeHelper(SelectionActionModeHelper.java:342)
    at android.widget.SelectionActionModeHelper$$ExternalSyntheticLambda9.run(Unknown Source:4)
    at android.widget.SelectionActionModeHelper.startSelectionActionModeWithSmartSelectAnimation(SelectionActionModeHelper.java:350)
    at android.widget.SelectionActionModeHelper.$r8$lambda$mMDhXh3JQs_q5UuyTdq2CLenZJk(Unknown Source:0)
    at android.widget.SelectionActionModeHelper$$ExternalSyntheticLambda11.accept(Unknown Source:4)
    at android.widget.SelectionActionModeHelper$TextClassificationAsyncTask.onPostExecute(SelectionActionModeHelper.java:1051)
    at android.widget.SelectionActionModeHelper$TextClassificationAsyncTask.onPostExecute(SelectionActionModeHelper.java:999)
    at android.os.AsyncTask.finish(AsyncTask.java:771)
    at android.os.AsyncTask.-$$Nest$mfinish(Unknown Source:0)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:788)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:211)
    at android.os.Looper.loop(Looper.java:300)
    at android.app.ActivityThread.main(ActivityThread.java:8348)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:582)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1028)
Caused by: java.lang.ClassNotFoundException: miuix.toolbar.FloatingActionMode
    ... 38 more
java.lang.ClassNotFoundException: miuix.toolbar.FloatingActionMode
** Activity (main) Pause event (activity is not paused). **
** Activity (main) Create  **
Call B4XPages.GetManager.LogEvents = True to enable logging B4XPages events.
** Activity (main) Resume **
** Activity (main) Pause event (activity is not paused). **
** Activity (main) Create  **
Call B4XPages.GetManager.LogEvents = True to enable logging B4XPages events.
** Activity (main) Resume **
main_contextmenu_create (java line: 425)
java.lang.ClassNotFoundException: miuix.toolbar.FloatingActionMode
    at java.lang.Class.classForName(Native Method)
    at java.lang.Class.forName(Class.java:607)
    at java.lang.Class.forName(Class.java:512)
    at anywheresoftware.b4j.object.JavaObject$MethodCache.getMethod(JavaObject.java:321)
    at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:120)
    at b4a.ETEditor.main._contextmenu_create(main.java:425)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:221)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:201)
    at b4a.ETEditor.main.onActionModeStarted(main.java:592)
    at com.android.internal.policy.DecorView.startActionMode(DecorView.java:1050)
    at com.android.internal.policy.DecorView.startActionModeForChild(DecorView.java:965)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.View.startActionMode(View.java:7791)
    at android.widget.Editor.startActionModeInternal(Editor.java:2524)
    at android.widget.SelectionActionModeHelper.startActionMode(SelectionActionModeHelper.java:307)
    at android.widget.SelectionActionModeHelper.startSelectionActionMode(SelectionActionModeHelper.java:281)
    at android.widget.SelectionActionModeHelper.lambda$startSelectionActionModeWithSmartSelectAnimation$0$android-widget-SelectionActionModeHelper(SelectionActionModeHelper.java:342)
    at android.widget.SelectionActionModeHelper$$ExternalSyntheticLambda9.run(Unknown Source:4)
    at android.widget.SelectionActionModeHelper.startSelectionActionModeWithSmartSelectAnimation(SelectionActionModeHelper.java:350)
    at android.widget.SelectionActionModeHelper.$r8$lambda$mMDhXh3JQs_q5UuyTdq2CLenZJk(Unknown Source:0)
    at android.widget.SelectionActionModeHelper$$ExternalSyntheticLambda11.accept(Unknown Source:4)
    at android.widget.SelectionActionModeHelper$TextClassificationAsyncTask.onPostExecute(SelectionActionModeHelper.java:1051)
    at android.widget.SelectionActionModeHelper$TextClassificationAsyncTask.onPostExecute(SelectionActionModeHelper.java:999)
    at android.os.AsyncTask.finish(AsyncTask.java:771)
    at android.os.AsyncTask.-$$Nest$mfinish(Unknown Source:0)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:788)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:211)
    at android.os.Looper.loop(Looper.java:300)
    at android.app.ActivityThread.main(ActivityThread.java:8348)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:582)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1028)
Caused by: java.lang.ClassNotFoundException: miuix.toolbar.FloatingActionMode
    ... 38 more
java.lang.ClassNotFoundException: miuix.toolbar.FloatingActionMode
main_contextmenu_create (java line: 425)
java.lang.ClassNotFoundException: miuix.toolbar.FloatingActionMode
    at java.lang.Class.classForName(Native Method)
    at java.lang.Class.forName(Class.java:607)
    at java.lang.Class.forName(Class.java:512)
    at anywheresoftware.b4j.object.JavaObject$MethodCache.getMethod(JavaObject.java:321)
    at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:120)
    at b4a.ETEditor.main._contextmenu_create(main.java:425)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:221)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:201)
    at b4a.ETEditor.main.onActionModeStarted(main.java:592)
    at com.android.internal.policy.DecorView.startActionMode(DecorView.java:1050)
    at com.android.internal.policy.DecorView.startActionModeForChild(DecorView.java:965)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.View.startActionMode(View.java:7791)
    at android.widget.Editor.startActionModeInternal(Editor.java:2524)
    at android.widget.SelectionActionModeHelper.startActionMode(SelectionActionModeHelper.java:307)
    at android.widget.SelectionActionModeHelper.startSelectionActionMode(SelectionActionModeHelper.java:281)
    at android.widget.SelectionActionModeHelper.lambda$startSelectionActionModeWithSmartSelectAnimation$0$android-widget-SelectionActionModeHelper(SelectionActionModeHelper.java:342)
    at android.widget.SelectionActionModeHelper$$ExternalSyntheticLambda9.run(Unknown Source:4)
    at android.widget.SelectionActionModeHelper.startSelectionActionModeWithSmartSelectAnimation(SelectionActionModeHelper.java:350)
    at android.widget.SelectionActionModeHelper.$r8$lambda$mMDhXh3JQs_q5UuyTdq2CLenZJk(Unknown Source:0)
    at android.widget.SelectionActionModeHelper$$ExternalSyntheticLambda11.accept(Unknown Source:4)
    at android.widget.SelectionActionModeHelper$TextClassificationAsyncTask.onPostExecute(SelectionActionModeHelper.java:1051)
    at android.widget.SelectionActionModeHelper$TextClassificationAsyncTask.onPostExecute(SelectionActionModeHelper.java:999)
    at android.os.AsyncTask.finish(AsyncTask.java:771)
    at android.os.AsyncTask.-$$Nest$mfinish(Unknown Source:0)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:788)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:211)
    at android.os.Looper.loop(Looper.java:300)
    at android.app.ActivityThread.main(ActivityThread.java:8348)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:582)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1028)
Caused by: java.lang.ClassNotFoundException: miuix.toolbar.FloatingActionMode
    ... 38 more
java.lang.ClassNotFoundException: miuix.toolbar.FloatingActionMode
Logger connected to:  Xiaomi 2201117SI
--------- beginning of main
main_contextmenu_create (java line: 425)
java.lang.ClassNotFoundException: miuix.toolbar.FloatingActionMode
    at java.lang.Class.classForName(Native Method)
    at java.lang.Class.forName(Class.java:607)
    at java.lang.Class.forName(Class.java:512)
    at anywheresoftware.b4j.object.JavaObject$MethodCache.getMethod(JavaObject.java:321)
    at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:120)
    at b4a.ETEditor.main._contextmenu_create(main.java:425)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:221)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:201)
    at b4a.ETEditor.main.onActionModeStarted(main.java:592)
    at com.android.internal.policy.DecorView.startActionMode(DecorView.java:1050)
    at com.android.internal.policy.DecorView.startActionModeForChild(DecorView.java:965)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.View.startActionMode(View.java:7791)
    at android.widget.Editor.startActionModeInternal(Editor.java:2524)
    at android.widget.SelectionActionModeHelper.startActionMode(SelectionActionModeHelper.java:307)
    at android.widget.SelectionActionModeHelper.startSelectionActionMode(SelectionActionModeHelper.java:281)
    at android.widget.SelectionActionModeHelper.lambda$startSelectionActionModeWithSmartSelectAnimation$0$android-widget-SelectionActionModeHelper(SelectionActionModeHelper.java:342)
    at android.widget.SelectionActionModeHelper$$ExternalSyntheticLambda9.run(Unknown Source:4)
    at android.widget.SelectionActionModeHelper.startSelectionActionModeWithSmartSelectAnimation(SelectionActionModeHelper.java:350)
    at android.widget.SelectionActionModeHelper.$r8$lambda$mMDhXh3JQs_q5UuyTdq2CLenZJk(Unknown Source:0)
    at android.widget.SelectionActionModeHelper$$ExternalSyntheticLambda11.accept(Unknown Source:4)
    at android.widget.SelectionActionModeHelper$TextClassificationAsyncTask.onPostExecute(SelectionActionModeHelper.java:1051)
    at android.widget.SelectionActionModeHelper$TextClassificationAsyncTask.onPostExecute(SelectionActionModeHelper.java:999)
    at android.os.AsyncTask.finish(AsyncTask.java:771)
    at android.os.AsyncTask.-$$Nest$mfinish(Unknown Source:0)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:788)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:211)
    at android.os.Looper.loop(Looper.java:300)
    at android.app.ActivityThread.main(ActivityThread.java:8348)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:582)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1028)
Caused by: java.lang.ClassNotFoundException: miuix.toolbar.FloatingActionMode
    ... 38 more
java.lang.ClassNotFoundException: miuix.toolbar.FloatingActionMode
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create (first time) **
Call B4XPages.GetManager.LogEvents = True to enable logging B4XPages events.
** Activity (main) Resume **
main_contextmenu_create (java line: 425)
java.lang.ClassNotFoundException: miuix.toolbar.FloatingActionMode
    at java.lang.Class.classForName(Native Method)
    at java.lang.Class.forName(Class.java:607)
    at java.lang.Class.forName(Class.java:512)
    at anywheresoftware.b4j.object.JavaObject$MethodCache.getMethod(JavaObject.java:321)
    at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:120)
    at b4a.ETEditor.main._contextmenu_create(main.java:425)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:221)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:201)
    at b4a.ETEditor.main.onActionModeStarted(main.java:592)
    at com.android.internal.policy.DecorView.startActionMode(DecorView.java:1050)
    at com.android.internal.policy.DecorView.startActionModeForChild(DecorView.java:965)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1048)
    at android.view.View.startActionMode(View.java:7791)
    at android.widget.Editor.startInsertionActionMode(Editor.java:2407)
    at android.widget.TextView.onTouchEvent(TextView.java:11483)
    at android.view.View.dispatchTouchEvent(View.java:15174)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3206)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2843)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3206)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2843)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3206)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2843)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3206)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2843)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3206)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2843)
    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3206)
    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2843)
    at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:579)
    at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1903)
    at android.app.Activity.dispatchTouchEvent(Activity.java:4450)
    at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:537)
    at android.view.View.dispatchPointerEvent(View.java:15454)
    at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:7295)
    at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:7048)
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6463)
    at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:6520)
    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:6486)
    at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:6651)
    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:6494)
    at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:6708)
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6467)
    at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:6520)
    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:6486)
    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:6494)
    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6467)
    at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:9764)
    at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:9715)
    at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:9670)
    at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:9925)
    at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:296)
    at android.os.MessageQueue.nativePollOnce(Native Method)
    at android.os.MessageQueue.next(MessageQueue.java:341)
    at android.os.Looper.loopOnce(Looper.java:169)
    at android.os.Looper.loop(Looper.java:300)
    at android.app.ActivityThread.main(ActivityThread.java:8348)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:582)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1028)
Caused by: java.lang.ClassNotFoundException: miuix.toolbar.FloatingActionMode
    ... 64 more
Message longer than Log limit (4000). Message was truncated.
java.lang.ClassNotFoundException: miuix.toolbar.FloatingActionMode
 

B G

Member
Licensed User
Longtime User

Hi Mehrzad238,

Unfortunately, your log doesn't tell me what B4A line the error came on, so I can't really help until I know it. Have you tried the code on another device?
I have never heard of the class 'miuix.toolbar.FloatingActionMode', so it makes me think that it is something unique to your device and not standard Android.
If that is the case, then there is nothing I can do about it, you'll have to comment out the code for custom context menus.
The custom context menu code is based on what Erel posted in the forum ,so you may find that the code for the menus will not work for any app on your device.
Create a new project and try and use just the context menu subs and see if it runs. I suspect that it is nothing to do with my demo but the device in general.
The code you need is everything in the '#Region Custom Context Menus' in 'Main' (including the Java code) or you can consult the original thread.
(https://www.b4x.com/android/forum/threads/custom-context-menu-for-text-selection.81596/).

Also please bear in mind that even though the demo app has custom context menus they are not actually part of the ETEditor class itself. They are just included in the app as a convenience. Perhaps you could try to build an app using just the ETEditor class without the context menus.
 
Last edited:
Top