Vertical alignment between text and embed
Have you checked for an existing issue?
- [x] I have searched the existing issues
Flutter Quill Version
11.0.0
Steps to Reproduce
I would like to center the text vertically with embed blocks.
This question has been asked twice in #1067 [Web] [Mobile] [Desktop] Cannot vertically align custom component with the rest of the text and #1117 [Web], [Mobile] and [Desktop] Widgets vertical alignment along the text line
and in both cases has been closed as completed without explanation or solution. One of them links to a changelog entry that I could not find.
How can I achieve this?
Best Regards
Expected results
Be able to vertically align text with embeds
Actual results
text always aligned to the base of the embed
Additional Context
Screenshots / Video demonstration
[Attach media here]
Logs
[Paste logs here]
Can you pass to me some example code about the embed (it does not need to be equals)? I'll take a look and fix if needed.
This is a very simple example of an embed.
The text in the same line as the embed is aligned to the base of the embed, like it is shown in the images from #1067 and #1117. I could not find a way to change that vertical alignment
import 'dart:convert';
import 'package:catappadmin/extensions/quill_control_embed.dart';
import 'package:flutter/material.dart';
import 'package:flutter_quill/flutter_quill.dart';
abstract class ControlEmbed {
ControlEmbed();
String get type;
Map<String, dynamic> toJson() {
throw UnimplementedError('toJson() has not been implemented.');
}
static ControlEmbed fromJson(Map<String, dynamic> json) {
throw UnimplementedError('fromJson() has not been implemented.');
}
factory ControlEmbed.fromNode(String node) {
final json = jsonDecode(node);
return fromJson(json);
}
}
class SimpleIconEmbed extends ControlEmbed {
SimpleIconEmbed({required this.code, required this.size});
final int code;
final double size;
@override
String get type => 'simpleicon';
factory SimpleIconEmbed.fromNode(String node) {
final json = jsonDecode(node);
return SimpleIconEmbed.fromJson(json);
}
@override
factory SimpleIconEmbed.fromJson(Map<String, dynamic> json) {
return SimpleIconEmbed(
code: (json['code'] as num).toInt(),
size: (json['size'] as num).toDouble(),
);
}
@override
Map<String, dynamic> toJson() {
final json = {
'code': code,
'size': size,
};
return json;
}
}
class SimpleIconEmbedBuilder extends EmbedBuilder {
SimpleIconEmbedBuilder();
@override
String get key => 'simpleicon';
@override
bool get expanded => false;
@override
Widget build(
BuildContext context,
EmbedContext embedContext,
) {
final iconEmbed = SimpleIconEmbed.fromNode(embedContext.node.value.data);
final attributes = embedContext.node.style.attributes;
final attr = attributes['color'];
final color = attr?.value as Color?;
return GestureDetector(
child: Builder(builder: (context) {
return Icon(
IconData(iconEmbed.code, fontFamily: 'MaterialIcons'),
size: iconEmbed.size,
color: color,
);
}),
);
}
}
This code inserts the embed:
Future<void> addListTile(BuildContext context) async {
final iconEmbed = SimpleIconEmbed(size: 80, code: Icons.add_box.codePoint);
final data = jsonEncode(iconEmbed);
final block = Embeddable('simpleicon', data);
final index = quillController.selection.baseOffset;
final length = quillController.selection.extentOffset - index;
quillController
..skipRequestKeyboard = true
..replaceText(
index,
length,
block,
null,
)
..moveCursorToPosition(index + 1);
}
One of them links to a changelog entry that I could not find.
That's because the previous CHANGELOG has been achieved, the valid link now is: https://pub.dev/packages/flutter_quill/versions/10.8.5/changelog#702
One of them links to a changelog entry that I could not find.
That's because the previous CHANGELOG has been achieved, the valid link now is: https://pub.dev/packages/flutter_quill/versions/10.8.5/changelog#702
I did realize of that, but the old changelog does not have any #720 entry and I found nothing related to this issue
This is what I found:
Allow widgets to override widget span properties.
Hi, how to fix this then?
For anyone looking for the fix, try overriding buildWidgetSpan of your class that extends EmbedBuilder
@override
WidgetSpan buildWidgetSpan(Widget widget) {
return WidgetSpan(child: widget, alignment: PlaceholderAlignment.middle);
}
For anyone looking for the fix, try overriding buildWidgetSpan of your class that extends EmbedBuilder
@override WidgetSpan buildWidgetSpan(Widget widget) { return WidgetSpan(child: widget, alignment: PlaceholderAlignment.middle); }
Hi @keyur2maru.
buildWidgetSpan looks promissing; however, how can you make the vertical alignment selectable for each embed, given the function does not pass the EmbedContext?
I would like to make the vertical alignment a property of each embed.
Regards
Hi @pamafe1976
I am not sure if it is possible to dynamically set the vertical alignment for each embed that’s under selection. My use case did not require dynamic vertical alignment, so I did not explore that possibility.
Apparently there is no Attribute for vertical selection, so it may be not possible to apply to selection, but I could incorporate a variable within the Embed that holds the vertical alignment, and can be changed in the embed properties dialog. This requires a small change in buildWidgetSpan, so it passes the embedContext:
@override WidgetSpan buildWidgetSpan(Widget widget, EmbedContext embedContext) { final picture = PictureEmbed.fromNode(embedContext.node.value.data); return WidgetSpan(child: widget, alignment: VerticalAlign.values.byName(picture.valign).placeholder); }
The change is very simple, because buildWidgetSpan has only one reference inside text_line.dart, where it already uses the embedContext
I will create a PR for this soon.
Regards