diff --git a/example/lib/main.dart b/example/lib/main.dart index f43e0fc8..9abcaf5d 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -13,55 +13,31 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - final scrollController = ScrollController(); - return Center( - child: Container( - color: Colors.red, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 40), - child: MaterialApp( - title: 'Flutter ShowCase', - theme: ThemeData( - primaryColor: const Color(0xffEE5366), - ), - debugShowCheckedModeBanner: false, - home: Scaffold( - body: ShowCaseWidget( - enableAutoScroll: true, - onStart: (index, key) { - print('index -> $index'); - if(index == 2) { - WidgetsBinding.instance.addPostFrameCallback((_) { - // If showcase widget is at offset 1000 in the listview. - // If you don't know the exact position of the showcase widget, - // You can provide nearest possible location. - // - // In this case providing 990 instead of 1000 will work as well. - scrollController.jumpTo(990); - }); - } - log('onStart: $index, $key'); - }, - onComplete: (index, key) { - log('onComplete: $index, $key'); - if (index == 4) { - SystemChrome.setSystemUIOverlayStyle( - SystemUiOverlayStyle.light.copyWith( - statusBarIconBrightness: Brightness.dark, - statusBarColor: Colors.white, - ), - ); - } - }, - blurValue: 1, - builder: Builder( - builder: (context) => MailPage( - scrollController: scrollController, - )), - autoPlayDelay: const Duration(seconds: 3), - ), - ), - ), + return MaterialApp( + title: 'Flutter ShowCase', + theme: ThemeData( + primaryColor: const Color(0xffEE5366), + ), + debugShowCheckedModeBanner: false, + home: Scaffold( + body: ShowCaseWidget( + onStart: (index, key) { + log('onStart: $index, $key'); + }, + onComplete: (index, key) { + log('onComplete: $index, $key'); + if (index == 4) { + SystemChrome.setSystemUIOverlayStyle( + SystemUiOverlayStyle.light.copyWith( + statusBarIconBrightness: Brightness.dark, + statusBarColor: Colors.white, + ), + ); + } + }, + blurValue: 1, + builder: Builder(builder: (context) => const MailPage()), + autoPlayDelay: const Duration(seconds: 3), ), ), ); @@ -69,15 +45,10 @@ class MyApp extends StatelessWidget { } class MailPage extends StatefulWidget { - const MailPage({ - Key? key, - required this.scrollController, - }) : super(key: key); + const MailPage({Key? key}) : super(key: key); @override _MailPageState createState() => _MailPageState(); - - final ScrollController scrollController; } class _MailPageState extends State { @@ -88,6 +59,8 @@ class _MailPageState extends State { final GlobalKey _five = GlobalKey(); List mails = []; + final scrollController = ScrollController(); + @override void initState() { super.initState(); @@ -167,7 +140,7 @@ class _MailPageState extends State { @override void dispose() { - widget.scrollController.dispose(); + scrollController.dispose(); super.dispose(); } @@ -288,12 +261,11 @@ class _MailPageState extends State { const Padding(padding: EdgeInsets.only(top: 8)), Expanded( child: ListView.builder( - scrollDirection: Axis.horizontal, - controller: widget.scrollController, + controller: scrollController, physics: const BouncingScrollPhysics(), itemBuilder: (context, index) { - if (index == 3) { - return showcaseMailTile(_three, true, context, mails[index]); + if (index == 0) { + return showcaseMailTile(_three, true, context, mails.first); } return MailTile( mail: mails[index % mails.length], @@ -316,7 +288,7 @@ class _MailPageState extends State { /* reset ListView to ensure that the showcased widgets are * currently rendered so the showcased keys are available in the * render tree. */ - widget.scrollController.jumpTo(0); + scrollController.jumpTo(0); ShowCaseWidget.of(context) .startShowCase([_one, _two, _three, _four, _five]); }); @@ -432,127 +404,122 @@ class MailTile extends StatelessWidget { return Container( padding: const EdgeInsets.only(left: 6, right: 16, top: 8, bottom: 8), color: mail.isUnread ? const Color(0xffFFF6F7) : Colors.white, - child: SizedBox( - width: 400, - child: Row( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (showCaseDetail) - Showcase.withWidget( - key: showCaseKey!, - height: 50, - width: 140, - targetShapeBorder: const CircleBorder(), - targetBorderRadius: const BorderRadius.all( - Radius.circular(150), - ), - container: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - width: 45, - height: 45, - decoration: const BoxDecoration( - shape: BoxShape.circle, - color: Color(0xffFCD8DC), - ), - child: Center( - child: Text( - 'S', - style: TextStyle( - color: Theme.of(context).primaryColor, - fontWeight: FontWeight.bold, - fontSize: 16, - ), - ), - ), - ), - const SizedBox( - height: 10, - ), - const Text( - "Your sender's profile ", - style: TextStyle(color: Colors.white), - ) - ], - ), - child: const SAvatarExampleChild(), - ) - else - const SAvatarExampleChild(), - const Padding(padding: EdgeInsets.only(left: 8)), - Expanded( - child: Column( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (showCaseDetail) + Showcase.withWidget( + key: showCaseKey!, + height: 50, + width: 140, + targetShapeBorder: const CircleBorder(), + targetBorderRadius: const BorderRadius.all( + Radius.circular(150), + ), + container: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - mail.sender, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontWeight: mail.isUnread - ? FontWeight.bold - : FontWeight.normal, - fontSize: 17, + Container( + width: 45, + height: 45, + decoration: const BoxDecoration( + shape: BoxShape.circle, + color: Color(0xffFCD8DC), ), - ), - Text( - mail.sub, - overflow: TextOverflow.ellipsis, - style: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 16, + child: Center( + child: Text( + 'S', + style: TextStyle( + color: Theme.of(context).primaryColor, + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), ), ), - Text( - mail.msg, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontWeight: FontWeight.normal, - color: mail.isUnread - ? Theme.of(context).primaryColor - : Colors.black, - fontSize: 15, - ), + const SizedBox( + height: 10, ), + const Text( + "Your sender's profile ", + style: TextStyle(color: Colors.white), + ) ], ), + child: const SAvatarExampleChild(), ) - ], - ), - ), - SizedBox( - width: 50, - child: Column( - children: [ - const SizedBox( - height: 5, - ), - Text( - mail.date, - style: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 12, - color: Colors.grey, - ), - ), - const SizedBox( - height: 10, + else + const SAvatarExampleChild(), + const Padding(padding: EdgeInsets.only(left: 8)), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + mail.sender, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontWeight: mail.isUnread + ? FontWeight.bold + : FontWeight.normal, + fontSize: 17, + ), + ), + Text( + mail.sub, + overflow: TextOverflow.ellipsis, + style: const TextStyle( + fontWeight: FontWeight.normal, + fontSize: 16, + ), + ), + Text( + mail.msg, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontWeight: FontWeight.normal, + color: mail.isUnread + ? Theme.of(context).primaryColor + : Colors.black, + fontSize: 15, + ), + ), + ], ), - Icon( - mail.isUnread ? Icons.star : Icons.star_border, - color: - mail.isUnread ? const Color(0xffFBC800) : Colors.grey, + ) + ], + ), + ), + SizedBox( + width: 50, + child: Column( + children: [ + const SizedBox( + height: 5, + ), + Text( + mail.date, + style: const TextStyle( + fontWeight: FontWeight.normal, + fontSize: 12, + color: Colors.grey, ), - ], - ), + ), + const SizedBox( + height: 10, + ), + Icon( + mail.isUnread ? Icons.star : Icons.star_border, + color: mail.isUnread ? const Color(0xffFBC800) : Colors.grey, + ), + ], ), - ], - ), + ), + ], ), ); } diff --git a/lib/src/layout_overlays.dart b/lib/src/layout_overlays.dart index 26432335..197bd20e 100644 --- a/lib/src/layout_overlays.dart +++ b/lib/src/layout_overlays.dart @@ -43,37 +43,42 @@ typedef OverlayBuilderCallback = Widget Function( /// /// The [overlayBuilder] is invoked every time this Widget is rebuilt. /// -class AnchoredOverlay extends StatelessWidget { +class AnchoredOverlay extends StatefulWidget { final bool showOverlay; final OverlayBuilderCallback? overlayBuilder; final Widget? child; + final RenderObject? rootRenderObject; const AnchoredOverlay({ Key? key, this.showOverlay = false, this.overlayBuilder, this.child, + required this.rootRenderObject, }) : super(key: key); + @override + State createState() => _AnchoredOverlayState(); +} + +class _AnchoredOverlayState extends State { @override Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { return OverlayBuilder( - showOverlay: showOverlay, + showOverlay: widget.showOverlay, overlayBuilder: (overlayContext) { // To calculate the "anchor" point we grab the render box of // our parent Container and then we find the center of that box. final box = context.findRenderObject() as RenderBox; - final rootWidget = - context.findRootAncestorStateOfType>(); - final rootRenderObject = rootWidget?.context.findRenderObject(); + final topLeft = box.size.topLeft(box.localToGlobal( const Offset(0.0, 0.0), - ancestor: rootRenderObject)); + ancestor: widget.rootRenderObject)); final bottomRight = box.size.bottomRight(box.localToGlobal( const Offset(0.0, 0.0), - ancestor: rootRenderObject)); + ancestor: widget.rootRenderObject)); Rect anchorBounds; anchorBounds = (topLeft.dx.isNaN || topLeft.dy.isNaN || @@ -87,9 +92,10 @@ class AnchoredOverlay extends StatelessWidget { bottomRight.dy, ); final anchorCenter = box.size.center(topLeft); - return overlayBuilder!(overlayContext, anchorBounds, anchorCenter); + return widget.overlayBuilder!( + overlayContext, anchorBounds, anchorCenter); }, - child: child, + child: widget.child, ); }, ); diff --git a/lib/src/showcase.dart b/lib/src/showcase.dart index 6232d661..6cf4e043 100644 --- a/lib/src/showcase.dart +++ b/lib/src/showcase.dart @@ -382,9 +382,9 @@ class _ShowcaseState extends State { final rootWidget = context.findRootAncestorStateOfType>(); rootRenderObject = rootWidget?.context.findRenderObject(); - rootWidgetSize = (rootRenderObject as RenderBox).size; - - print('recalculated -> $rootWidgetSize'); + rootWidgetSize = rootWidget == null + ? MediaQuery.sizeOf(context) + : (rootRenderObject as RenderBox).size; }); } @@ -443,6 +443,7 @@ class _ShowcaseState extends State { Widget build(BuildContext context) { if (_enableShowcase) { return AnchoredOverlay( + rootRenderObject: rootRenderObject, overlayBuilder: (context, rectBound, offset) { final size = rootWidgetSize; position = GetPosition( diff --git a/lib/src/showcase_widget.dart b/lib/src/showcase_widget.dart index 630f7b43..7b192b86 100644 --- a/lib/src/showcase_widget.dart +++ b/lib/src/showcase_widget.dart @@ -149,11 +149,16 @@ class ShowCaseWidgetState extends State { @override void initState() { super.initState(); + initRootWidget(); + } + + void initRootWidget() { WidgetsBinding.instance.addPostFrameCallback((_) { - final rootWidget = - context.findRootAncestorStateOfType>(); + final rootWidget = context.findAncestorStateOfType>(); rootRenderObject = rootWidget?.context.findRenderObject(); - rootWidgetSize = (rootRenderObject as RenderBox).size; + rootWidgetSize = rootWidget == null + ? MediaQuery.of(context).size + : (rootRenderObject as RenderBox).size; }); } diff --git a/lib/src/tooltip_widget.dart b/lib/src/tooltip_widget.dart index fbd8dad0..1d57bcec 100644 --- a/lib/src/tooltip_widget.dart +++ b/lib/src/tooltip_widget.dart @@ -164,10 +164,8 @@ class _ToolTipWidgetState extends State var maxTextWidth = max(titleLength, descriptionLength); if (maxTextWidth > widget.screenSize!.width - tooltipScreenEdgePadding) { tooltipWidth = widget.screenSize!.width - tooltipScreenEdgePadding; - print('intool if tool $tooltipWidth'); } else { tooltipWidth = maxTextWidth + tooltipTextPadding; - print('intool else $tooltipWidth'); } } @@ -314,6 +312,12 @@ class _ToolTipWidgetState extends State _getTooltipWidth(); } + @override + void didUpdateWidget(covariant ToolTipWidget oldWidget) { + super.didUpdateWidget(oldWidget); + _getTooltipWidth(); + } + @override void dispose() { _movingAnimationController.dispose();