-
Notifications
You must be signed in to change notification settings - Fork 79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a feature to allow WidgetSpan in annotation #70
base: master
Are you sure you want to change the base?
Conversation
It should be related with #25 |
What's the point of removing
|
Hi @maRci002, It is a scenario to be useful of the added feature. I understand that removing just WidgetSpan is too naive and there is no way to estimate the size of widget before rendering. ReadMoreText(
'@[{"key": {"inner":"test"}}] and @[{"key":"value"}]',
annotations: [
Annotation(
regExp: RegExp('@\\[(.+?)\\]'),
spanBuilder: ({required text, required textStyle}) {
return WidgetSpan(
child: Tooltip(
message: 'It is just tooltip',
child: Text(
'It is a widget',
style: TextStyle(height: 0),
),
),
);
},
),
],
style: TextStyle(color: Colors.red),
) |
I think instead of removing Note: The Here is an example of how import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('WidgetSpan Test'),
),
body: const Center(
child: TextPainterButton(),
),
),
);
}
}
class TextPainterButton extends StatelessWidget {
const TextPainterButton({super.key});
void _printTextLayout(BuildContext context) {
final defaultTextStyle = DefaultTextStyle.of(context);
var effectiveTextStyle = defaultTextStyle.style;
if (MediaQuery.boldTextOf(context)) {
effectiveTextStyle = effectiveTextStyle.merge(const TextStyle(fontWeight: FontWeight.bold));
}
final textScaler = MediaQuery.textScalerOf(context);
final textAlign = defaultTextStyle.textAlign ?? TextAlign.start;
final textDirection = Directionality.of(context);
final locale = Localizations.maybeLocaleOf(context);
final textWidthBasis = defaultTextStyle.textWidthBasis;
final textHeightBehavior = defaultTextStyle.textHeightBehavior ?? DefaultTextHeightBehavior.maybeOf(context);
final textPainter = TextPainter(
textAlign: textAlign,
textDirection: textDirection,
locale: locale,
textScaler: textScaler,
maxLines: 1,
textWidthBasis: textWidthBasis,
textHeightBehavior: textHeightBehavior,
);
const txt = 'It is a widget';
const widgetSpan = WidgetSpan(
child: Tooltip(
message: 'It is just tooltip',
child: Text(txt),
),
);
final widgetSpanText = TextSpan(
text: txt,
style: effectiveTextStyle,
);
textPainter.text = widgetSpanText;
textPainter.layout();
final widgetSpanSize = textPainter.size;
final widgetSpanPlaceHolderDimension = PlaceholderDimensions(
size: widgetSpanSize,
alignment: widgetSpan.alignment,
baseline: widgetSpan.baseline,
);
final span = TextSpan(
style: effectiveTextStyle.merge(const TextStyle(color: Colors.black, fontSize: 18)),
text: 'Hello, TextPainter!',
children: const [widgetSpan],
);
textPainter.text = span;
textPainter.setPlaceholderDimensions([widgetSpanPlaceHolderDimension]);
textPainter.layout();
print('Text size: ${textPainter.size}');
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => _printTextLayout(context),
child: const Text('Layout Text'),
);
}
}
|
I provide a widget size estimator. Size? _calculateWidgetSize(Widget widget) {
final child = InheritedTheme.captureAll(
context,
MediaQuery(
data: MediaQuery.of(context),
child: Material(
color: Colors.transparent,
child: widget,
),
),
);
final RenderRepaintBoundary repaintBoundary = RenderRepaintBoundary();
final platformDispatcher = WidgetsBinding.instance.platformDispatcher;
final fallBackView = platformDispatcher.views.first;
final view = View.maybeOf(context) ?? fallBackView;
Size logicalSize = view.physicalSize / view.devicePixelRatio; // Adapted
final RenderView renderView = RenderView(
view: view,
child: RenderPositionedBox(
alignment: Alignment.center, child: repaintBoundary),
configuration: ViewConfiguration(
// size: logicalSize,
logicalConstraints: BoxConstraints(
maxWidth: logicalSize.width,
maxHeight: logicalSize.height,
),
devicePixelRatio: 1.0,
),
);
final PipelineOwner pipelineOwner = PipelineOwner();
final BuildOwner buildOwner =
BuildOwner(focusManager: FocusManager(), onBuildScheduled: () {});
pipelineOwner.rootNode = renderView;
renderView.prepareInitialFrame();
final RenderObjectToWidgetElement<RenderBox> rootElement =
RenderObjectToWidgetAdapter<RenderBox>(
container: repaintBoundary,
child: Directionality(
textDirection: TextDirection.ltr,
child: child,
)).attachToRenderTree(
buildOwner,
);
buildOwner.buildScope(
rootElement,
);
buildOwner.finalizeTree();
pipelineOwner.flushLayout();
pipelineOwner.flushCompositingBits();
pipelineOwner.flushPaint();
return rootElement.size;
} |
_isTextSpan
.