有这样一个项目,开发一个电子绘本,需要在绘本上显示,汉语拼音。
界面布局
<androidx.core.widget.NestedScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:fillViewport="true"android:padding="10dp"><cn.aigcsst.student.view.PinyinTextViewandroid: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);
// }@Overrideprotected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {super.onTextChanged(text, start, lengthBefore, lengthAfter);plainText = null;}@Overrideprotected 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;}}
}