コンテンツのハイライト表示は、特に検索コンテンツ ページではどこでも見られます。Nuggets を例にとると、特定のキーワードについて、検索後、以下に示すように、キーワードと同じコンテンツがハイライト表示されます。 :
上記の効果は、Flutter で実装するのが非常に簡単であると言えますが、結局のところ、ネイティブ コンポーネント、つまりリッチ テキスト コンポーネント RichText が提供されています。
本日の内容ですが、簡単に概要を申し上げますと、主な内容は次のとおりです。
1. ケースの簡単な効果
2. リッチテキストについて知る
3. テキストの強調表示によるロジックの実装
4. コンポーネントのソースコードを強調表示する
1. ケースの簡単な効果
1. シンプルなコンテンツのハイライト
2. コンテンツの一覧表示
2、リッチテキストを知る
ハイライト効果を実現するには、リッチ テキスト コンポーネント RichText を理解する必要があります。次に、リッチ テキストとは何でしょうか。簡単に言えば、これは通常のテキストよりもカラフルな特別なテキスト形式です。テキストをより鮮やかで興味深いものにするために、さまざまなフォント、色、サイズ、その他の要素を含めることができます。たとえば、次のような一般的なシナリオでは、契約書を読むと、リッチ テキストを使用できます。これは、ネイティブ テキストでは実現できない効果です。
最初の知識構造
ここでのテキストは Text のテキストとは異なることに注意してください。Text というテキストは文字列を指し、ここでのテキストは InlineSpan を指します。もちろん、 InlineSpan は抽象基本クラスです。通常は TextSpan を使用します。
RichText({
super.key,
required this.text,
this.textAlign = TextAlign.start,
this.textDirection,
this.softWrap = true,
this.overflow = TextOverflow.clip,
this.textScaleFactor = 1.0,
this.maxLines,
this.locale,
this.strutStyle,
this.textWidthBasis = TextWidthBasis.parent,
this.textHeightBehavior,
this.selectionRegistrar,
this.selectionColor,
}) : assert(text != null),
assert(textAlign != null),
assert(softWrap != null),
assert(overflow != null),
assert(textScaleFactor != null),
assert(maxLines == null || maxLines > 0),
assert(textWidthBasis != null),
assert(selectionRegistrar == null || selectionColor != null),
super(children: _extractChildren(text));
一般的な建設プロパティの概要:
const TextSpan({
this.text,
this.children,
super.style,
this.recognizer,
MouseCursor? mouseCursor,
this.onEnter,
this.onExit,
this.semanticsLabel,
this.locale,
this.spellOut,
}) : mouseCursor = mouseCursor ??
(recognizer == null ? MouseCursor.defer : SystemMouseCursors.click),
assert(!(text == null && semanticsLabel != null));
属性 |
タイプ |
概要 |
テキスト整列 |
TextAlign |
テキストの配置 TextAlign.left |
テキスト方向 |
テキストの方向 |
テキストの方向 TextDirection.ltr |
オーバーフロー |
テキストオーバーフロー |
テキストのオーバーフローを処理する方法 |
最大行数 |
整数 |
最大行数 |
textWidthBase |
TextWidthBase |
文字幅 TextWidthBasis.parent TextWidthBasis.longestLine |
TextSpan の共通プロパティ
属性 |
説明する |
文章 |
文字列型のテキスト |
子供たち |
サブアセンブリ |
スタイル |
TextStyle型のテキストスタイルは、テキストのサイズ、色、スタイルなどを設定できます。 |
認識装置 |
ジェスチャ インタラクション |
単純なケース:
RichText(
text: const TextSpan(children: [
TextSpan(text: "床前明月光,", style: TextStyle(color: Colors.black)),
TextSpan(text: "疑是地上霜。", style: TextStyle(color: Colors.red)),
TextSpan(text: "举头望明月,", style: TextStyle(color: Colors.blueAccent)),
TextSpan(text: "低头思故乡。", style: TextStyle(color: Colors.tealAccent))
])
効果:
もちろん、上記の書き方以外にもText.richを使って実現することもできます。コードは以下の通りです。
const Text.rich(TextSpan(children: [
TextSpan(text: "床前明月光,", style: TextStyle(color: Colors.black)),
TextSpan(text: "疑是地上霜。", style: TextStyle(color: Colors.red)),
TextSpan(text: "举头望明月,", style: TextStyle(color: Colors.blueAccent)),
TextSpan(text: "低头思故乡。", style: TextStyle(color: Colors.tealAccent))
]))
3. テキストの強調表示によりロジックが実現されます
RichText はリッチ テキスト表示を実装できますが、このコンポーネントを使用して特定のコンテンツを強調表示するにはどうすればよいでしょうか? まず、強調表示されるコンテンツは固定されておらず、コンテンツの各文字が強調表示される可能性があることを理解する必要があります。そのため、TextSpan の場合は、動的に作成し、そのスタイルを動的に変更する必要があります。
ここでのダイナミクスも非常に単純で、以下の図に示すように、文字列の先頭、末尾、中間でインターセプトされるだけです。
もちろん、検索される可能性のあるコンテンツはコンテンツ全体のあちこちに存在することに注意する必要があり、このとき、上記ロジックでは、最後に検索されたコンテンツが見つかるまでループをたどる必要がある。
主なロジックは次のとおりです。
//搜索内容为空
if (_searchContent == "") {
return Text(
_content,
style: _ordinaryStyle,
);
}
List<TextSpan> richList = [];
int start = 0;
int end;
//遍历,进行多处高亮
while ((end = _content.indexOf(_searchContent, start)) != -1) {
//如果搜索内容在开头位置,直接高亮,此处不执行
if (end != 0) {
richList.add(TextSpan(
text: _content.substring(start, end), style: _ordinaryStyle));
}
//高亮内容
richList.add(TextSpan(text: _searchContent, style: _highlightStyle));
//赋值索引
start = end + _searchContent.length;
}
//搜索内容只有在开头或者中间位置,才执行
if (start != _content.length) {
richList.add(TextSpan(
text: _content.substring(start, _content.length),
style: _ordinaryStyle));
}
return RichText(
text: TextSpan(children: richList),
);
4. コンポーネントのソースコードを強調表示する
ソースコードは非常にシンプルで、リストコンポーネントと組み合わせたり、単独で使用したりすることができますが、もちろん文字を増やしたり、背景を変更したりするなど、特殊なニーズに応じて拡張することもできます。
class TextHighlight extends StatelessWidget {
final TextStyle _ordinaryStyle; //普通的样式
final TextStyle _highlightStyle; //高亮的样式
final String _content; //文本内容
final String _searchContent; //搜索的内容
const TextHighlight(this._content, this._searchContent, this._ordinaryStyle,
this._highlightStyle,
{super.key});
@override
Widget build(BuildContext context) {
//搜索内容为空
if (_searchContent == "") {
return Text(
_content,
style: _ordinaryStyle,
);
}
List<TextSpan> richList = [];
int start = 0;
int end;
//遍历,进行多处高亮
while ((end = _content.indexOf(_searchContent, start)) != -1) {
//如果搜索内容在开头位置,直接高亮,此处不执行
if (end != 0) {
richList.add(TextSpan(
text: _content.substring(start, end), style: _ordinaryStyle));
}
//高亮内容
richList.add(TextSpan(text: _searchContent, style: _highlightStyle));
//赋值索引
start = end + _searchContent.length;
}
//搜索内容只有在开头或者中间位置,才执行
if (start != _content.length) {
richList.add(TextSpan(
text: _content.substring(start, _content.length),
style: _ordinaryStyle));
}
return RichText(
text: TextSpan(children: richList),
);
}
}
ケースのデモは非常にシンプルです。上が検索ボックス、下が表示内容なので、ここには掲載しません。ハイライト コンポーネントが提供されているので、コピーして直接使用できます。