diff --git a/lib/common/widgets/text/paragraph.dart b/lib/common/widgets/text/paragraph.dart index 442a51ea..d0cc018c 100644 --- a/lib/common/widgets/text/paragraph.dart +++ b/lib/common/widgets/text/paragraph.dart @@ -78,6 +78,7 @@ class RenderParagraph extends RenderBox Color? selectionColor, SelectionRegistrar? registrar, required Color primary, + VoidCallback? onShowMore, }) : assert(text.debugAssertIsValid()), assert( maxLines == null || @@ -93,6 +94,7 @@ class RenderParagraph extends RenderBox _softWrap = softWrap, _overflow = overflow, _selectionColor = selectionColor, + _onShowMore = onShowMore, _textPainter = TextPainter( text: text, textAlign: textAlign, @@ -294,6 +296,8 @@ class RenderParagraph extends RenderBox _disposeSelectableFragments(); _textPainter.dispose(); _textIntrinsicsCache?.dispose(); + _tapGestureRecognizer?.dispose(); + _tapGestureRecognizer = null; _morePainter?.dispose(); _morePainter = null; super.dispose(); @@ -553,6 +557,16 @@ class RenderParagraph extends RenderBox @override @protected bool hitTestChildren(BoxHitTestResult result, {required Offset position}) { + if (_morePainter case final textPainter?) { + late final height = _textPainter.height; + if (position.dx < textPainter.width && + position.dy > height && + position.dy < height + textPainter.height) { + result.add(HitTestEntry(_moreTextSpan)); + return true; + } + } + final GlyphInfo? glyph = _textPainter.getClosestGlyphForOffset(position); // The hit-test can't fall through the horizontal gaps between visually // adjacent characters on the same line, even with a large letter-spacing or @@ -680,9 +694,20 @@ class RenderParagraph extends RenderBox } } + VoidCallback? _onShowMore; + set onShowMore(VoidCallback? onShowMore) { + _onShowMore = onShowMore; + _tapGestureRecognizer?.onTap = onShowMore; + } + + TapGestureRecognizer? _tapGestureRecognizer; + TapGestureRecognizer get _effectiveTapRecognizer => + _tapGestureRecognizer ??= TapGestureRecognizer()..onTap = _onShowMore; + TextSpan get _moreTextSpan => TextSpan( style: text.style!.copyWith(color: _primary), text: '查看更多', + recognizer: _effectiveTapRecognizer, ); TextPainter? _morePainter; diff --git a/lib/common/widgets/text/rich_text.dart b/lib/common/widgets/text/rich_text.dart index 6d3b67f4..97f96d55 100644 --- a/lib/common/widgets/text/rich_text.dart +++ b/lib/common/widgets/text/rich_text.dart @@ -114,6 +114,7 @@ class RichText extends MultiChildRenderObjectWidget { this.textHeightBehavior, this.selectionRegistrar, this.selectionColor, + this.onShowMore, }) : assert(maxLines == null || maxLines > 0), assert(selectionRegistrar == null || selectionColor != null), assert( @@ -228,6 +229,8 @@ class RichText extends MultiChildRenderObjectWidget { /// widgets. final Color? selectionColor; + final VoidCallback? onShowMore; + @override RenderParagraph createRenderObject(BuildContext context) { assert(textDirection != null || debugCheckHasDirectionality(context)); @@ -246,6 +249,7 @@ class RichText extends MultiChildRenderObjectWidget { registrar: selectionRegistrar, selectionColor: selectionColor, primary: Theme.of(context).colorScheme.primary, + onShowMore: onShowMore, ); } @@ -266,7 +270,8 @@ class RichText extends MultiChildRenderObjectWidget { ..locale = locale ?? Localizations.maybeLocaleOf(context) ..registrar = selectionRegistrar ..selectionColor = selectionColor - ..primary = Theme.of(context).colorScheme.primary; + ..primary = Theme.of(context).colorScheme.primary + ..onShowMore = onShowMore; } @override diff --git a/lib/common/widgets/text/text.dart b/lib/common/widgets/text/text.dart index d8a7d945..632e11f6 100644 --- a/lib/common/widgets/text/text.dart +++ b/lib/common/widgets/text/text.dart @@ -174,6 +174,7 @@ class Text extends StatelessWidget { this.textWidthBasis, this.textHeightBehavior, this.selectionColor, + this.onShowMore, }) : textSpan = null, assert( textScaler == null || textScaleFactor == null, @@ -211,6 +212,7 @@ class Text extends StatelessWidget { this.textWidthBasis, this.textHeightBehavior, this.selectionColor, + this.onShowMore, }) : data = null, assert( textScaler == null || textScaleFactor == null, @@ -349,6 +351,8 @@ class Text extends StatelessWidget { /// (semi-transparent grey). final Color? selectionColor; + final VoidCallback? onShowMore; + @override Widget build(BuildContext context) { final DefaultTextStyle defaultTextStyle = DefaultTextStyle.of(context); @@ -435,6 +439,7 @@ class Text extends StatelessWidget { text: data, children: textSpan != null ? [textSpan!] : null, ), + onShowMore: onShowMore, ); } if (semanticsLabel != null || semanticsIdentifier != null) { diff --git a/lib/pages/dynamics/widgets/content_panel.dart b/lib/pages/dynamics/widgets/content_panel.dart index a0a0df62..ac43da37 100644 --- a/lib/pages/dynamics/widgets/content_panel.dart +++ b/lib/pages/dynamics/widgets/content_panel.dart @@ -4,6 +4,7 @@ import 'package:PiliPlus/common/widgets/image/custom_grid_view.dart'; import 'package:PiliPlus/common/widgets/text/text.dart' as custom_text; import 'package:PiliPlus/models/dynamics/result.dart'; import 'package:PiliPlus/pages/dynamics/widgets/rich_node_panel.dart'; +import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -84,6 +85,7 @@ Widget content( : const TextStyle(fontSize: 14), richNodes, maxLines: isSave ? null : 6, + onShowMore: () => PageUtils.pushDynDetail(item, isPush: true), ), if (pics?.isNotEmpty == true) CustomGridView(