mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-08-03 17:20:16 +08:00
150 lines
3.7 KiB
Dart
150 lines
3.7 KiB
Dart
import 'package:flutter/gestures.dart' show TapGestureRecognizer;
|
|
import 'package:flutter/rendering.dart'
|
|
show
|
|
Size,
|
|
Color,
|
|
Offset,
|
|
TextSpan,
|
|
TextStyle,
|
|
InlineSpan,
|
|
TextScaler,
|
|
TextPainter,
|
|
VoidCallback,
|
|
HitTestEntry,
|
|
RenderParagraph,
|
|
PaintingContext,
|
|
BoxHitTestResult,
|
|
RenderComparison;
|
|
|
|
class RenderParagraphMore extends RenderParagraph {
|
|
RenderParagraphMore(
|
|
super.text, {
|
|
super.textAlign,
|
|
required super.textDirection,
|
|
super.softWrap,
|
|
super.overflow,
|
|
// ignore: deprecated_member_use
|
|
super.textScaleFactor,
|
|
super.textScaler,
|
|
super.maxLines,
|
|
super.locale,
|
|
super.strutStyle,
|
|
super.textWidthBasis,
|
|
super.textHeightBehavior,
|
|
super.children,
|
|
super.selectionColor,
|
|
super.registrar,
|
|
required this._primary,
|
|
this._onShowMore,
|
|
});
|
|
|
|
Color _primary;
|
|
|
|
VoidCallback? _onShowMore;
|
|
set onShowMore(VoidCallback? onShowMore) {
|
|
if (_onShowMore != onShowMore) {
|
|
_onShowMore = onShowMore;
|
|
_tapGestureRecognizer?.onTap = onShowMore;
|
|
}
|
|
}
|
|
|
|
TapGestureRecognizer? _tapGestureRecognizer;
|
|
|
|
TextSpan _moreTextSpan([TextStyle? style]) => TextSpan(
|
|
style: (style ?? text.style!).copyWith(color: _primary),
|
|
text: '查看更多',
|
|
recognizer: _tapGestureRecognizer,
|
|
);
|
|
TextPainter? _morePainter;
|
|
|
|
bool didOverflowHeight = false;
|
|
|
|
@override
|
|
set textScaler(TextScaler value) {
|
|
if (textPainter.textScaler == value) {
|
|
return;
|
|
}
|
|
_morePainter
|
|
?..textScaler = value
|
|
..layout();
|
|
super.textScaler = value;
|
|
}
|
|
|
|
void setText(({InlineSpan text, Color primary}) params) {
|
|
final newText = params.text;
|
|
_primary = params.primary;
|
|
if (_morePainter != null) {
|
|
final textSpan = _moreTextSpan(newText.style);
|
|
switch (_morePainter!.text!.compareTo(textSpan)) {
|
|
case RenderComparison.paint:
|
|
_morePainter!.text = textSpan;
|
|
case RenderComparison.layout:
|
|
_morePainter!
|
|
..text = textSpan
|
|
..layout();
|
|
default:
|
|
}
|
|
}
|
|
super.text = newText;
|
|
}
|
|
|
|
@override
|
|
void performLayout() {
|
|
super.performLayout();
|
|
|
|
if (didOverflowHeight = textPainter.didExceedMaxLines) {
|
|
if (_onShowMore != null) {
|
|
_tapGestureRecognizer ??= TapGestureRecognizer()..onTap = _onShowMore;
|
|
}
|
|
_morePainter ??= TextPainter(
|
|
text: _moreTextSpan(),
|
|
textDirection: textDirection,
|
|
textScaler: textScaler,
|
|
locale: locale,
|
|
)..layout(maxWidth: constraints.maxWidth);
|
|
size = Size(
|
|
size.width,
|
|
constraints.constrainHeight(size.height + _morePainter!.height),
|
|
);
|
|
}
|
|
}
|
|
|
|
@override
|
|
void paint(PaintingContext context, Offset offset) {
|
|
super.paint(context, offset);
|
|
|
|
if (didOverflowHeight) {
|
|
_morePainter?.paint(
|
|
context.canvas,
|
|
offset + Offset(0, textPainter.height),
|
|
);
|
|
}
|
|
}
|
|
|
|
@override
|
|
bool hitTestChildren(BoxHitTestResult result, {required Offset position}) {
|
|
if (_tapGestureRecognizer != null) {
|
|
if (_morePainter != null) {
|
|
if (position.dx < _morePainter!.width) {
|
|
final height = textPainter.height;
|
|
if (position.dy > height &&
|
|
position.dy < height + _morePainter!.height) {
|
|
result.add(HitTestEntry(_morePainter!.text as TextSpan));
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return super.hitTestChildren(result, position: position);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_tapGestureRecognizer?.dispose();
|
|
_tapGestureRecognizer = null;
|
|
_morePainter?.dispose();
|
|
_morePainter = null;
|
|
super.dispose();
|
|
}
|
|
}
|