flutter_widget_from_html
flutter_widget_from_html copied to clipboard
scrollToAnchor not work for headers with custom widgets
Hi, how to preserve the scrollToAnchor behavior for the headers when use a custom widget?
The use case can be to make the title clickable and show a link button like a lot of webs.
In the following example when you register a WidgetFactory with a BuildOp for the header the scrolToAnchor it does not work, if you comment the factoryBuilder you can see the expected behavior.
So, how can I do it?
Thank you
import 'package:flutter/material.dart';
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: HtmlDemo(),
);
}
}
class HtmlDemo extends StatefulWidget {
const HtmlDemo({super.key});
@override
State<HtmlDemo> createState() => _HtmlDemoState();
}
class _HtmlDemoState extends State<HtmlDemo> {
final htmlKey = GlobalKey<HtmlWidgetState>();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SingleChildScrollView(
child: HtmlWidget(
html,
key: htmlKey,
// Comment to see the scroll to anchor working
factoryBuilder: _MyWidgetFactory.new,
),
),
Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ElevatedButton(
onPressed: () {
htmlKey.currentState?.scrollToAnchor('h1');
},
child: const Text('Go to H1'),
),
ElevatedButton(
onPressed: () {
htmlKey.currentState?.scrollToAnchor('h2');
},
child: const Text('Go to H2'),
),
],
),
),
],
),
);
}
}
class _MyWidgetFactory extends WidgetFactory {
final headerOp = BuildOp(
onRenderBlock: (tree, placeholder) {
return Header(text: tree.element.text);
},
);
@override
void parse(BuildTree tree) {
final e = tree.element;
if (e.localName == 'h1' || e.localName == 'h2') {
tree.register(headerOp);
return;
}
return super.parse(tree);
}
}
class Header extends StatelessWidget {
const Header({
super.key,
required this.text,
});
final String text;
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () {
// Some stuff like update url with the id
},
child: Text(text),
);
}
}
final html = '''
<h1 id="h1">Heading 1</h1>
<p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p>
<p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p>
<p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p>
<p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p>
<p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p>
<p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p>
<p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p>
<p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p>
<p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p>
<p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p>
<p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p>
<p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p><p>X</p>
<h2 id="h2">Heading 2</h2>
''';
Can you remove the early return here?
@override
void parse(BuildTree tree) {
final e = tree.element;
if (e.localName == 'h1' || e.localName == 'h2') {
tree.register(headerOp);
return; // <- this one
}
return super.parse(tree);
}
You didn't allow the super WidgetFactory to parse the tree so the id attribute didn't register -> scrollToAnchor cannot see the #h1 to scroll.