移动端强大的富文本编辑器richeditor-android
一、运行效果图
二、代码具体实现
1.引入richeditor-android
richeditor-android需要的jar:
implementation 'jp.wasabeef:richeditor-android:1.2.2'
这是一个Dialog框架,demo中不想自己去写,所以就使用了第三方
implementation 'com.afollestad.material-dialogs:core:0.9.6.0'
2.引入控件RichEditor
<jp.wasabeef.richeditor.RichEditor
android:id="@+id/editor"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
3.使用到的权限
如果拍照需要相机权限,选择图片需要SD卡权限,插入网络图片需要网络权限
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
4.初始化RichEditor
mEditor = (RichEditor) findViewById(R.id.editor);
//初始化编辑高度
mEditor.setEditorHeight(200);
//初始化字体大小
mEditor.setEditorFontSize(22);
//初始化字体颜色
mEditor.setEditorFontColor(Color.BLACK);
//mEditor.setEditorBackgroundColor(Color.BLUE);
//初始化内边距
mEditor.setPadding(10, 10, 10, 10);
//设置编辑框背景,可以是网络图片
//mEditor.setBackground("https://raw.githubusercontent.com/wasabeef/art/master/chip.jpg");
// mEditor.setBackgroundColor(Color.BLUE);
mEditor.setBackgroundResource(R.drawable.bg);
//设置默认显示语句
mEditor.setPlaceholder("Insert text here...");
//设置编辑器是否可用
mEditor.setInputEnabled(true);
5.实时监听Editor输入内容
mPreview = (TextView) findViewById(R.id.preview);
mEditor.setOnTextChangeListener(new RichEditor.OnTextChangeListener() {
@Override
public void onTextChange(String text) {
mPreview.setText(text);
}
});
6.功能方法
/**
* 撤销当前标签状态下所有内容
*/
findViewById(R.id.action_undo).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.undo();
}
});
/**
* 恢复撤销的内容
*/
findViewById(R.id.action_redo).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.redo();
}
});
/**
* 加粗
*/
findViewById(R.id.action_bold).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.focusEditor();
mEditor.setBold();
}
});
/**
* 斜体
*/
findViewById(R.id.action_italic).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.focusEditor();
mEditor.setItalic();
}
});
/**
* 下角表
*/
findViewById(R.id.action_subscript).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.focusEditor();
if (mEditor.getHtml() == null) {
return;
}
mEditor.setSubscript();
}
});
/**
* 上角标
*/
findViewById(R.id.action_superscript).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.focusEditor();
if (mEditor.getHtml() == null) {
return;
}
mEditor.setSuperscript();
}
});
/**
* 删除线
*/
findViewById(R.id.action_strikethrough).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.focusEditor();
mEditor.setStrikeThrough();
}
});
/**
*下划线
*/
findViewById(R.id.action_underline).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.focusEditor();
mEditor.setUnderline();
}
});
/**
* 设置标题(1到6)
*/
findViewById(R.id.action_heading1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.setHeading(1);
}
});
findViewById(R.id.action_heading2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.setHeading(2);
}
});
findViewById(R.id.action_heading3).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.setHeading(3);
}
});
findViewById(R.id.action_heading4).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.setHeading(4);
}
});
findViewById(R.id.action_heading5).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.setHeading(5);
}
});
findViewById(R.id.action_heading6).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.setHeading(6);
}
});
/**
* 设置字体颜色
*/
findViewById(R.id.action_txt_color).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.focusEditor();
new MaterialDialog.Builder(MainActivity.this)
.title("选择字体颜色")
.items(R.array.color_items)
.itemsCallbackSingleChoice(-1, new MaterialDialog.ListCallbackSingleChoice() {
@Override
public boolean onSelection(MaterialDialog dialog, View itemView, int which, CharSequence text) {
dialog.dismiss();
switch (which) {
case 0://红
mEditor.setTextColor(Color.RED);
break;
case 1://黄
mEditor.setTextColor(Color.YELLOW);
break;
case 2://蓝
mEditor.setTextColor(Color.GREEN);
break;
case 3://绿
mEditor.setTextColor(Color.BLUE);
break;
case 4://黑
mEditor.setTextColor(Color.BLACK);
break;
}
return false;
}
}).show();
}
});
findViewById(R.id.action_bg_color).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.focusEditor();
new MaterialDialog.Builder(MainActivity.this)
.title("选择字体背景颜色")
.items(R.array.text_back_color_items)
.itemsCallbackSingleChoice(-1, new MaterialDialog.ListCallbackSingleChoice() {
@Override
public boolean onSelection(MaterialDialog dialog, View itemView, int which, CharSequence text) {
dialog.dismiss();
switch (which) {
case 0://红
mEditor.setTextBackgroundColor(Color.RED);
break;
case 1://黄
mEditor.setTextBackgroundColor(Color.YELLOW);
break;
case 2://蓝
mEditor.setTextBackgroundColor(Color.GREEN);
break;
case 3://绿
mEditor.setTextBackgroundColor(Color.BLUE);
break;
case 4://黑
mEditor.setTextBackgroundColor(Color.BLACK);
break;
case 5://透明
mEditor.setTextBackgroundColor(R.color.transparent);
break;
}
return false;
}
}).show();
}
});
/**
* 向右缩进
*/
findViewById(R.id.action_indent).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.focusEditor();
mEditor.setIndent();
}
});
/**
* 向左缩进
*/
findViewById(R.id.action_outdent).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.focusEditor();
mEditor.setOutdent();
}
});
/**
*文章左对齐
*/
findViewById(R.id.action_align_left).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.focusEditor();
mEditor.setAlignLeft();
}
});
/**
* 文章居中对齐
*/
findViewById(R.id.action_align_center).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.setAlignCenter();
}
});
/**
* 文章右对齐
*/
findViewById(R.id.action_align_right).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.setAlignRight();
}
});
/**
* 无序排列
*/
findViewById(R.id.action_insert_bullets).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.setBullets();
}
});
/**
* 有序排列
*/
findViewById(R.id.action_insert_numbers).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.setNumbers();
}
});
/**
* 引用
*/
findViewById(R.id.action_blockquote).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.setBlockquote();
}
});
/**
* 插入图片
*/
findViewById(R.id.action_insert_image).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.focusEditor();
ActivityCompat.requestPermissions(MainActivity.this, mPermissionList, 100);
}
});
/**
* 插入连接
*/
findViewById(R.id.action_insert_link).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new MaterialDialog.Builder(MainActivity.this)
.title("将输入连接地址")
.items("http://blog.csdn.net/huangxiaoguo1")
.itemsCallbackSingleChoice(-1, new MaterialDialog.ListCallbackSingleChoice() {
@Override
public boolean onSelection(MaterialDialog dialog, View itemView, int which, CharSequence text) {
dialog.dismiss();
mEditor.focusEditor();
mEditor.insertLink("http://blog.csdn.net/huangxiaoguo1",
"http://blog.csdn.net/huangxiaoguo1");
return false;
}
}).show();
}
});
/**
* 选择框
*/
findViewById(R.id.action_insert_checkbox).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mEditor.focusEditor();
mEditor.insertTodo();
}
});
/**
* 获取并显示Html
*/
findViewById(R.id.tv_showhtml).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(v.getContext(), WebViewActivity.class);
intent.putExtra("contextURL", mEditor.getHtml());
startActivity(intent);
}
});
7.插入图片并使用屏幕宽度
权限,我这里只是选着图片,关于拍照的自己可以去实现
String[] mPermissionList = new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE};
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 100:
boolean writeExternalStorage = grantResults[0] == PackageManager.PERMISSION_GRANTED;
boolean readExternalStorage = grantResults[1] == PackageManager.PERMISSION_GRANTED;
if (grantResults.length > 0 && writeExternalStorage && readExternalStorage) {
getImage();
} else {
Toast.makeText(this, "请设置必要权限", Toast.LENGTH_SHORT).show();
}
break;
}
}
private void getImage() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
startActivityForResult(new Intent(Intent.ACTION_GET_CONTENT).setType("image/*"),
REQUEST_PICK_IMAGE);
} else {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, REQUEST_PICK_IMAGE);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
switch (requestCode) {
case REQUEST_PICK_IMAGE:
if (data != null) {
String realPathFromUri = RealPathFromUriUtils.getRealPathFromUri(this, data.getData());
mEditor.insertImage("https://unsplash.it/2000/2000?random&58",
"huangxiaoguo\" style=\"max-width:100%");
mEditor.insertImage(realPathFromUri, realPathFromUri + "\" style=\"max-width:100%");
// mEditor.insertImage(realPathFromUri, realPathFromUri + "\" style=\"max-width:100%;max-height:100%");
} else {
Toast.makeText(this, "图片损坏,请重新选择", Toast.LENGTH_SHORT).show();
}
break;
}
}
}
注意这里 “\” style=\”max-width:100%”是让我们从手机选择的图片和网络加载的图片适配屏幕宽高,解决图片太大显示不全问题!
三、项目代码结构目录图
四、参考文章
richeditor-android github地址:https://github.com/wasabeef/richeditor-android
关于如何获得手机图片真正地址(realPathFromUri )请看:http://blog.csdn.net/huangxiaoguo1/article/details/78983582
移动端强大的富文本编辑器richeditor-android
注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权