Flutter實現(xiàn)文本滾動高亮效果的示例講解
前言
最近有個需求是人工語音播放時文本能隨語音朗讀時像歌詞滾動的效果.
原本第一考慮的時能隨時間字體漸變成更改后的顏色, 有比較流暢的走馬燈效果. 但最終實踐了幾次后發(fā)現(xiàn)要能夠逐字逐行漸變有一些麻煩, 不好實現(xiàn).
所以轉(zhuǎn)而變?yōu)閷⒆煮w直接將字體高亮, 一段文本區(qū)分成兩個部分, 一個部分是高亮文本, 也就是已朗讀的部分, 一個部分是剩下未朗讀的非高亮文本. 通過時時渲染頁面就能達成滾動高亮的效果.
功能實現(xiàn)
因為在Text中會存在兩段文本, 所以就不能單只用Text組件, 而改用Text.rich. 通過textSpan生成一個數(shù)組然后放到text.rich中. 所以本文需要處理, 而不是自己一個個拼接, 所以需要先有一個解析的類來負責(zé)處理.
需要在項目中加入第三方插件 string_scanner 用于掃描文本.
class StringParser {
// 導(dǎo)入的文本
final String content;
// 高亮部分尾部索引, 也就是兩段的區(qū)分位置
final int endIndex;
StringParser({required this.content, required this.endIndex});
late StringScanner _scanner;
// 解析函數(shù)
InlineSpan parser() {
_scanner = StringScanner(content);
parseContent();
final List<InlineSpan> spans = [];
int currentPosition = 0;
// 需要高亮的部分
spans.add(TextSpan(style: _spans.style, text: _spans.text(content)));
currentPosition = _spans.end;
// 未高亮的部分
if (currentPosition != content.length) {
spans.add(
TextSpan(text: content.substring(currentPosition, content.length)));
}
return TextSpan(style: TextStyleSupport.defaultStyle, children: spans);
}
late SpanBean _spans;
// 解析需要變成高亮的字符
void parseContent() {
int startIndex = 0;
_spans = SpanBean(startIndex, endIndex);
if (!_scanner.isDone) {
_scanner.position++;
}
}
}之后需要定義一個高亮的數(shù)據(jù)類型, 用于方便修改之后想要高亮的文本樣式和默認樣式.
class SpanBean {
SpanBean(this.start, this.end);
final int start;
final int end;
String text(String src) {
return src.substring(start, end);
}
TextStyle get style => TextStyleSupport.highLightStyle;
}
class TextStyleSupport {
static const defaultStyle = TextStyle(color: Colors.black, fontSize: 36);
static const highLightStyle = TextStyle(color: Colors.green, fontSize: 36);
}至此文本高亮和非高亮處理完成, 只需要在文件中導(dǎo)入后使用.
滾動效果則需要實現(xiàn)一個play函數(shù)里通過 Future.delayed來控制延時遞歸執(zhí)行.
_starPlay(flag) {
// flag用于判斷是 執(zhí)行還是暫停
if (this.endIndex == content.length + 1 || !flag) {
return;
}
parser = StringParser(content: content, endIndex: this.endIndex++);
span = parser.parser();
setState(() {});
Future.delayed(Duration(milliseconds: 100)).then((value) {
_starPlay(this.flag);
});
}最終在文件里的代碼則是
import 'package:flutter/material.dart';
import 'string_parser.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late InlineSpan span;
final String content =
"""一點不錯,”狐貍說?!皩ξ襾碚f,你還只是一個小男孩,就像其他千萬個小男孩一樣。我不需要你。你也同樣用不著我。對你來說,我也不過是一只狐貍,和其他千萬只狐貍一樣。但是,如果你馴服了我,我們就互相不可缺少了。對我來說,你就是世界上唯一的了;我對你來說,也是世界上唯一的了。""";
late StringParser parser;
int endIndex = 0;
bool flag = true;
@override
void initState() {
super.initState();
parser = StringParser(content: content, endIndex: endIndex);
span = parser.parser();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("滾動高亮文本"),
actions: [
ElevatedButton(
onPressed: () {
this.flag = true;
_starPlay(flag);
print('開始');
},
child: Text("開始")),
ElevatedButton(
onPressed: () {
this.flag = false;
// _starPlay(flag);
print('暫停');
},
child: Text("暫停"))
],
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Text.rich(span),
));
}
_starPlay(flag) {
if (this.endIndex == content.length + 1 || !flag) {
return;
}
parser = StringParser(content: content, endIndex: this.endIndex++);
span = parser.parser();
setState(() {});
Future.delayed(Duration(milliseconds: 100)).then((value) {
_starPlay(this.flag);
});
}
}實現(xiàn)效果:

到此這篇關(guān)于Flutter實現(xiàn)文本滾動高亮效果的示例講解的文章就介紹到這了,更多相關(guān)Flutter文本高亮內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android?Jetpack組件中LifeCycle作用詳細介紹
Jetpack是谷歌在Google?I/O?2017大會上發(fā)布一套幫助開發(fā)者解決Android架構(gòu)設(shè)計的方案,而Lifecycle是Jetpack?architecture下的一部分,一起來看一下Lifecycle的使用及原理分析2022-09-09
ionic監(jiān)聽android返回鍵實現(xiàn)“再按一次退出”功能
本篇文章主要介紹了ionic監(jiān)聽android返回鍵實現(xiàn)“再按一次退出”功能,非常具有實用價值,需要的朋友可以參考下2018-02-02
Jetpack Compose實現(xiàn)列表和動畫效果詳解
這篇文章主要為大家詳細講講Jetpack Compose實現(xiàn)列表和動畫效果的方法步驟,文中的代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-06-06
Android 超詳細深刨Activity Result API的使用
這篇文章主要介紹了Android開發(fā)中Activity Result API的使用,掌握了它以后你就可以放棄startActivityForResult了,感興趣的朋友一起來看看吧2022-03-03

