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 系列微…

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…

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

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

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、半波全波和全桥…

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

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

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是定义…

oracle数据库的plsql免安装版安装

这个是连接oracle数据库的&#xff0c;注意安装不能有中文路径。以下只是示例。 1、打开D:\ruanjian\plsql\plsql\plsql&#xff0c;发送plsqldev.exe快捷方式到桌面。 2、新弹出的页面填写cancel,什么也不写。 3、将instanceclient解压&#xff0c;并复制文件路径。 修改tool…

[Python学习篇] Python搭建静态web服务器

Python内置的web静态服务器 Python内置的http.server模块可以快速启动一个简单的HTTP服务器。 在Python 3中&#xff0c;打开命令行或终端&#xff0c;在你想要作为静态服务器根目录的文件夹下&#xff0c;运行以下命令&#xff1a; python -m http.server 8000 这将会在…

纯vue+js实现数字0到增加到指定数字动画效果功能

关于数字增加动画效果网上基本上都是借助第三方插件实现的,就会导致有的项目安装插件总会出问题,所有最好使用原生vue+js实现,比较稳妥 纯vue+js实现数字0到增加到指定数字动画效果功能 vue+js 实现数字增加动画功能 效果图 其中,关于数字变化的间隔时间,延时效果都可…

澳门建筑插画:成都亚恒丰创教育科技有限公司

澳门建筑插画&#xff1a;绘就东方之珠的斑斓画卷 在浩瀚的中华大地上&#xff0c;澳门以其独特的地理位置和丰富的历史文化&#xff0c;如同一颗璀璨的明珠镶嵌在南国海疆。这座城市&#xff0c;不仅是东西方文化交融的典范&#xff0c;更是建筑艺术的宝库。当画笔轻触纸面&a…

一个spring boot项目的启动过程分析

1、web.xml 定义入口类 <context-param><param-name>contextConfigLocation</param-name><param-value>com.baosight.ApplicationBoot</param-value> </context-param> 2、主入口类: ApplicationBoot,SpringBoot项目的mian函数 SpringBo…

(三)Redis持久化,你真的懂了吗?万字分析AOF和RDB的优劣 AOF的刷盘、重写策略 什么叫混合重写 MP-AOF方案是什么

引言 —— Redis基础概念 Redis概念&#xff1a;Redis (REmote DIctionary Server) 是用 C 语言开发的一个开源的高性能键值对&#xff08;key-value&#xff09;数据库。 为什么会出现Redis呢&#xff1f;它的到来是为了解决什么样的问题&#xff1f; Redis 是一个NOSQL类型…

操作系统真象还原:创建文件系统

14.2 创建文件系统 14.2.1 创建超级块、i结点、目录项 超级块 /** Author: Adward-DYX 1654783946qq.com* Date: 2024-05-07 10:18:02* LastEditors: Adward-DYX 1654783946qq.com* LastEditTime: 2024-05-07 11:24:50* FilePath: /OS/chapter14/14.2/fs/super_block.h* Des…

WPF学习(6) -- WPF命令和通知

一 、WPF命令 1.ICommand代码 创建一个文件夹和文件 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Input;namespace 学习.Command {public class MyCommand : ICommand{Acti…

CCSI: 数据无关类别增量学习的持续类特定印象| 文献速递-基于深度学习的多模态数据分析与生存分析

Title 题目 CCSI: Continual Class-Specific Impression for data-free class incremental learning CCSI: 数据无关类别增量学习的持续类特定印象 01 文献速递介绍 当前用于医学影像分类任务的深度学习模型表现出令人鼓舞的性能。这些模型大多数需要在训练之前收集所有的…

中间件——Kafka

两个系统各自都有各自要去做的事&#xff0c;所以只能将消息放到一个中间平台&#xff08;中间件&#xff09; Kafka 分布式流媒体平台 程序发消息&#xff0c;程序接收消息 Producer&#xff1a;Producer即生产者&#xff0c;消息的产生者&#xff0c;是消息的入口。 Brok…