Skip to content
Projects

chinalwb/Android-Rich-text-Editor

View on GitHub

chinalwb/Android-Rich-text-Editor has 871 GitHub stars and 170 forks. GitHot measured -1 in 7 days. Last checked 2026-11-11 01:29 UTC. Last push 2026-09-08.

How these counts are measured

Android Rich Text Editor With customized spans - 富文本编辑器 - Don't miss this one :)

Measured star growth

in 24h
Update delayed
in 7 days
-1
in 15 days
Collecting history
in 1 month
Collecting history

Net star changes over overlapping periods, not daily totals. Missing measurements are left blank. Stars measure attention, not software quality.

README.md

Original

Download GitHub license

Android Rich text Editor (中文说明见这里)

If you are looking for a good rich text editor on Android, DON'T MISS THIS ONE!

And, I am open to work. Feel free to contact me at [email protected] if you have an opening. Thank you!

It's still in progress now, welcome fork and join me!

I published colorpicker and emojipicker as standalone components so they can be reused in other projects easily.

Hey guys! If you're reading this, I believe you are kind of struggling to find out some solution for rich text editor on Android, and specifically, you want to use the Android native APIs to implement. If I was right, maybe I can help. But starting from the very beginning of this project, I open-sourced all of the code, and have helped tens to even hundreds of friends out from their troubles, for free! Now I have to charge for the future helps, starting from $49 per feature implementation; $19 per feature contact. And the improvement will all be open-source to help others out. Reach out [email protected] for details. Thank you!

This is implemented by Java

image

Supported styles:

  • Bold
  • Italic
  • Underline
  • Strikethrough
  • Numeric list
  • Bullet list
  • Align left
  • Align center
  • Align right
  • Insert image
  • Background color
  • Hyper link
  • @
  • Quote
  • Foreground color
  • Emoji icon
  • Superscript
  • Subscript
  • Font size
  • Video
  • Image from internet
  • Dividing line
  • All styles support save as HTML file
  • Load from HTML then continue editing or displaying - New in 0.1.0

Released 0.2.0: migrated to AndroidX

  • Update Glide to 4.11.0
  • The last non-androidx version is 0.1.10

Released 0.1.8: added support for multiple ARE instances in one page

Released 0.1.7: update glide to 4.9.0

In 0.1.6

  • Maintain release, includes:
  • Added foreground color style to ARE_Toolbar_Default
  • Added background color style to ARE_Toolbar_Default
  • Bugs fixing

image

Plan for next version:
  • Undo
  • Redo

Let me know what features you want to have in the next version if there is any, thanks.

How ARE works

  • Two usage modes

    1. AREditor. EditText (the input area) and Toolbar (the styling tools) are in the same component. I.e.: if you include <com.chinalwb.are.AREditor .../> in layout XML, you'll see the input area and styling tools (Bold / Italic / Alignment / Bullet list / etc..) in your activity.

    2. AREditText + IARE_Toolbar (it's an interface). EditText (the input area) and Toolbar (the styling tools) are standalone component themselves. I.e.: you have the choice to decide whether to show the Toolbar, and where to place it, below or bottom of the AREditText, left or right to the AREditText, or any other alignment because the toolbar itself is a HorizontalScrollView (default implementation is ARE_ToolbarDefault), and also you can decide what toolitem to be added to the toolbar.

  • Inside these two modes:

    1. AREditor: it extends RelativeLayout, it contains two child components: AREditText and ARE_Toolbar.

      1. AREditText extends AppCompatEditText, in its afterTextChanged method of TextWatcher, it calls the applyStyle of IARE_Style.

      2. ARE_Toolbar extends LinearLayout, the tool items inside are IARE_Style instances, each instance contains an ImageView, which is being shown in the toolbar.

    2. AREditText + IARE_Toolbar.

      1. No need to repeat about AREditText

      2. IARE_Toolbar, it is an interface, which defines what a toolbar needs to implement. Such as: addToolbarItem, getToolItems, etc.. Inside are, there is a default implementation: ARE_ToolbarDefault, it extends HorizontalScrollView, and has the implementation of all the methods in the IARE_Toolbar interface.

      3. ARE_ToolbarDefault, it is just a toolbar, i.e.: tool item container, what the component does the real work is IARE_ToolItem, which is another interface defines the behaviors of a tool item should have, like: getView returns a view to be shown in the toolbar, getStyle returns an IARE_Style to response to the text change. Currently there are 19 toolitems implementation:

        1. ARE_ToolItem_Abstract ARE_ToolItem_AlignmentCenter ARE_ToolItem_AlignmentLeft ARE_ToolItem_AlignmentRight ARE_ToolItem_At ARE_ToolItem_Bold ARE_ToolItem_Hr ARE_ToolItem_Image ARE_ToolItem_Italic ARE_ToolItem_Link ARE_ToolItem_ListBullet ARE_ToolItem_ListNumber ARE_ToolItem_Quote ARE_ToolItem_Strikethrough ARE_ToolItem_Subscript ARE_ToolItem_Superscript ARE_ToolItem_Underline ARE_ToolItem_UpdaterDefault ARE_ToolItem_Video

        2. The above tool items can be added to toolbar by calling: addToolbarItem(IARE_ToolItem toolItem)

        3. If you want to add your own tool item, you just need to implement your IARE_ToolItem, for example, if you want to add a tool item to change font family, then you can define ARE_ToolItem_FontFamily and implements the methods in IARE_ToolItem. You can check out any of the above ToolItems as reference.

        4. Specially if you want to add a new feature like @, such as ##, check out ARE_ToolItem_At.java, which is a demo for tool item without an image at toolbar.

  • All styles are based on Android Spans

Integration

In your gradle.build of app module, add this in the dependencies:

    implementation 'com.github.bumptech.glide:glide:4.9.0'
    implementation 'com.github.chinalwb:are:0.1.7'

or, as are is still not stable enough to handle kinds of issues in different business scenarios, I'd like recommend to import are into your project directly and add it as a local module dependency.

	implementation project(':are')

Customization & Samples

Documentation for AREditor in layout XML

Name Format Description
expandMode enum FULL (default: Full screen editor) / MIN (min height editor, maxLines = 3)
hideToolbar boolean Whether to hide the toolbar, by default toolbar will be shown. You may want to set it as true when you use MIN expand mode, @feature will still be available but other features won't work because those styles on toolbar has been hidden with toolbar.
toolbarAlignment enum BOTTOM (default: at bottom of AREditor) / TOP (at top of AREditor)

APIs for AREditor in Java

Class Method Params Description
AREditor setExpandMode AREditor.ExpandMode Sets the edit area mode. Possible values are: ExpandMode.FULL (default) / ExpandMode.MIN
AREditor setHideToolbar boolean Sets as true to hide toolbar; sets false will show toolbar
AREditor setToolbarAlignment AREditor.ToolbarAlignment Sets the toolbar position. Possible values are: ToolbarAlignment.BOTTOM (default) / ToolbarAlignment.TOP

Samples for AREditor

XML:

RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:are="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/holo_blue_dark" >

&lt;<span class="pl-ent">TextView</span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">id</span>=<span class="pl-s"><span class="pl-pds">"</span>@+id/xView<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_above</span>=<span class="pl-s"><span class="pl-pds">"</span>@+id/areditor<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_width</span>=<span class="pl-s"><span class="pl-pds">"</span>match_parent<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_height</span>=<span class="pl-s"><span class="pl-pds">"</span>match_parent<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_marginTop</span>=<span class="pl-s"><span class="pl-pds">"</span>1dp<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">background</span>=<span class="pl-s"><span class="pl-pds">"</span>@color/colorAccent<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">gravity</span>=<span class="pl-s"><span class="pl-pds">"</span>center<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">textSize</span>=<span class="pl-s"><span class="pl-pds">"</span>50sp<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">text</span>=<span class="pl-s"><span class="pl-pds">"</span>Your ListView may go here<span class="pl-pds">"</span></span>
    /&gt;

&lt;<span class="pl-ent">com</span>.chinalwb.are.AREditor
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">id</span>=<span class="pl-s"><span class="pl-pds">"</span>@+id/areditor<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_width</span>=<span class="pl-s"><span class="pl-pds">"</span>match_parent<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_height</span>=<span class="pl-s"><span class="pl-pds">"</span>wrap_content<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_alignParentBottom</span>=<span class="pl-s"><span class="pl-pds">"</span>true<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">background</span>=<span class="pl-s"><span class="pl-pds">"</span>@android:color/holo_green_dark<span class="pl-pds">"</span></span>
    <span class="pl-e">are</span><span class="pl-e">:</span><span class="pl-e">expandMode</span>=<span class="pl-s"><span class="pl-pds">"</span>MIN<span class="pl-pds">"</span></span>
    <span class="pl-e">are</span><span class="pl-e">:</span><span class="pl-e">hideToolbar</span>=<span class="pl-s"><span class="pl-pds">"</span>true<span class="pl-pds">"</span></span>
    <span class="pl-e">are</span><span class="pl-e">:</span><span class="pl-e">toolbarAlignment</span>=<span class="pl-s"><span class="pl-pds">"</span>TOP<span class="pl-pds">"</span></span> /&gt;

</RelativeLayout>

Java:

AREditor arEditor = this.findViewById(R.id.areditor);
arEditor.setExpandMode(AREditor.ExpandMode.FULL);
arEditor.setHideToolbar(false);
arEditor.setToolbarAlignment(AREditor.ToolbarAlignment.BOTTOM);

==========

AREditText it self is an AppCompatEditText subclass, so anything applies to AppCompatEditText also works for AREditText.

==========

Documentation for ARE_ToolbarDefault

It extends HorizontalScrollView, so anything applies to HorizontalScrollView also works for ARE_ToolbarDefault.

APIs for IARE_Toolbar

Class Method Params Description
IARE_Toolbar addToolbarItem IARE_ToolItem Add a toolbar item to toolbar
IARE_Toolbar getToolItems -none- Returns all of the tool items in the toolbar
IARE_Toolbar setEditText AREditText Binds AREditText with toolbar
IARE_Toolbar getEditText -none- Returns the bound AREditText
IARE_Toolbar onActivityResult requestCode(int) resultCode(int) data(Intent) For some styles like insert image or video or @ feature, you need open a new Activity, and need to handle the data via onActivityResult, in this method you can dispatch to the specific styles.

APIs for IARE_ToolItem

Class Method Params Description
IARE_ToolItem getStyle -none- Each tool item is a style, and a style combines with specific span.
IARE_ToolItem getView Context Each tool item has a view. If context is null, return the generated view.
IARE_ToolItem onSelectionChanged int selStart, int selEnd Selection changed call back. Update tool item checked status
IARE_ToolItem getToolbar -none- Returns the toolbar of this tool item.
IARE_ToolItem setToolbar IARE_Toolbar Sets the toolbar for this tool item.
IARE_ToolItem getToolItemUpdater -none- Gets the tool item updater instance, will be called when style being checked and unchecked.
IARE_ToolItem setToolItemUpdater IARE_ToolItem_Updater Sets the tool item updater.
IARE_ToolItem onActivityResult requestCode(int) resultCode(int) data(Intent) Handle the dispatched event from IARE_Toolbar

Samples:

xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:are="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/holo_blue_dark">

&lt;<span class="pl-ent">ScrollView</span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_width</span>=<span class="pl-s"><span class="pl-pds">"</span>match_parent<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_height</span>=<span class="pl-s"><span class="pl-pds">"</span>match_parent<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_above</span>=<span class="pl-s"><span class="pl-pds">"</span>@+id/bottombar<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_alignParentLeft</span>=<span class="pl-s"><span class="pl-pds">"</span>true<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_alignParentStart</span>=<span class="pl-s"><span class="pl-pds">"</span>true<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">background</span>=<span class="pl-s"><span class="pl-pds">"</span>@android:color/white<span class="pl-pds">"</span></span>&gt;

    &lt;<span class="pl-ent">com</span>.chinalwb.are.AREditText
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">id</span>=<span class="pl-s"><span class="pl-pds">"</span>@+id/arEditText<span class="pl-pds">"</span></span>
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_width</span>=<span class="pl-s"><span class="pl-pds">"</span>match_parent<span class="pl-pds">"</span></span>
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_height</span>=<span class="pl-s"><span class="pl-pds">"</span>match_parent<span class="pl-pds">"</span></span>
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">gravity</span>=<span class="pl-s"><span class="pl-pds">"</span>top|left<span class="pl-pds">"</span></span>
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">hint</span>=<span class="pl-s"><span class="pl-pds">"</span>Your EditText goes here<span class="pl-pds">"</span></span>
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">textSize</span>=<span class="pl-s"><span class="pl-pds">"</span>50sp<span class="pl-pds">"</span></span> /&gt;
&lt;/<span class="pl-ent">ScrollView</span>&gt;

&lt;<span class="pl-ent">LinearLayout</span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">id</span>=<span class="pl-s"><span class="pl-pds">"</span>@+id/bottombar<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_width</span>=<span class="pl-s"><span class="pl-pds">"</span>match_parent<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_height</span>=<span class="pl-s"><span class="pl-pds">"</span>50dp<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_alignParentBottom</span>=<span class="pl-s"><span class="pl-pds">"</span>true<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">orientation</span>=<span class="pl-s"><span class="pl-pds">"</span>horizontal<span class="pl-pds">"</span></span>
    <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">weightSum</span>=<span class="pl-s"><span class="pl-pds">"</span>1000<span class="pl-pds">"</span></span>&gt;

    &lt;<span class="pl-ent">com</span>.chinalwb.are.styles.toolbar.ARE_ToolbarDefault
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">id</span>=<span class="pl-s"><span class="pl-pds">"</span>@+id/areToolbar<span class="pl-pds">"</span></span>
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_width</span>=<span class="pl-s"><span class="pl-pds">"</span>0dp<span class="pl-pds">"</span></span>
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_height</span>=<span class="pl-s"><span class="pl-pds">"</span>match_parent<span class="pl-pds">"</span></span>
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_weight</span>=<span class="pl-s"><span class="pl-pds">"</span>900<span class="pl-pds">"</span></span>
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">background</span>=<span class="pl-s"><span class="pl-pds">"</span>@color/colorPrimary<span class="pl-pds">"</span></span>
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">gravity</span>=<span class="pl-s"><span class="pl-pds">"</span>center_vertical<span class="pl-pds">"</span></span> /&gt;

    &lt;<span class="pl-ent">View</span>
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_width</span>=<span class="pl-s"><span class="pl-pds">"</span>0dp<span class="pl-pds">"</span></span>
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_height</span>=<span class="pl-s"><span class="pl-pds">"</span>wrap_content<span class="pl-pds">"</span></span>
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_weight</span>=<span class="pl-s"><span class="pl-pds">"</span>5<span class="pl-pds">"</span></span>
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">background</span>=<span class="pl-s"><span class="pl-pds">"</span>@color/colorPrimaryDark<span class="pl-pds">"</span></span> /&gt;

    &lt;<span class="pl-ent">LinearLayout</span>
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_width</span>=<span class="pl-s"><span class="pl-pds">"</span>0dp<span class="pl-pds">"</span></span>
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_height</span>=<span class="pl-s"><span class="pl-pds">"</span>match_parent<span class="pl-pds">"</span></span>
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_weight</span>=<span class="pl-s"><span class="pl-pds">"</span>95<span class="pl-pds">"</span></span>
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">background</span>=<span class="pl-s"><span class="pl-pds">"</span>@color/colorAccent<span class="pl-pds">"</span></span>
        <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">gravity</span>=<span class="pl-s"><span class="pl-pds">"</span>center<span class="pl-pds">"</span></span>&gt;

        &lt;<span class="pl-ent">ImageView</span>
            <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">id</span>=<span class="pl-s"><span class="pl-pds">"</span>@+id/arrow<span class="pl-pds">"</span></span>
            <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_width</span>=<span class="pl-s"><span class="pl-pds">"</span>30dp<span class="pl-pds">"</span></span>
            <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">layout_height</span>=<span class="pl-s"><span class="pl-pds">"</span>30dp<span class="pl-pds">"</span></span>
            <span class="pl-e">android</span><span class="pl-e">:</span><span class="pl-e">src</span>=<span class="pl-s"><span class="pl-pds">"</span>@drawable/arrow_right<span class="pl-pds">"</span></span> /&gt;
    &lt;/<span class="pl-ent">LinearLayout</span>&gt;
&lt;/<span class="pl-ent">LinearLayout</span>&gt;

</RelativeLayout>

Sample in Java for setting up custom toolbar

public class ARE_DefaultToolbarActivity extends AppCompatActivity {

<span class="pl-k">private</span> <span class="pl-smi">IARE_Toolbar</span> <span class="pl-s1">mToolbar</span>;

<span class="pl-k">private</span> <span class="pl-smi">AREditText</span> <span class="pl-s1">mEditText</span>;

<span class="pl-k">private</span> <span class="pl-smi">boolean</span> <span class="pl-s1">scrollerAtEnd</span>;

<span class="pl-c1">@</span><span class="pl-c1">Override</span>
<span class="pl-k">protected</span> <span class="pl-smi">void</span> <span class="pl-en">onCreate</span>(<span class="pl-smi">Bundle</span> <span class="pl-s1">savedInstanceState</span>) {
    <span class="pl-en">super</span>.<span class="pl-en">onCreate</span>(<span class="pl-s1">savedInstanceState</span>);
    <span class="pl-en">setContentView</span>(<span class="pl-smi">R</span>.<span class="pl-s1">layout</span>.<span class="pl-s1">activity_are__default_toolbar</span>);

    <span class="pl-en">initToolbar</span>();
}


<span class="pl-k">private</span> <span class="pl-smi">void</span> <span class="pl-en">initToolbar</span>() {
    <span class="pl-s1">mToolbar</span> = <span class="pl-smi">this</span>.<span class="pl-en">findViewById</span>(<span class="pl-smi">R</span>.<span class="pl-s1">id</span>.<span class="pl-s1">areToolbar</span>);
    <span class="pl-smi">IARE_ToolItem</span> <span class="pl-s1">bold</span> = <span class="pl-k">new</span> <span class="pl-smi">ARE_ToolItem_Bold</span>();
    <span class="pl-smi">IARE_ToolItem</span> <span class="pl-s1">italic</span> = <span class="pl-k">new</span> <span class="pl-smi">ARE_ToolItem_Italic</span>();
    <span class="pl-smi">IARE_ToolItem</span> <span class="pl-s1">underline</span> = <span class="pl-k">new</span> <span class="pl-smi">ARE_ToolItem_Underline</span>();
    <span class="pl-smi">IARE_ToolItem</span> <span class="pl-s1">strikethrough</span> = <span class="pl-k">new</span> <span class="pl-smi">ARE_ToolItem_Strikethrough</span>();
    <span class="pl-smi">IARE_ToolItem</span> <span class="pl-s1">quote</span> = <span class="pl-k">new</span> <span class="pl-smi">ARE_ToolItem_Quote</span>();
    <span class="pl-smi">IARE_ToolItem</span> <span class="pl-s1">listNumber</span> = <span class="pl-k">new</span> <span class="pl-smi">ARE_ToolItem_ListNumber</span>();
    <span class="pl-smi">IARE_ToolItem</span> <span class="pl-s1">listBullet</span> = <span class="pl-k">new</span> <span class="pl-smi">ARE_ToolItem_ListBullet</span>();
    <span class="pl-smi">IARE_ToolItem</span> <span class="pl-s1">hr</span> = <span class="pl-k">new</span> <span class="pl-smi">ARE_ToolItem_Hr</span>();
    <span class="pl-smi">IARE_ToolItem</span> <span class="pl-s1">link</span> = <span class="pl-k">new</span> <span class="pl-smi">ARE_ToolItem_Link</span>();
    <span class="pl-smi">IARE_ToolItem</span> <span class="pl-s1">subscript</span> = <span class="pl-k">new</span> <span class="pl-smi">ARE_ToolItem_Subscript</span>();
    <span class="pl-smi">IARE_ToolItem</span> <span class="pl-s1">superscript</span> = <span class="pl-k">new</span> <span class="pl-smi">ARE_ToolItem_Superscript</span>();
    <span class="pl-smi">IARE_ToolItem</span> <span class="pl-s1">left</span> = <span class="pl-k">new</span> <span class="pl-smi">ARE_ToolItem_AlignmentLeft</span>();
    <span class="pl-smi">IARE_ToolItem</span> <span class="pl-s1">center</span> = <span class="pl-k">new</span> <span class="pl-smi">ARE_ToolItem_AlignmentCenter</span>();
    <span class="pl-smi">IARE_ToolItem</span> <span class="pl-s1">right</span> = <span class="pl-k">new</span> <span class="pl-smi">ARE_ToolItem_AlignmentRight</span>();
    <span class="pl-smi">IARE_ToolItem</span> <span class="pl-s1">image</span> = <span class="pl-k">new</span> <span class="pl-smi">ARE_ToolItem_Image</span>();
    <span class="pl-smi">IARE_ToolItem</span> <span class="pl-s1">video</span> = <span class="pl-k">new</span> <span class="pl-smi">ARE_ToolItem_Video</span>();
    <span class="pl-smi">IARE_ToolItem</span> <span class="pl-s1">at</span> = <span class="pl-k">new</span> <span class="pl-smi">ARE_ToolItem_At</span>();
    <span class="pl-s1">mToolbar</span>.<span class="pl-en">addToolbarItem</span>(<span class="pl-s1">bold</span>);
    <span class="pl-s1">mToolbar</span>.<span class="pl-en">addToolbarItem</span>(<span class="pl-s1">italic</span>);
    <span class="pl-s1">mToolbar</span>.<span class="pl-en">addToolbarItem</span>(<span class="pl-s1">underline</span>);
    <span class="pl-s1">mToolbar</span>.<span class="pl-en">addToolbarItem</span>(<span class="pl-s1">strikethrough</span>);
    <span class="pl-s1">mToolbar</span>.<span class="pl-en">addToolbarItem</span>(<span class="pl-s1">quote</span>);
    <span class="pl-s1">mToolbar</span>.<span class="pl-en">addToolbarItem</span>(<span class="pl-s1">listNumber</span>);
    <span class="pl-s1">mToolbar</span>.<span class="pl-en">addToolbarItem</span>(<span class="pl-s1">listBullet</span>);
    <span class="pl-s1">mToolbar</span>.<span class="pl-en">addToolbarItem</span>(<span class="pl-s1">hr</span>);
    <span class="pl-s1">mToolbar</span>.<span class="pl-en">addToolbarItem</span>(<span class="pl-s1">link</span>);
    <span class="pl-s1">mToolbar</span>.<span class="pl-en">addToolbarItem</span>(<span class="pl-s1">subscript</span>);
    <span class="pl-s1">mToolbar</span>.<span class="pl-en">addToolbarItem</span>(<span class="pl-s1">superscript</span>);
    <span class="pl-s1">mToolbar</span>.<span class="pl-en">addToolbarItem</span>(<span class="pl-s1">left</span>);
    <span class="pl-s1">mToolbar</span>.<span class="pl-en">addToolbarItem</span>(<span class="pl-s1">center</span>);
    <span class="pl-s1">mToolbar</span>.<span class="pl-en">addToolbarItem</span>(<span class="pl-s1">right</span>);
    <span class="pl-s1">mToolbar</span>.<span class="pl-en">addToolbarItem</span>(<span class="pl-s1">image</span>);
    <span class="pl-s1">mToolbar</span>.<span class="pl-en">addToolbarItem</span>(<span class="pl-s1">video</span>);
    <span class="pl-s1">mToolbar</span>.<span class="pl-en">addToolbarItem</span>(<span class="pl-s1">at</span>);

    <span class="pl-s1">mEditText</span> = <span class="pl-smi">this</span>.<span class="pl-en">findViewById</span>(<span class="pl-smi">R</span>.<span class="pl-s1">id</span>.<span class="pl-s1">arEditText</span>);
    <span class="pl-s1">mEditText</span>.<span class="pl-en">setToolbar</span>(<span class="pl-s1">mToolbar</span>);

    <span class="pl-en">setHtml</span>();

    <span class="pl-en">initToolbarArrow</span>();
}

<span class="pl-k">private</span> <span class="pl-smi">void</span> <span class="pl-en">setHtml</span>() {
    <span class="pl-smi">String</span> <span class="pl-s1">html</span> = <span class="pl-s">"&lt;p style=<span class="pl-cce">\"</span>text-align: center;<span class="pl-cce">\"</span>&gt;&lt;strong&gt;New Feature in 0.1.2&lt;/strong&gt;&lt;/p&gt;<span class="pl-cce">\n</span>"</span> +
            <span class="pl-s">"&lt;p style=<span class="pl-cce">\"</span>text-align: center;<span class="pl-cce">\"</span>&gt;&amp;nbsp;&lt;/p&gt;<span class="pl-cce">\n</span>"</span> +
            <span class="pl-s">"&lt;p style=<span class="pl-cce">\"</span>text-align: left;<span class="pl-cce">\"</span>&gt;&lt;span style=<span class="pl-cce">\"</span>color: #3366ff;<span class="pl-cce">\"</span>&gt;In this release, you have a new usage with ARE.&lt;/span&gt;&lt;/p&gt;<span class="pl-cce">\n</span>"</span> +
            <span class="pl-s">"&lt;p style=<span class="pl-cce">\"</span>text-align: left;<span class="pl-cce">\"</span>&gt;&amp;nbsp;&lt;/p&gt;<span class="pl-cce">\n</span>"</span> +
            <span class="pl-s">"&lt;p style=<span class="pl-cce">\"</span>text-align: left;<span class="pl-cce">\"</span>&gt;&lt;span style=<span class="pl-cce">\"</span>color: #3366ff;<span class="pl-cce">\"</span>&gt;AREditText + ARE_Toolbar, you are now able to control the position of the input area and where to put the toolbar at and, what ToolItems you'd like to have in the toolbar. &lt;/span&gt;&lt;/p&gt;<span class="pl-cce">\n</span>"</span> +
            <span class="pl-s">"&lt;p style=<span class="pl-cce">\"</span>text-align: left;<span class="pl-cce">\"</span>&gt;&amp;nbsp;&lt;/p&gt;<span class="pl-cce">\n</span>"</span> +
            <span class="pl-s">"&lt;p style=<span class="pl-cce">\"</span>text-align: left;<span class="pl-cce">\"</span>&gt;&lt;span style=<span class="pl-cce">\"</span>color: #3366ff;<span class="pl-cce">\"</span>&gt;You can not only define the Toolbar (and it's style), you can also add your own ARE_ToolItem with your style into ARE.&lt;/span&gt;&lt;/p&gt;<span class="pl-cce">\n</span>"</span> +
            <span class="pl-s">"&lt;p style=<span class="pl-cce">\"</span>text-align: left;<span class="pl-cce">\"</span>&gt;&amp;nbsp;&lt;/p&gt;<span class="pl-cce">\n</span>"</span> +
            <span class="pl-s">"&lt;p style=<span class="pl-cce">\"</span>text-align: left;<span class="pl-cce">\"</span>&gt;&lt;span style=<span class="pl-cce">\"</span>color: #ff00ff;<span class="pl-cce">\"</span>&gt;&lt;em&gt;&lt;strong&gt;Why not give it a try now?&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;"</span>;
    <span class="pl-s1">mEditText</span>.<span class="pl-en">fromHtml</span>(<span class="pl-s1">html</span>);
}

<span class="pl-k">private</span> <span class="pl-smi">void</span> <span class="pl-en">initToolbarArrow</span>() {
    <span class="pl-k">final</span> <span class="pl-smi">ImageView</span> <span class="pl-s1">imageView</span> = <span class="pl-smi">this</span>.<span class="pl-en">findViewById</span>(<span class="pl-smi">R</span>.<span class="pl-s1">id</span>.<span class="pl-s1">arrow</span>);
    <span class="pl-k">if</span> (<span class="pl-smi">this</span>.<span class="pl-s1">mToolbar</span> <span class="pl-k">instanceof</span> <span class="pl-smi">ARE_ToolbarDefault</span>) {
        ((<span class="pl-smi">ARE_ToolbarDefault</span>) <span class="pl-s1">mToolbar</span>).<span class="pl-en">getViewTreeObserver</span>().<span class="pl-en">addOnScrollChangedListener</span>(<span class="pl-k">new</span> <span class="pl-smi">ViewTreeObserver</span>.<span class="pl-smi">OnScrollChangedListener</span>() {
            <span class="pl-c1">@</span><span class="pl-c1">Override</span>
            <span class="pl-k">public</span> <span class="pl-smi">void</span> <span class="pl-en">onScrollChanged</span>() {
                <span class="pl-smi">int</span> <span class="pl-s1">scrollX</span> = ((<span class="pl-smi">ARE_ToolbarDefault</span>) <span class="pl-s1">mToolbar</span>).<span class="pl-en">getScrollX</span>();
                <span class="pl-smi">int</span> <span class="pl-s1">scrollWidth</span> = ((<span class="pl-smi">ARE_ToolbarDefault</span>) <span class="pl-s1">mToolbar</span>).<span class="pl-en">getWidth</span>();
                <span class="pl-smi">int</span> <span class="pl-s1">fullWidth</span> = ((<span class="pl-smi">ARE_ToolbarDefault</span>) <span class="pl-s1">mToolbar</span>).<span class="pl-en">getChildAt</span>(<span class="pl-c1">0</span>).<span class="pl-en">getWidth</span>();

                <span class="pl-k">if</span> (<span class="pl-s1">scrollX</span> + <span class="pl-s1">scrollWidth</span> &lt; <span class="pl-s1">fullWidth</span>) {
                    <span class="pl-s1">imageView</span>.<span class="pl-en">setImageResource</span>(<span class="pl-smi">R</span>.<span class="pl-s1">drawable</span>.<span class="pl-s1">arrow_right</span>);
                    <span class="pl-s1">scrollerAtEnd</span> = <span class="pl-c1">false</span>;
                } <span class="pl-k">else</span> {
                    <span class="pl-s1">imageView</span>.<span class="pl-en">setImageResource</span>(<span class="pl-smi">R</span>.<span class="pl-s1">drawable</span>.<span class="pl-s1">arrow_left</span>);
                    <span class="pl-s1">scrollerAtEnd</span> = <span class="pl-c1">true</span>;
                }
            }
        });
    }

    <span class="pl-s1">imageView</span>.<span class="pl-en">setOnClickListener</span>(<span class="pl-k">new</span> <span class="pl-smi">View</span>.<span class="pl-smi">OnClickListener</span>() {
        <span class="pl-c1">@</span><span class="pl-c1">Override</span>
        <span class="pl-k">public</span> <span class="pl-smi">void</span> <span class="pl-en">onClick</span>(<span class="pl-smi">View</span> <span class="pl-s1">view</span>) {
            <span class="pl-k">if</span> (<span class="pl-s1">scrollerAtEnd</span>) {
                ((<span class="pl-smi">ARE_ToolbarDefault</span>) <span class="pl-s1">mToolbar</span>).<span class="pl-en">smoothScrollBy</span>(-<span class="pl-smi">Integer</span>.<span class="pl-c1">MAX_VALUE</span>, <span class="pl-c1">0</span>);
                <span class="pl-s1">scrollerAtEnd</span> = <span class="pl-c1">false</span>;
            } <span class="pl-k">else</span> {
                <span class="pl-smi">int</span> <span class="pl-s1">hsWidth</span> = ((<span class="pl-smi">ARE_ToolbarDefault</span>) <span class="pl-s1">mToolbar</span>).<span class="pl-en">getChildAt</span>(<span class="pl-c1">0</span>).<span class="pl-en">getWidth</span>();
                ((<span class="pl-smi">ARE_ToolbarDefault</span>) <span class="pl-s1">mToolbar</span>).<span class="pl-en">smoothScrollBy</span>(<span class="pl-s1">hsWidth</span>, <span class="pl-c1">0</span>);
                <span class="pl-s1">scrollerAtEnd</span> = <span class="pl-c1">true</span>;
            }
        }
    });
}

<span class="pl-c1">@</span><span class="pl-c1">Override</span>
<span class="pl-k">public</span> <span class="pl-smi">boolean</span> <span class="pl-en">onCreateOptionsMenu</span>(<span class="pl-smi">Menu</span> <span class="pl-s1">menu</span>) {
    <span class="pl-en">getMenuInflater</span>().<span class="pl-en">inflate</span>(<span class="pl-smi">R</span>.<span class="pl-s1">menu</span>.<span class="pl-s1">main</span>, <span class="pl-s1">menu</span>);
    <span class="pl-k">return</span> <span class="pl-c1">true</span>;
}

<span class="pl-c1">@</span><span class="pl-c1">Override</span>
<span class="pl-k">public</span> <span class="pl-smi">boolean</span> <span class="pl-en">onOptionsItemSelected</span>(<span class="pl-smi">MenuItem</span> <span class="pl-s1">item</span>) {
    <span class="pl-smi">int</span> <span class="pl-s1">menuId</span> = <span class="pl-s1">item</span>.<span class="pl-en">getItemId</span>();
    <span class="pl-k">if</span> (<span class="pl-s1">menuId</span> == <span class="pl-s1">com</span>.<span class="pl-s1">chinalwb</span>.<span class="pl-s1">are</span>.<span class="pl-s1">R</span>.<span class="pl-s1">id</span>.<span class="pl-s1">action_save</span>) {
        <span class="pl-smi">String</span> <span class="pl-s1">html</span> = <span class="pl-smi">this</span>.<span class="pl-s1">mEditText</span>.<span class="pl-en">getHtml</span>();
        <span class="pl-smi">DemoUtil</span>.<span class="pl-en">saveHtml</span>(<span class="pl-smi">this</span>, <span class="pl-s1">html</span>);
        <span class="pl-k">return</span> <span class="pl-c1">true</span>;
    }
    <span class="pl-k">if</span> (<span class="pl-s1">menuId</span> == <span class="pl-smi">R</span>.<span class="pl-s1">id</span>.<span class="pl-s1">action_show_tv</span>) {
        <span class="pl-smi">String</span> <span class="pl-s1">html</span> = <span class="pl-smi">this</span>.<span class="pl-s1">mEditText</span>.<span class="pl-en">getHtml</span>();
        <span class="pl-smi">Intent</span> <span class="pl-s1">intent</span> = <span class="pl-k">new</span> <span class="pl-smi">Intent</span>(<span class="pl-smi">this</span>, <span class="pl-smi">TextViewActivity</span>.<span class="pl-k">class</span>);
        <span class="pl-s1">intent</span>.<span class="pl-en">putExtra</span>(<span class="pl-c1">HTML_TEXT</span>, <span class="pl-s1">html</span>);
        <span class="pl-en">startActivity</span>(<span class="pl-s1">intent</span>);
        <span class="pl-k">return</span> <span class="pl-c1">true</span>;
    }
    <span class="pl-k">return</span> <span class="pl-en">super</span>.<span class="pl-en">onOptionsItemSelected</span>(<span class="pl-s1">item</span>);
}


<span class="pl-c1">@</span><span class="pl-c1">Override</span>
<span class="pl-k">protected</span> <span class="pl-smi">void</span> <span class="pl-en">onActivityResult</span>(<span class="pl-smi">int</span> <span class="pl-s1">requestCode</span>, <span class="pl-smi">int</span> <span class="pl-s1">resultCode</span>, <span class="pl-smi">Intent</span> <span class="pl-s1">data</span>) {
    <span class="pl-s1">mToolbar</span>.<span class="pl-en">onActivityResult</span>(<span class="pl-s1">requestCode</span>, <span class="pl-s1">resultCode</span>, <span class="pl-s1">data</span>);
}

}

APIs for AREditor

Class Method Params Description
AREditor fromHtml String Load html to AREditor
AREditor getHtml -none- Returns the HTML source of current content in AREditor
AREditor getARE -none- Returns the AREditText instance in this AREditor

APIs for AREditText

Class Method Params Description
AREditText fromHtml -none- Load html to AREditor
AREditText getHtml -none- Returns the HTML source of current content in AREditor
AREditText setToolbar IARE_Toolbar Sets the IARE_Toolbar instance (only necessary when works as separated component and works together with custom toolbar)

Available features demo:

image

image

In progress items:

  • Audio
  • Font family
  • Indent right
  • Indent left
  • Save editings to local SQLite
  • Notes list
  • Headline - deferred, can be done with font size and center style

You can download the APK here:

Click ARE_20190524_0.1.6.apk to download

Known issues:

  • Background color - cursor invisible when put it in the range of BackgroundColorSpan

Thanks @Yasujizr providing the logo for ARE. @Yasujizr I hope to get a new logo now :) Could you please help me?


If you find my work is helpful to you or you are start using my code, you don't need to buy me a coffee, just could you please send me a "✨"? Your * encourages me to make more features open source, thanks for your support. You can contact me at [email protected] if you need any customization or any suggestion.

Explore related projects