Created
October 13, 2021 11:56
-
-
Save deva666/cb290cec937b4398cbf933bb525736de to your computer and use it in GitHub Desktop.
Flutter inherited widgets
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
void main() { | |
runApp(const MyApp()); | |
} | |
class IsVisible extends InheritedWidget { | |
final bool visible; | |
const IsVisible(this.visible, {required Widget child, Key? key}) : super(child: child, key: key); | |
@override | |
bool updateShouldNotify(covariant InheritedWidget oldWidget) { | |
return oldWidget is IsVisible && oldWidget.visible != visible; | |
} | |
} | |
class ExpensiveListItem extends StatefulWidget { | |
const ExpensiveListItem({Key? key}) : super(key: key); | |
@override | |
_ExpensiveListItemState createState() => _ExpensiveListItemState(); | |
} | |
class _ExpensiveListItemState extends State<ExpensiveListItem> { | |
bool isVisible = false; | |
@override | |
void didChangeDependencies() { | |
IsVisible? inheritedWidget = context.dependOnInheritedWidgetOfExactType(); | |
isVisible = inheritedWidget?.visible ?? false; | |
super.didChangeDependencies(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return isVisible | |
? FutureBuilder( | |
future: Future.delayed(const Duration(seconds: 3)), | |
builder: (c, snapshot) { | |
if (snapshot.connectionState == ConnectionState.done) { | |
return const Text('Received data'); | |
} else if (snapshot.connectionState == ConnectionState.waiting) { | |
return const CircularProgressIndicator.adaptive(); | |
} | |
return Container(); | |
}) | |
: Container(); | |
} | |
} | |
class MyApp extends StatelessWidget { | |
const MyApp({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'Inherited Widget Demo', | |
theme: ThemeData( | |
primarySwatch: Colors.blue, | |
), | |
home: const MyHomePage(title: 'Inherited Widget Demo'), | |
); | |
} | |
} | |
class MyHomePage extends StatefulWidget { | |
const MyHomePage({Key? key, required this.title}) : super(key: key); | |
final String title; | |
@override | |
State<MyHomePage> createState() => _MyHomePageState(); | |
} | |
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin { | |
late List<Widget> childViews; | |
late AnimationController animationController; | |
late Animation<Offset> slideInAnimation; | |
late Animation<double> fadeInAnimation; | |
int childIndex = 0; | |
@override | |
void initState() { | |
animationController = AnimationController( | |
vsync: this, | |
duration: const Duration(milliseconds: 500), | |
); | |
fadeInAnimation = Tween<double>(begin: 0, end: 1) | |
.animate(CurvedAnimation(parent: animationController, curve: Curves.easeInCubic)); | |
slideInAnimation = Tween<Offset>(begin: const Offset(0, 50), end: Offset.zero) | |
.animate(CurvedAnimation(parent: animationController, curve: Curves.easeOutQuad)); | |
childViews = [ | |
Container( | |
child: const Text( | |
'Home', | |
), | |
padding: const EdgeInsets.all(16), | |
), | |
ListView.builder( | |
itemBuilder: (c, i) => const ExpensiveListItem(), | |
itemCount: 20, | |
) | |
]; | |
super.initState(); | |
} | |
@override | |
void dispose() { | |
animationController.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: Text(widget.title), | |
), | |
body: AnimatedBuilder( | |
animation: animationController, | |
builder: (ctx, child) { | |
return Stack( | |
children: childViews.map((v) { | |
int navIndex = childViews.indexOf(v); | |
bool isCurrent = navIndex == childIndex; | |
return IsVisible(isCurrent, | |
child: TickerMode( | |
enabled: isCurrent, | |
child: Offstage( | |
offstage: !isCurrent, | |
child: Opacity( | |
opacity: animationController.isAnimating ? fadeInAnimation.value : 1, | |
child: Transform.translate( | |
offset: animationController.isAnimating ? slideInAnimation.value : Offset.zero, | |
child: v))))); | |
}).toList()); | |
}), | |
bottomNavigationBar: BottomNavigationBar( | |
onTap: changeChild, | |
currentIndex: childIndex, | |
items: const [ | |
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'), | |
BottomNavigationBarItem(icon: Icon(Icons.bar_chart), label: 'List'), | |
], | |
), | |
); | |
} | |
void changeChild(int i) async { | |
if (animationController.isAnimating) { | |
return; | |
} | |
if (i != childIndex) { | |
setState(() { | |
childIndex = i; | |
}); | |
} | |
await animationController.forward(); | |
animationController.reset(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment