Android 儿童绘本/汉语拼音实现

有这样一个项目,开发一个电子绘本,需要在绘本上显示,汉语拼音。

界面布局

                       <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;}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/46176.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32CubeMX 下载及安装教程

目录 1. 什么是 STM32CubeMX? 2. 主要功能 2.1 图形化界面 2.2 中间件支持 2.3 代码生成与集成 3.Java 官网下载并安装 4 CubeMX 下载并安装 4.1 官网下载 ​4.2 安装 1. 什么是 STM32CubeMX? STM32CubeMX 是一款图形化的配置工具&#xff0c;用于配置 STM32 系列微…

一阶低通滤波(IIR)

1.Y(n)a⋅X(n)(1−a)⋅Y(n−1) Y表示输出 X表示输入 a表示滤波系数 为什么该函数可以进行低通滤波。 这个公式中的 a 是一个介于 0 和 1 之间的系数&#xff0c;它决定了滤波器的截止频率和滤波效果。 平滑作用&#xff1a;公式中的 (1−a)⋅Y(n−1) 部分表示上一次输出对当前…

springcolud学习01

创建项目 修改pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.o…

【STM32项目】基于嵌入式智能网控微嵌式远距操控平台(完整工程资料源码)

基于嵌入式智能网控微嵌式远距操控平台 目录&#xff1a; 前言: 一、项目前景调研 1.1 研究背景及意义 1.2 国内外发展现状及趋势 1.2.1 国内现状 1.2.2 国外发展现状 1.2.3 发展趋势 二、什么是嵌入式&#xff1f; 2.1 嵌入式系统概述 2.2 嵌入式系统的组成 2.3 嵌入式操作系统…

《SpringBoot 整合 Prometheus 采集自定义指标》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; 近期刚转战 CSDN&#xff0c;会严格把控文章质量&#xff0c;绝不滥竽充数&#xff0c;如需交流&#xff…

并发漏洞介绍

文章目录 漏洞介绍漏洞场景举例核心思路总结一下 漏洞介绍 并发漏洞&#xff0c;又称条件竞争漏洞&#xff0c;是指在多线程或多进程环境中&#xff0c;由于对共享资源的访问没有正确的同步控制&#xff0c;导致程序行为异常或安全问题的漏洞。这种漏洞常见于各种软件系统中&a…

基于与STM32的加湿器之旋转编码器驱动

1.简介 旋转编码器&#xff0c;也被称为轴编码器或脉冲编码器&#xff08;SPC&#xff09;&#xff0c;是一种将旋转的机械位移量转换为电气信号的传感器&#xff0c;其信号可用于检测位置、速度等。 2.工作原理 旋转编码器的工作原理主要基于光电转换或磁电转换。以光电式旋转…

uniapp 小程序注册全局弹窗组件(无需引入,无需写标签)

由于uniapp没有开放根节点&#xff0c;所以一般情况下通过app.components注册&#xff0c;在需要的页面直接写组件标签&#xff0c;但是如果每个页面都需要的话&#xff0c;再每个都加的话会非常的麻烦 网上的思路都不咋地&#xff1a; 1.通过写一个透明弹窗页面来实现&#…

在 Objective-C 中,如何有效地处理内存管理以避免内存泄漏?

在 Objective-C 中&#xff0c;可以通过以下几个方法来有效地处理内存管理以避免内存泄漏&#xff1a; 使用自动引用计数&#xff08;ARC&#xff09;&#xff1a;ARC 是一种自动内存管理机制&#xff0c;它可以自动地插入 retain、release 和 autorelease 方法来管理对象的内存…

Proteus元器件库与仪器仪表

常用元件与仪表简介 分立元件 1. 电阻Resistor 电阻 RES 排阻 RESPACK-8 2. 电容 Capacitor 瓷片电容 CAP 电解电容 CAP-ELEC 3. 电感 Inductor 4. 电位器 Potentiometer 5. 二极管 Diode 发光二极管 LED 6. 晶体管 Transistor 7. 场效应管 FET 8. 三极管 T…

LivePortrait 数字人:开源的图生视频模型,本地部署和专业视频制作详细教程

看到上面面部表情动态图片&#xff0c;是不是感觉挺有有意思&#xff1f;它就是通过快手、中科大和复旦大学联合研发的图生视频开源大模型LivePortrait&#xff08;灵动人像&#xff09;生成的视频。通过LivePortrait大模型&#xff0c;我们只需要一张人脸正面图片和一段文字或…

单相整流-TI视频课笔记

目录 1、单相半波整流 1.1、单相半波----电容滤波---超轻负载 1.2、单相半波----电容滤波---轻负载 1.3、单相半波----电容滤波---重负载 2、全波整流 2.1、全波整流的仿真 2.2、半波与全波滤波的对比 3、全桥整流电路 3.1、全波和全桥整流对比 3.2、半波全波和全桥…

.env.development、.env.production、.env.staging

环境变量文件&#xff08;如 .env.development、.env.production、.env.staging&#xff09;用于根据不同的环境&#xff08;开发、生产、测试等&#xff09;配置应用程序的行为。 作用 .env.development&#xff1a;用于开发环境的配置。开发人员在本地开发时会使用这个文件…

php获取,昨,今,后天.... 本周,月,年...日期时间戳

时间戳->时间转换工具 时间戳(Unix timestamp)转换工具 - 在线工具 (tool.lu) 代码如下: public function date(){/** 日期 **/// 今天的日期$result[today_date] date("Y-m-d");// 昨天的日期$result[yesterday_date] date("Y-m-d", strtotime(&quo…

Oracle使用fetch first子句报错:ORA-00933 SQL命令未正确结束

问题背景 今天在统计终端厂商告警次数Top10的时候使用SQL查询使用到了fetch first子句&#xff0c;结果执行报错&#xff1a;ORA-00933 SQL命令未正确结束。 报错原因 Oracle数据库中&#xff0c;使用 FETCH FIRST 子句需要启用 Oracle 12c 及以上版本。如果在较低版本的 Or…

【Git使用】管理代码

Git使用 1、git命令1.1、git init1.2、git add1.3、git commit1.4、git push1.5、git branch1.6、git fetch1.7、git checkout X1.8、git status 2、提交执行顺序3、常见错误Error3.1、error: pathspec XXX did not match any file(s) known to git3.2、fatal: not a valid obj…

使机器人在执行任务倒快递

这段代码是用来控制机器人在不同模式下的行为&#xff0c;具体是处理 residenceright 和 residenceleft 两种模式下的过渡过程。代码中使用了一个 mythread 结构体&#xff0c;该结构体包含了机器人的当前模式 (mode) 和过渡过程的阶段 (residenceTransientProcess)。以下是对这…

PyTorch是使用GPU和CPU优化的深度学习张量库——torchvision

torchvision datasets torchvision.datasets 包含了许多标准数据集的加载器。例如&#xff0c;CIFAR10 和 ImageFolder 是其中两个非常常用的类。 CIFAR10 CIFAR10 数据集是一个广泛使用的数据集&#xff0c;包含10类彩色图像&#xff0c;每类有6000张图像&#xff08;5000张…

C++ 类和对象(上)

再C中&#xff0c;我们使用类定义自己的数据类型。通过定义新的类型来反映待解决的问题中的各种概念&#xff0c;可以使我们更容易编写&#xff0c;调试和修改程序。 类定义格式 首先类的定义格式和结构体差不多&#xff0c;而结构体的那一套语法也可以在C中使用。class是定义…

RC-u3 跑团机器人

这道题目要求我们模拟一个跑团机器人&#xff0c;解析玩家输入的包含骰子掷出和加减法运算的指令&#xff0c;计算出不同种类的骰子分别需要掷出几个&#xff0c;并根据输入指令得到可能的最小结果和最大结果。 题目分析 我们需要解析输入的表达式&#xff0c;处理其中的加法…