From 166a8cb8bbb8df862b680771294ad753f55a5b64 Mon Sep 17 00:00:00 2001 From: Vatsal Tanna Date: Mon, 31 May 2021 19:20:21 +0530 Subject: [PATCH] :sparkles: add overlay padding --- example/assets/simform.png | Bin 2059 -> 5352 bytes example/lib/main.dart | 3 +++ lib/src/get_position.dart | 29 ++++++++++++++------- lib/src/showcase.dart | 51 +++++++++++++++++++++---------------- 4 files changed, 52 insertions(+), 31 deletions(-) diff --git a/example/assets/simform.png b/example/assets/simform.png index 1122429a2ef4ebf3f1420306907384f944b1addb..ef4a996e3fd4c19b5235ed634048cab7e7bbb684 100644 GIT binary patch literal 5352 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 ZvE!AMjs}@FDM?<%=afID#VhjXzW{H_we|o2 diff --git a/example/lib/main.dart b/example/lib/main.dart index faa549bc..09cda873 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -14,6 +14,7 @@ class MyApp extends StatelessWidget { theme: ThemeData( primarySwatch: Colors.blue, ), + debugShowCheckedModeBanner: false, home: Scaffold( body: ShowCaseWidget( onStart: (index, key) { @@ -56,6 +57,7 @@ class _MailPageState extends State { @override Widget build(BuildContext context) { return Scaffold( + appBar: AppBar(), body: SafeArea( child: ListView( children: [ @@ -98,6 +100,7 @@ class _MailPageState extends State { ), ), Showcase( + overlayPadding: EdgeInsets.all(5), key: _two, title: 'Profile', description: diff --git a/lib/src/get_position.dart b/lib/src/get_position.dart index 5eda21a7..d7ef1d5f 100644 --- a/lib/src/get_position.dart +++ b/lib/src/get_position.dart @@ -29,8 +29,15 @@ import 'package:flutter/material.dart'; class GetPosition { final GlobalKey? key; + final EdgeInsets padding; + final double? screenWidth; + final double? screenHeight; - GetPosition({this.key}); + GetPosition( + {this.key, + this.padding = EdgeInsets.zero, + this.screenWidth, + this.screenHeight}); Rect getRect() { final box = key!.currentContext!.findRenderObject() as RenderBox; @@ -40,10 +47,14 @@ class GetPosition { box.size.bottomRight(box.localToGlobal(const Offset(0.0, 0.0))); final rect = Rect.fromLTRB( - topLeft.dx, - topLeft.dy, - bottomRight.dx, - bottomRight.dy, + topLeft.dx - padding.left < 0 ? 0 : topLeft.dx - padding.left, + topLeft.dy - padding.top < 0 ? 0 : topLeft.dy - padding.top, + bottomRight.dx + padding.right > screenWidth! + ? screenWidth! + : bottomRight.dx + padding.right, + bottomRight.dy + padding.bottom > screenHeight! + ? screenHeight! + : bottomRight.dy + padding.bottom, ); return rect; } @@ -53,21 +64,21 @@ class GetPosition { final box = key!.currentContext!.findRenderObject() as RenderBox; final bottomRight = box.size.bottomRight(box.localToGlobal(const Offset(0.0, 0.0))); - return bottomRight.dy; + return bottomRight.dy + padding.bottom; } ///Get the top position of the widget double getTop() { final box = key!.currentContext!.findRenderObject() as RenderBox; final topLeft = box.size.topLeft(box.localToGlobal(const Offset(0.0, 0.0))); - return topLeft.dy; + return topLeft.dy - padding.top; } ///Get the left position of the widget double getLeft() { final box = key!.currentContext!.findRenderObject() as RenderBox; final topLeft = box.size.topLeft(box.localToGlobal(const Offset(0.0, 0.0))); - return topLeft.dx; + return topLeft.dx - padding.left; } ///Get the right position of the widget @@ -75,7 +86,7 @@ class GetPosition { final box = key!.currentContext!.findRenderObject() as RenderBox; final bottomRight = box.size.bottomRight(box.localToGlobal(const Offset(0.0, 0.0))); - return bottomRight.dx; + return bottomRight.dx + padding.right; } double getHeight() { diff --git a/lib/src/showcase.dart b/lib/src/showcase.dart index 1927d725..cc4f72b3 100644 --- a/lib/src/showcase.dart +++ b/lib/src/showcase.dart @@ -60,27 +60,29 @@ class Showcase extends StatefulWidget { final VoidCallback? onTargetClick; final bool? disposeOnTap; final bool disableAnimation; + final EdgeInsets overlayPadding; - const Showcase({ - required this.key, - required this.child, - this.title, - required this.description, - this.shapeBorder, - this.overlayColor = Colors.black, - this.overlayOpacity = 0.75, - this.titleTextStyle, - this.descTextStyle, - this.showcaseBackgroundColor = Colors.white, - this.textColor = Colors.black, - this.showArrow = true, - this.onTargetClick, - this.disposeOnTap, - this.animationDuration = const Duration(milliseconds: 2000), - this.disableAnimation = false, - this.contentPadding = const EdgeInsets.symmetric(vertical: 8), - this.onToolTipClick, - }) : height = null, + const Showcase( + {required this.key, + required this.child, + this.title, + required this.description, + this.shapeBorder, + this.overlayColor = Colors.black, + this.overlayOpacity = 0.75, + this.titleTextStyle, + this.descTextStyle, + this.showcaseBackgroundColor = Colors.white, + this.textColor = Colors.black, + this.showArrow = true, + this.onTargetClick, + this.disposeOnTap, + this.animationDuration = const Duration(milliseconds: 2000), + this.disableAnimation = false, + this.contentPadding = const EdgeInsets.symmetric(vertical: 8), + this.onToolTipClick, + this.overlayPadding = EdgeInsets.zero}) + : height = null, width = null, container = null, assert(overlayOpacity >= 0.0 && overlayOpacity <= 1.0, @@ -116,6 +118,7 @@ class Showcase extends StatefulWidget { this.animationDuration = const Duration(milliseconds: 2000), this.disableAnimation = false, this.contentPadding = const EdgeInsets.symmetric(vertical: 8), + this.overlayPadding = EdgeInsets.zero, }) : showArrow = false, onToolTipClick = null, assert(overlayOpacity >= 0.0 && overlayOpacity <= 1.0, @@ -154,8 +157,6 @@ class _ShowcaseState extends State with TickerProviderStateMixin { parent: _slideAnimationController, curve: Curves.easeInOut, ); - - position = GetPosition(key: widget.key); } @override @@ -167,6 +168,12 @@ class _ShowcaseState extends State with TickerProviderStateMixin { @override void didChangeDependencies() { super.didChangeDependencies(); + position ??= GetPosition( + key: widget.key, + padding: widget.overlayPadding, + screenWidth: MediaQuery.of(context).size.width, + screenHeight: MediaQuery.of(context).size.height, + ); showOverlay(); }