-
Notifications
You must be signed in to change notification settings - Fork 131
Description
您好,非常感谢您的付出,markdown_widget给我帮了很大的忙!!但是我需要在markdown_widget的基础上实现“高亮”的效果,如图:
选中文字“Postpartum”后,点击菜单中的“高亮”按钮,期望将选中的文字增加黄色的背景(效果和前面的“during”文字相同)
目前我已经在简单场景中实现了这个功能,但是部分复杂的场景中还是有很多问题,我不知道我基于markdown_widget的实现是否是正确的方案,所以向您请教。
首先我使用SelectionArea搭配SelectionListener就能拿到选中的文案startOffset和endOffset,参考官网的demo实现:https://api.flutter.dev/flutter/widgets/SelectionListener-class.html
但是这里的startOffset和endOffset对应的位置是将md渲染后的位置,而不是md原文中的位置,所以我不能在md原文中直接使用startOffset和endOffset去匹配进行高亮渲染。
所以我需要在渲染时将startOffset和endOffset位置对应的文案找出来,然后进行高亮。
我观察到MarkdownWidget中的textGenerator会在每渲染一段文本就会触发里面的onAccepted方法一次,拿到文本,累积收集每个文本相对于全局的开始位置和结束位置。
然后我就可以知道选中的高亮文本的startOffset和endOffset是否在当前onAccepted触发时的文本范围内。
如果是在范围内,那么我就将当前文本进行切割,将高亮的部分切割出来。大概代码如下:
MarkdownWidget(
data: _markdownText,
selectable: false,
markdownGenerator: MarkdownGenerator(
textGenerator:
(node, config, visitor) => CustomTextNode(
//...省略
),
),
)
int offset = 0;
class CustomTextNode extends ElementNode {
final String text;
CustomTextNode()
@override
void onAccepted(SpanNode parent) {
final textStyle = config.p.textStyle.merge(parentStyle);
children.clear();
startIndex = offset;
offset += getTextLength();
int endIndex = startIndex + getTextLength();
// range为高亮选中的范围
// 情况1:选中文本完全在当前文本块内
if (range.startOffset >= startIndex && range.endOffset <= endIndex) {
// 添加高亮前的普通文本
if (range.startOffset > startIndex) {
final beforeText = text.substring(
startIndex - startIndex,
range.startOffset - startIndex,
);
accept(TextNode(text: beforeText, style: textStyle));
}
// 添加高亮文本
final highlightText = text.substring(
range.startOffset - startIndex,
range.endOffset - startIndex,
);
accept(
// 这是一个高亮的TextSpan
CustomWidgetNode(
text: highlightText,
style: highlightStyle,
onTap: () => handleHighlightTap(highlightId),
),
);
// 添加高亮后的普通文本
// ...省略
}
}
}
上面的方案可以实现我想要的高亮效果,但是有很多问题。比如如果是”公式”那么就不会触发textGenerator中的onAccepted方法,或者是html好像也不会触发,等等等各种情况。
想请教您我的方案是否可行,是否还有其他更佳的方案可以在渲染时去匹配高亮选中文案的startOffset和endOffse。
再次感谢您的付出!!!
