hidable
hidable copied to clipboard
Nested navigation hidable not responding
Hello, thanks for your job. If i have a nested navigation like this
Home Practice(StatefullWidget) -> DetailsPractice(StatefullWidget) Profile
in practice hirable it's ok but in detailPractice not responding .
I use go_router and i have this: final ScrollController _genericsSC = ScrollController()
i pass this _genericsSC into Practice and into DetailsPractice
I have a CustomScrollView into a Practice and into a DetailsPractice
if attach scrollController to CustomScrollView in Practice (and not in DetailsPractice) it's run in Practice and not responding in DetailsPractice: it's Ok
if attach scrollController in CustomScrollView in DetailsPractice (and not in Practice) it's run in DetailsPractice and not responding in Practice: it's Ok
But i don't understand why if i attach scrollController to CustomScrollView in Practice and in DetailsPractice, it's run in Practice and NOT responding in DetailsPractice 🤷🏻♂️
How to use in both StatefullWidget?
Thanks so much
Hi, first of all thanks for the issue. I'll take a deep look into issue and I'll respond back as soon as possible.
Hi, News? I tried to handle more Scrollview, but it wasn't a good idea. ;-)
Hello, apologies for the delay. We're currently experiencing a busy period, and we regret any inconvenience caused. We aim to address all open issues over the weekend and hope to provide you with feedback regarding your specific issue.
Hi @zoelounge, i've tested the way you described the issue, and actually couldn't reproduce. Can you share your code in order to make it simple to understand the way you use hidable?
I gonna need the widgets you mentioned and one-level up widget (where actually you display them). And also hidable version. Thanks.
Hi @theiskaa thanks for your replay.
This is my test code, please check it and tell me why do not run correctly:
When i pass ScrollController to RequestView it's ok but if i navigate on AboutView, passing the same scrollController to control hidable, the hidable not run because i have this error: "ScrollController attached to multiple scroll views."
Thanks in advanced ;-)
Code
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:go_router/go_router.dart';
import 'package:hidable/hidable.dart';
class AppRouter {
// ScrollController: for bottomNavBar that i pass into ohter widget to controll the scrool on always page
final ScrollController scrollController = ScrollController();
final _rootNavigatorKey = GlobalKey<NavigatorState>();
final _shellNavigatorHomeKey =
GlobalKey<NavigatorState>(debugLabel: 'shellHome');
final _shellNavigatorRequestsKey =
GlobalKey<NavigatorState>(debugLabel: 'shellRequests');
late final goRouter = GoRouter(
initialLocation: '/home',
navigatorKey: _rootNavigatorKey,
debugLogDiagnostics: true,
routes: [
StatefulShellRoute.indexedStack(
builder: (context, state, navigationShell) {
return ScaffoldWithNestedNavigation(
navigationShell: navigationShell,
scrollController: scrollController,
);
},
branches: [
//home
StatefulShellBranch(
navigatorKey: _shellNavigatorHomeKey,
routes: [
GoRoute(
path: '/home',
name: 'home',
pageBuilder: (context, GoRouterState state) => NoTransitionPage(
key: state.pageKey,
child: const HomeView(
label: 'Home',
),
),
),
],
),
//requests
StatefulShellBranch(
navigatorKey: _shellNavigatorRequestsKey,
routes: [
GoRoute(
path: '/requests',
name: 'requests',
pageBuilder: (context, state) => NoTransitionPage(
key: state.pageKey,
child: RequestView(
label: 'Request',
scrollController: scrollController,
),
),
routes: [
GoRoute(
// ZOE: La soluzione al problema di non avere la navbar
path: 'about',
name: 'about',
builder: (context, state) {
return About(
scrollController: scrollController,
);
},
),
]),
],
),
],
),
],
);
}
class ScaffoldWithNestedNavigation extends StatelessWidget {
const ScaffoldWithNestedNavigation({
Key? key,
required this.navigationShell,
required this.scrollController,
}) : super(
key: key ?? const ValueKey<String>('ScaffoldWithNestedNavigation'));
final StatefulNavigationShell navigationShell;
final ScrollController scrollController;
void _goBranch(int index) {
navigationShell.goBranch(
index,
initialLocation: index == navigationShell.currentIndex,
);
}
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
return ScaffoldWithNavigationBar(
body: navigationShell,
selectedIndex: navigationShell.currentIndex,
onDestinationSelected: _goBranch,
scrollController: scrollController,
navigationShell: navigationShell);
});
}
}
class ScaffoldWithNavigationBar extends StatelessWidget {
const ScaffoldWithNavigationBar({
super.key,
required this.body,
required this.selectedIndex,
required this.onDestinationSelected,
required this.scrollController,
required this.navigationShell,
});
final Widget body;
final int selectedIndex;
final ValueChanged<int> onDestinationSelected;
final ScrollController scrollController;
final StatefulNavigationShell navigationShell;
void _onItemTapped(int index) {
onDestinationSelected(index);
}
void animateScrollOnTop(ScrollController controller) {
controller.animateTo(
0.0,
curve: Curves.easeOut,
duration: const Duration(milliseconds: 300),
);
}
@override
Widget build(BuildContext context) {
if (kDebugMode) {
final location = GoRouterState.of(context).uri.toString();
print('goRouter Location $location');
}
return Scaffold(
resizeToAvoidBottomInset: true,
body: body,
bottomNavigationBar: SafeArea(
child: Hidable(
controller: scrollController,
child: BottomNavigationBar(
selectedFontSize: 12,
unselectedFontSize: 10,
selectedLabelStyle: const TextStyle(
color: Colors.black,
fontFamily: 'Outfit',
fontWeight: FontWeight.w400,
),
unselectedLabelStyle: const TextStyle(
color: Colors.green,
fontFamily: 'Outfit',
fontWeight: FontWeight.w400,
),
mouseCursor: SystemMouseCursors.grab,
type: BottomNavigationBarType.fixed,
backgroundColor: Colors.white,
currentIndex: selectedIndex,
elevation: 0,
showUnselectedLabels: true,
unselectedItemColor: Colors.blue,
selectedItemColor: Colors.orange,
onTap: (index) {
_onItemTapped(index);
},
items: const [
BottomNavigationBarItem(
icon: Icon(
Icons.home,
),
label: "Home",
activeIcon: Icon(
Icons.home,
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.question_answer,
),
label: "Richieste",
activeIcon: Icon(
Icons.question_answer,
),
),
],
),
),
),
);
}
}
////////////////////////////////// The Home View screen
class HomeView extends StatefulWidget {
const HomeView({
super.key,
required this.label,
});
/// The label to display in the center of the screen.
final String label;
@override
State<StatefulWidget> createState() => HomeViewState();
}
class HomeViewState extends State<HomeView> {
int _counter = 0;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('HomeView Screen - ${widget.label}'),
),
body: Center(
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text('Details for ${widget.label} - Counter: $_counter',
style: Theme.of(context).textTheme.titleLarge),
const Padding(
padding: EdgeInsets.all(4),
),
TextButton(
onPressed: () {
setState(() {
_counter++;
});
},
child: const Text('Increment counter'),
),
],
),
),
),
);
}
}
////////////////////////////////// The RequestView screen
class RequestView extends StatefulWidget {
final ScrollController scrollController;
const RequestView({
super.key,
required this.label,
required this.scrollController,
});
final String label;
@override
State<StatefulWidget> createState() => RequestViewState();
}
class RequestViewState extends State<RequestView> {
@override
void initState() {
super.initState();
}
@override
void dispose() {
widget.scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: GlobalKey(debugLabel: 'RequestViewKey'),
appBar: AppBar(
title: Text('RequestView Screen - ${widget.label}'),
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: CustomScrollView(
controller: widget.scrollController,
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => GestureDetector(
onTap: () {
context.goNamed("about");
},
child: Text("ELement = ${index + 1}"),
),
),
),
],
),
),
);
}
}
////////////////////////////////// The AboutView screen
class About extends StatefulWidget {
final ScrollController scrollController;
const About({
super.key,
required this.scrollController,
});
@override
State<About> createState() => _AboutState();
}
class _AboutState extends State<About> {
@override
void initState() {
super.initState();
}
@override
void dispose() {
widget.scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: GlobalKey(debugLabel: 'AboutViewKey'),
backgroundColor: Colors.white,
appBar: AppBar(
title: const Text(
'AboutView Screen',
style: TextStyle(color: Colors.redAccent),
),
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: CustomScrollView(
controller: widget
.scrollController, // here i have the error: "ScrollController attached to multiple scroll views."
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => GestureDetector(
onTap: () {
context.goNamed("about");
},
child: Text(
"ELement = ${index + 1}",
style: const TextStyle(color: Colors.redAccent),
),
),
),
),
],
),
),
);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
final goRouter = AppRouter().goRouter;
void main() {
runApp(const MainApp());
}
class MainApp extends StatelessWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerConfig: goRouter,
debugShowCheckedModeBanner: false,
themeMode: ThemeMode.light);
}
}