Sub6Resources / flutter_html

A Flutter widget for rendering static html as Flutter widgets (Will render over 80 different html tags!)
https://pub.dev/packages/flutter_html
MIT License
1.79k stars 858 forks source link

[FEATURE] Scroll to anchor for inline elements #1082

Open giorgio79 opened 2 years ago

giorgio79 commented 2 years ago

Hello,

I am trying to scroll to an HTML anchor with AnchorKey.forId call but it does not seem to be working. I am providing a full example here with a large HTML that has a "TESTING" a anchor towards the end. When clicking on the Button to scroll nothing happens. Can you please help?

import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';

class HTMLTest extends StatefulWidget {
  HTMLTest({Key? key}) : super(key: key);

  @override
  State<HTMLTest> createState() => _HTMLTestState();
}

class _HTMLTestState extends State<HTMLTest> {
  GlobalKey htmlKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        child: Html(
            anchorKey: htmlKey,
            data:
                '<div id="lipsum"><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer sit amet lobortis lectus, vitae cursus sapien. Quisque posuere placerat vulputate. Interdum et malesuada fames ac ante ipsum primis in faucibus. Curabitur imperdiet velit in elit efficitur, ac tempus eros egestas. Aliquam eget interdum velit, eu viverra enim. Fusce sem dolor, rutrum tempus tristique ut, aliquam semper eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce dictum, nisi at porttitor placerat, ex risus dignissim augue, vitae aliquet nisl ex in dolor. Fusce faucibus orci eu dui porta pellentesque. Quisque ornare ligula in dolor ullamcorper, a luctus ipsum maximus. Maecenas est sem, hendrerit vitae erat sed, facilisis ornare tellus. Cras tortor mi, feugiat pretium pulvinar sit amet, aliquam sed enim. Vivamus finibus mauris et erat sollicitudin, vitae condimentum nisl feugiat. Quisque luctus ligula id ipsum ultrices dignissim. Integer mattis scelerisque felis. Morbi dictum massa at nunc tristique mattis.</p><p>Maecenas ac ultricies felis, id dignissim nibh. Etiam in neque mauris. Fusce ullamcorper, nulla in elementum bibendum, nisi dolor imperdiet magna, vel pulvinar tellus quam vel tellus. Nulla malesuada diam eros, eget pulvinar nisl laoreet a. In commodo quam mauris, nec congue metus tincidunt a. Vestibulum vitae fermentum justo, laoreet dictum arcu. Suspendisse quis enim nisi.</p><p>Etiam dictum finibus leo id ultrices. Nunc ornare risus rutrum leo iaculis, eu hendrerit eros molestie. Phasellus massa risus, interdum ut felis ut, tristique feugiat sem. Vivamus quis faucibus tortor, in tempor odio. In hac habitasse platea dictumst. In eu turpis in leo bibendum ornare. Pellentesque ut eros sit amet libero porttitor finibus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut ac iaculis leo. Nam ut dui id nulla porta convallis.</p><p>Maecenas fermentum ipsum elit, porta ornare sem aliquet eget. Proin id commodo odio, et ultricies libero. Maecenas eget sodales nibh. Fusce interdum velit luctus scelerisque mattis. Nunc ut vulputate dolor. Sed lacus lorem, aliquet maximus commodo quis, posuere sit amet ligula. Cras volutpat, orci id commodo efficitur, felis erat gravida lorem, vitae consequat felis justo sed felis.</p><p>Duis vitae accumsan nisi. Donec placerat, libero vitae accumsan auctor, est velit luctus magna, porttitor placerat tortor ex ac purus. In hac habitasse platea dictumst. Suspendisse ac nunc venenatis nulla feugiat egestas. Cras a neque sed augue malesuada posuere. Etiam ultricies orci a neque efficitur blandit. Nunc ac auctor leo. Nunc lacinia sem in justo egestas sollicitudin. Ut ac mi maximus, sollicitudin lorem ut, dictum augue. Proin vestibulum nisl eu ullamcorper accumsan. Praesent ornare dui eu justo consectetur, vel sollicitudin est interdum. Donec sodales, tortor nec porttitor porta, dui turpis sodales libero, in pharetra lectus quam sed velit. Cras pharetra id turpis ac fringilla. Nunc lacus felis, tempor eu urna ac, tincidunt rutrum nunc.</p><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer sit amet lobortis lectus, vitae cursus sapien. Quisque posuere placerat vulputate. Interdum et malesuada fames ac ante ipsum primis in faucibus. Curabitur imperdiet velit in elit efficitur, ac tempus eros egestas. Aliquam eget interdum velit, eu viverra enim. Fusce sem dolor, rutrum tempus tristique ut, aliquam semper eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce dictum, nisi at porttitor placerat, ex risus dignissim augue, vitae aliquet nisl ex in dolor. Fusce faucibus orci eu dui porta pellentesque. Quisque ornare ligula in dolor ullamcorper, a luctus ipsum maximus. Maecenas est sem, hendrerit vitae erat sed, facilisis ornare tellus. Cras tortor mi, feugiat pretium pulvinar sit amet, aliquam sed enim. Vivamus finibus mauris et erat sollicitudin, vitae condimentum nisl feugiat. Quisque luctus ligula id ipsum ultrices dignissim. Integer mattis scelerisque felis. Morbi dictum massa at nunc tristique mattis.</p><p>Maecenas ac ultricies felis, id dignissim nibh. Etiam in neque mauris. Fusce ullamcorper, nulla in elementum bibendum, nisi dolor imperdiet magna, vel pulvinar tellus quam vel tellus. Nulla malesuada diam eros, eget pulvinar nisl laoreet a. In commodo quam mauris, nec congue metus tincidunt a. Vestibulum vitae fermentum justo, laoreet dictum arcu. Suspendisse quis enim nisi.</p><p>Etiam dictum finibus leo id ultrices. Nunc ornare risus rutrum leo iaculis, eu hendrerit eros molestie. Phasellus massa risus, interdum ut felis ut, tristique feugiat sem. Vivamus quis faucibus tortor, in tempor odio. In hac habitasse platea dictumst. In eu turpis in leo bibendum ornare. Pellentesque ut eros sit amet libero porttitor finibus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut ac iaculis leo. Nam ut dui id nulla porta convallis.</p><p>Maecenas fermentum ipsum elit, porta ornare sem aliquet eget. Proin id commodo odio, et ultricies libero. Maecenas eget sodales nibh. Fusce interdum velit luctus scelerisque mattis. Nunc ut vulputate dolor. Sed lacus lorem, aliquet maximus commodo quis, posuere sit amet ligula. Cras volutpat, orci id commodo efficitur, felis erat gravida lorem, vitae consequat felis justo sed felis.</p><p>Duis vitae accumsan nisi. Donec placerat, libero vitae accumsan auctor, est velit luctus magna, porttitor placerat tortor ex ac purus. In hac habitasse platea dictumst. Suspendisse ac nunc venenatis nulla feugiat egestas. Cras a neque sed augue malesuada posuere. Etiam ultricies orci a neque efficitur blandit. Nunc ac auctor leo. Nunc lacinia sem in justo egestas sollicitudin. Ut ac mi maximus, sollicitudin lorem ut, <a id="TESTING" name="TESTING">dictum augue</a>. Proin vestibulum nisl eu ullamcorper accumsan. Praesent ornare dui eu justo consectetur, vel sollicitudin est interdum. Donec sodales, tortor nec porttitor porta, dui turpis sodales libero, in pharetra lectus quam sed velit. Cras pharetra id turpis ac fringilla. Nunc lacus felis, tempor eu urna ac, tincidunt rutrum nunc.</p></div>'),
      ),
      floatingActionButton: FloatingActionButton.extended(
          //elevation: 0.0,
          label: const Text("Scroll"),
          icon: const Icon(Icons.search),
          onPressed: () {
            final anchorContext =
                AnchorKey.forId(htmlKey, "TESTING")?.currentContext;
            if (anchorContext != null) {
              Scrollable.ensureVisible(anchorContext);
            } else {
              print("Anchor context null");
            }

            setState(() {});
          }),
    );
  }
}
erickok commented 2 years ago

Seems to be working in our example app. Make sure to use a 'constant' anchorKey.

new Scaffold(
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.arrow_downward),
        onPressed: () {
          final anchorContext = AnchorKey.forId(staticKey, "bottom")?.currentContext;
          if (anchorContext != null) {
            Scrollable.ensureVisible(anchorContext);
          }
        },
      ),
      body: SingleChildScrollView(
        child: Html(
          anchorKey: staticKey,
          data: htmlData,
        ),
      ),
    );

And that you update to release 3.0.0-alpha.5.

giorgio79 commented 2 years ago

Thx Eric! Ah, the example is really nice, we need to promote the link in the package description https://github.com/Sub6Resources/flutter_html/blob/master/example/lib/main.dart

I noticed the scrolling only works if the anchor is a "p" tag. Tried replacing it with a "span" or an "a" tag but no candy.

PS also tried switching to div, and plain div works, but as soon as I add inline it stops working <div id='bottom' style='color:orange; display:inline'>HEHEHE</div>

erickok commented 2 years ago

Ah yeah it might currently only work on block elements. Let me see if that is something I can fix.

giorgio79 commented 2 years ago

How are you getting along Eric? I was looking at the code

https://github.com/Sub6Resources/flutter_html/search?q=AnchorKey

and notice AnchorKey is added replaced_element.dart "Wrap" and layout_element.dart "ExpansionTile". Would it be adding a similar line of code to the rest of the elements created by flutter_html?

erickok commented 2 years ago

Yes, basically we have to add the key to all such elements but it's not quite so simple I think (without deep diving yet) because inline elements don't have a WidgetSpan and InlineSpan doesn't have a key to attach to I think.

giorgio79 commented 2 years ago

Happy to chip in 20 bucks :)