有这样一个项目,开发一个电子绘本,需要在绘本上显示,汉语拼音。
界面布局
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:padding="10dp">
<cn.aigcsst.student.view.PinyinTextView
android:id="@+id/textViewStory"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fadeScrollbars="true"
android:scrollbars="vertical"
android:textSize="18sp" />
</androidx.core.widget.NestedScrollView>
实现代码
package cn.netkiller.student.view;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@SuppressLint("AppCompatCustomView")
public class PinyinTextView extends TextView {
private static final String TAG = PinyinTextView.class.getSimpleName();
private final TextPaint textPaintSpell = new TextPaint(Paint.ANTI_ALIAS_FLAG);
private final TextPaint textPaintChinese = new TextPaint(Paint.ANTI_ALIAS_FLAG);
private final int colorSpell = Color.parseColor("#1b97d6");
private final int colorChinese = Color.parseColor("#000000");
private String[] pinyin;
private String[] chinese;
private PlainText plainText;
public PinyinTextView(Context context) {
super(context);
init();
}
public PinyinTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PinyinTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void init() {
initTextPaint();
}
public void initTextPaint() {
float denity = getResources().getDisplayMetrics().density;
textPaintSpell.setStrokeWidth(denity);
textPaintChinese.setStrokeWidth(denity);
textPaintSpell.setTextAlign(Paint.Align.LEFT);
textPaintChinese.setTextAlign(Paint.Align.LEFT);
//设置字体大小
textPaintSpell.setTextSize(getTextSize());
textPaintChinese.setTextSize(getTextSize());
textPaintSpell.setColor(colorSpell);
textPaintChinese.setColor(colorChinese);
textPaintSpell.setTextSize(ConvertUtils.dp2px(spellFontSize));
textPaintChinese.setTextSize(ConvertUtils.dp2px(chineseFontSize));
}
private void initResource() {
if (plainText != null) return;
Log.d(TAG, "initResource " + getText().toString());
String text = getText().toString();
plainText = new PlainText();
plainText.chinese = text;
if (!text.isEmpty()) {
try {
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
format.setToneType(HanyuPinyinToneType.WITH_TONE_MARK);
format.setVCharType(HanyuPinyinVCharType.WITH_U_UNICODE);
plainText.pinyin = PinyinHelper.toHanYuPinyinString(text, format, " ", true);
for (int index = 0; index < text.length(); index++) {
char character = text.charAt(index);
// Log.d(TAG, String.valueOf(character));
String[] pinyinUnit = PinyinHelper.toHanyuPinyinStringArray(character, format);
if (pinyinUnit == null || pinyinUnit.length == 0) {
plainText.character.add(new PlainTextCharacter(String.valueOf(character), String.valueOf(character)));
} else {
plainText.character.add(new PlainTextCharacter(pinyinUnit[0], String.valueOf(character)));
}
}
} catch (
ArrayIndexOutOfBoundsException e) {
Log.e(TAG, Objects.requireNonNull(e.getMessage()));
}
Log.d(TAG, "plainText: " + plainText.character.size());
}
// return plainText;
}
// @Override
// public boolean onPreDraw() {
// return super.onPreDraw();
// }
// @Override
// protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
// super.onLayout(changed, left, top, right, bottom);
// }
@Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
super.onTextChanged(text, start, lengthBefore, lengthAfter);
plainText = null;
}
@Override
protected void onDraw(Canvas canvas) {
initResource();
TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
textPaint.setTextSize(getTextSize());
float fontSpacing = textPaint.getFontSpacing();
float x = 0;
float y = fontSpacing;
for (PlainTextCharacter c : plainText.character) {
// Log.d(TAG, c.toString());
float wordWidth = textPaint.measureText(c.pinyin) > textPaint.measureText(c.chinese) ? textPaint.measureText(c.pinyin) : textPaint.measureText(c.chinese);
if (x + wordWidth > getWidth()) {
x = 0;
y = y + fontSpacing / 2;
}
float x1 = x;
if (textPaint.measureText(c.pinyin) > textPaint.measureText(c.chinese)) {
x1 = x + textPaint.measureText(c.pinyin) / 2 - textPaint.measureText(c.chinese) / 2;
} else {
x = x + textPaint.measureText(c.chinese) / 2 - textPaint.measureText(c.pinyin) / 2;
}
float y1 = y;
canvas.drawText(c.pinyin, x, y, textPaintSpell);
canvas.drawText(c.chinese, x1, y1, textPaintChinese);
x = x + wordWidth + fontSpacing / 2;
}
setHeight((int) (y + fontSpacing + fontSpacing / 2));
}
public class PlainText {
public String pinyin;
public String chinese;
public List<PlainTextCharacter> character = new ArrayList<PlainTextCharacter>();
}
public class PlainTextCharacter {
public String pinyin;
public String chinese;
public PlainTextCharacter(String pinyin, String chinese) {
this.pinyin = pinyin;
this.chinese = chinese;
}
}
}