From c05fb27cd7f81fdc3d5754b200233ec63b0463c8 Mon Sep 17 00:00:00 2001 From: vinothvino42 Date: Tue, 28 Nov 2023 19:15:11 +0530 Subject: [PATCH 1/2] feat: add a functionality to remove focus node when tapping non interactive elements in the page --- assets/schema/ensemble_schema.json | 4 +++ lib/framework/view/page.dart | 51 ++++++++++++++++-------------- lib/widget/helpers/unfocus.dart | 27 ++++++++++++++++ 3 files changed, 59 insertions(+), 23 deletions(-) create mode 100644 lib/widget/helpers/unfocus.dart diff --git a/assets/schema/ensemble_schema.json b/assets/schema/ensemble_schema.json index 63dc88ac1..9889a3df7 100644 --- a/assets/schema/ensemble_schema.json +++ b/assets/schema/ensemble_schema.json @@ -166,6 +166,10 @@ "type": "boolean", "description": "Specify if the content of this screen is scrollable with a global scrollbar. Using this also allow you to customize the scrolling experience of the header." }, + "unfocus": { + "type": "boolean", + "description": "Specify if the keyboard should dismissed automatically when tapping in the non interactive widgets. Default (false)" + }, "showNavigationIcon": { "type": "boolean", "description": "For a screen with header, the App will automatically show the Menu, Back, or Close icon (for modal screen) before the title. On modal screen without the header, the Close icon will be shown. Set this flag to false if you wish to hide the icons and handle the navigation yourself." diff --git a/lib/framework/view/page.dart b/lib/framework/view/page.dart index 9d48f4e99..32ed41bd6 100644 --- a/lib/framework/view/page.dart +++ b/lib/framework/view/page.dart @@ -19,6 +19,7 @@ import 'package:ensemble/page_model.dart'; import 'package:ensemble/screen_controller.dart'; import 'package:ensemble/util/utils.dart'; import 'package:ensemble/widget/helpers/controllers.dart'; +import 'package:ensemble/widget/helpers/unfocus.dart'; import 'package:ensemble/widget/helpers/widgets.dart'; import 'package:flutter/material.dart'; @@ -409,29 +410,33 @@ class PageState extends State Widget rtn = DataScopeWidget( scopeManager: _scopeManager, - child: Scaffold( - resizeToAvoidBottomInset: true, - // slight optimization, if body background is set, let's paint - // the entire screen including the Safe Area - backgroundColor: backgroundColor, - - // appBar is inside CustomScrollView if defined - appBar: fixedAppBar, - body: isScrollableView - ? buildScrollablePageContent(hasDrawer) - : buildFixedPageContent(fixedAppBar != null), - bottomNavigationBar: _bottomNavBar, - drawer: _drawer, - endDrawer: _endDrawer, - bottomSheet: _buildFooter( - _scopeManager, - widget._pageModel, - ), - floatingActionButton: closeModalButton, - floatingActionButtonLocation: - widget._pageModel.pageStyles?['navigationIconPosition'] == 'start' - ? FloatingActionButtonLocation.startTop - : FloatingActionButtonLocation.endTop), + child: Unfocus( + isUnfocus: widget._pageModel.pageStyles?['unfocus'] == true, + child: Scaffold( + resizeToAvoidBottomInset: true, + // slight optimization, if body background is set, let's paint + // the entire screen including the Safe Area + backgroundColor: backgroundColor, + + // appBar is inside CustomScrollView if defined + appBar: fixedAppBar, + body: isScrollableView + ? buildScrollablePageContent(hasDrawer) + : buildFixedPageContent(fixedAppBar != null), + bottomNavigationBar: _bottomNavBar, + drawer: _drawer, + endDrawer: _endDrawer, + bottomSheet: _buildFooter( + _scopeManager, + widget._pageModel, + ), + floatingActionButton: closeModalButton, + floatingActionButtonLocation: + widget._pageModel.pageStyles?['navigationIconPosition'] == + 'start' + ? FloatingActionButtonLocation.startTop + : FloatingActionButtonLocation.endTop), + ), ); // selectableText at the root diff --git a/lib/widget/helpers/unfocus.dart b/lib/widget/helpers/unfocus.dart new file mode 100644 index 000000000..1ca273363 --- /dev/null +++ b/lib/widget/helpers/unfocus.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; + +/// [Unfocus] - A gesture detector widget +/// +/// It hides the keyboard when tapping outside of non intractive widgetss +class Unfocus extends StatelessWidget { + const Unfocus({ + Key? key, + required this.child, + this.isUnfocus = true, + }) : super(key: key); + + final Widget child; + final bool isUnfocus; + + @override + Widget build(BuildContext context) { + // If false, Just return the child + if (!isUnfocus) return child; + + return Listener( + behavior: HitTestBehavior.opaque, + onPointerDown: (_) => FocusManager.instance.primaryFocus?.unfocus(), + child: child, + ); + } +} From 12f969341ce3dace75ad11f116e2e56a982c95c1 Mon Sep 17 00:00:00 2001 From: vinothvino42 Date: Wed, 6 Dec 2023 10:03:04 +0530 Subject: [PATCH 2/2] refactor: unfocus value assignment with utils --- lib/framework/view/page.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/framework/view/page.dart b/lib/framework/view/page.dart index 32ed41bd6..8a30afeea 100644 --- a/lib/framework/view/page.dart +++ b/lib/framework/view/page.dart @@ -411,7 +411,8 @@ class PageState extends State Widget rtn = DataScopeWidget( scopeManager: _scopeManager, child: Unfocus( - isUnfocus: widget._pageModel.pageStyles?['unfocus'] == true, + isUnfocus: Utils.getBool(widget._pageModel.pageStyles?['unfocus'], + fallback: false), child: Scaffold( resizeToAvoidBottomInset: true, // slight optimization, if body background is set, let's paint