You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
xiaomi_notes_reading/src/notes/ui/RichEditor.java

277 lines
7.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package net.micode.notes.ui;
import android.content.Context;
import android.os.Build;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.UnderlineSpan;
import android.util.AttributeSet;
import android.widget.EditText;
import android.graphics.Typeface;
import android.text.Spannable;
public class RichEditor extends EditText {
public interface OnTextChangeListener {
void onTextChange(String text);
}
private OnTextChangeListener onTextChangeListener;
public RichEditor(Context context) {
super(context);
init();
}
public RichEditor(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RichEditor(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
// 初始化逻辑
}
public void setOnTextChangeListener(OnTextChangeListener listener) {
this.onTextChangeListener = listener;
// 监听文本变化
addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (onTextChangeListener != null) {
onTextChangeListener.onTextChange(s.toString());
}
}
@Override
public void afterTextChanged(Editable s) {}
});
}
// 重写获取文本的方法
@Override
public Editable getText() {
return super.getText();
}
// 重写设置文本的方法,包括设置文本颜色、文本样式等
@Override
public void setText(CharSequence text, BufferType type) {
super.setText(text, type);
}
// 重写设置光标位置的方法
@Override
public void setSelection(int index) {
super.setSelection(index);
}
// 重写设置选中文本的方法
@Override
public void setSelection(int start, int stop) {
super.setSelection(start, stop);
}
// 重写获取选中文本起始位置的方法
@Override
public int getSelectionStart() {
return super.getSelectionStart();
}
// 重写获取选中文本结束位置的方法
@Override
public int getSelectionEnd() {
return super.getSelectionEnd();
}
// 重写设置文本外观的方法,文本外观包括字体、颜色等
@Override
public void setTextAppearance(Context context, int resid) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
super.setTextAppearance(resid);
} else {
// 对旧版本的兼容处理
setTextAppearance(context, resid);
}
}
// 设置编辑器高度
public void setEditorHeight(int pixels) {
this.setHeight(pixels);
}
//设置编辑器字体大小
public void setEditorFontSize(int size) {
this.setTextSize(size);
}
//设置编辑器字体颜色
public void setEditorFontColor(int color) {
this.setTextColor(color);
}
//设置占位符文本
public void setPlaceholder(String placeholder) {
this.setHint(placeholder);
}
// 设置编辑器启用或禁用输入
public void setInputEnabled(boolean enabled) {
this.setEnabled(enabled);
}
//切换粗体样式
public void toggleBold() {
toggleStyleSpan(Typeface.BOLD);
}
//切换斜体样式
public void toggleItalic() {
toggleStyleSpan(Typeface.ITALIC);
}
//切换删除线样式
public void toggleStrikeThrough() {
toggleSpan(StrikethroughSpan.class, new StrikethroughSpan());
}
//切换下划线样式
public void toggleUnderline() {
toggleSpan(UnderlineSpan.class, new UnderlineSpan());
}
// 粗体、斜体样式切换方法
private void toggleStyleSpan(int style) {
int start = getSelectionStart();
int end = getSelectionEnd();
if (start < 0 || end < 0 || start >= end) {
return; // 没有选中文本时不处理
}
Spannable str = getText();
StyleSpan[] spans = str.getSpans(start, end, StyleSpan.class);
boolean hasStyle = false;
// 检查是否已存在相同样式
for (StyleSpan span : spans) {
if (span.getStyle() == style) {
str.removeSpan(span);
hasStyle = true;
}
}
// 如果不存在对应样式,则添加
if (!hasStyle) {
str.setSpan(new StyleSpan(style), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
//通用的Span切换方法下划线和删除线
private <T> void toggleSpan(Class<T> spanType, T newSpan) {
int start = getSelectionStart();
int end = getSelectionEnd();
if (start < 0 || end < 0 || start >= end) {
return;
}
Spannable str = getText();
@SuppressWarnings("unchecked")
T[] spans = (T[]) str.getSpans(start, end, spanType);
if (spans.length > 0) {
// 如果已存在样式,则移除
for (T span : spans) {
str.removeSpan(span);
}
} else {
// 如果不存在样式,则添加
str.setSpan(newSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
// 应用粗体样式
public void applyBold() {
int start = getSelectionStart();
int end = getSelectionEnd();
if (start >= 0 && end >= 0 && start != end) {
Spannable str = getText();
StyleSpan[] spans = str.getSpans(start, end, StyleSpan.class);
for (StyleSpan span : spans) {
if (span.getStyle() == Typeface.BOLD) {
str.removeSpan(span);
}
}
str.setSpan(new StyleSpan(Typeface.BOLD), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
// 应用斜体样式
public void applyItalic() {
int start = getSelectionStart();
int end = getSelectionEnd();
if (start >= 0 && end >= 0 && start != end) {
Spannable str = getText();
StyleSpan[] spans = str.getSpans(start, end, StyleSpan.class);
for (StyleSpan span : spans) {
if (span.getStyle() == Typeface.ITALIC) {
str.removeSpan(span);
}
}
str.setSpan(new StyleSpan(Typeface.ITALIC), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
// 应用删除线样式
public void applyStrikeThrough() {
int start = getSelectionStart();
int end = getSelectionEnd();
if (start >= 0 && end >= 0 && start != end) {
Spannable str = getText();
StrikethroughSpan[] spans = str.getSpans(start, end, StrikethroughSpan.class);
for (StrikethroughSpan span : spans) {
str.removeSpan(span);
}
str.setSpan(new StrikethroughSpan(), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
// 应用下划线样式
public void applyUnderline() {
int start = getSelectionStart();
int end = getSelectionEnd();
if (start >= 0 && end >= 0 && start != end) {
Spannable str = getText();
UnderlineSpan[] spans = str.getSpans(start, end, UnderlineSpan.class);
for (UnderlineSpan span : spans) {
str.removeSpan(span);
}
str.setSpan(new UnderlineSpan(), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}