Data not loading after using annimation - flutter

I am making a chat app using flutter. It is loading data from firestore but when I am using annimation in the drawer the chat's aren't loading I don't know the reason if i comment out the animation in the chat screen it works and it works also if comment out if block which contain connection state.waiting without commenting annimation
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:my_flutter_app/chat/messages.dart';
import 'package:my_flutter_app/chat/new_message.dart';
class ChatScreen extends StatefulWidget {
const ChatScreen({Key? key}) : super(key: key);
#override
State<ChatScreen> createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> with SingleTickerProviderStateMixin{
late AnimationController controller;
late Animation animation;
#override
void initState() {
super.initState();
controller=AnimationController(
duration: Duration(seconds: 2),
vsync: this);
animation=CurvedAnimation(parent: controller, curve: Curves.decelerate);
controller.forward();
animation.addStatusListener((status) {
if(status==AnimationStatus.completed){
controller.reverse(from: 1.0);
}else if(status==AnimationStatus.dismissed){
controller.forward();
}
});
controller.addListener(() {
setState(() {
animation.value;
});
});
}
#override
void dispose() {
super.dispose();
controller.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: Drawer(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Container(
margin: EdgeInsets.only(top: 50),
padding: EdgeInsets.all(15),
child: CircleAvatar(backgroundImage: AssetImage('assets/profile.png'),radius: 60),),
Container(
child: Image.asset('assets/welcome.png'),
height: animation.value*100,
),
InkWell(
onTap: (){
showCupertinoDialog(context: context, builder: (context)=>CupertinoAlertDialog(
title: Text('Alert'),
content: Text('Are you sure you want to logout?'),
actions: [
CupertinoDialogAction(child: Text('Yes'),onPressed: (){
FirebaseAuth.instance.signOut();
Navigator.pop(context);
},),
CupertinoDialogAction(child: Text('No'),onPressed: (){
Navigator.pop(context);
},)
],
));
//FirebaseAuth.instance.signOut();
},
child: ListTile(leading: Icon(Icons.logout,color: Colors.white),
title: Text('LOGOUT',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold),),
tileColor: Colors.red,),
)
],
),
),
appBar: AppBar(title: Text('Chats'),centerTitle: true,backgroundColor: Colors.green),
body: Container(
child: Column(
children: [
Expanded(child: Messages()),
NewMessage(),
],
),
),
);
}
}
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:my_flutter_app/chat/mesui.dart';
class Messages extends StatefulWidget {
const Messages({Key? key}) : super(key: key);
#override
State<Messages> createState() => _MessagesState();
}
class _MessagesState extends State<Messages> {
final auth=FirebaseAuth.instance;
User ?cuser;
#override
void initState() {
// TODO: implement initState
super.initState();
getCurrentUser();
}
void getCurrentUser(){
try {
final user = auth.currentUser;
if (user != null) {
cuser = user;
}
}
catch(e){
print(e);
}
}
#override
Widget build(BuildContext context) {
return StreamBuilder(stream: FirebaseFirestore.instance.collection('chat').orderBy('messaged_on',descending: true).snapshots(),
builder: (context,snaps) {
if(snaps.connectionState == ConnectionState.waiting){
return Center(
child: CircularProgressIndicator(),
);
}
final documents=snaps.data!.docs;
final nowperson=cuser!.email;
return ListView.builder(
reverse: true,
itemBuilder: (ctx,index){
final sender=documents[index]['email'];
bool isMe= sender==nowperson;
return Mesui(documents[index]['text'],isMe);
},
itemCount: documents.length,);
},
);
}
}

Related

Flutter youtube player iframe not working properly with full screen

I am using youtube_player_iframe to play you tube video. It is working but if click the full screen button on player, It is only show small as shown in picture. It is not always happen but It is happen once in two to three time.
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:thitsarparami/blocs/bloc.dart';
import 'package:thitsarparami/helper/constants.dart';
import 'package:thitsarparami/helper/enum.dart';
import 'package:thitsarparami/ui/error/something_went_wrong.dart';
import 'package:thitsarparami/widgets/circular_progress_indicator_widget.dart';
import 'package:youtube_player_iframe/youtube_player_iframe.dart';
class VideoScreen extends StatefulWidget {
static const routeName = '/video';
const VideoScreen({Key? key}) : super(key: key);
#override
_VideoScreenState createState() => _VideoScreenState();
}
class _VideoScreenState extends State<VideoScreen> {
#override
void initState() {
super.initState();
_loadYoutube();
}
_loadYoutube() async {
List<String> codes = [
systemDataCodeToString(SystemDataCode.youtube_live),
];
BlocProvider.of<SystemDataBloc>(context).add(GetYoutubeLiveEvent(codes));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
elevation: 0,
title: AutoSizeText(
kYouTubeChannel,
style: Theme.of(context).appBarTheme.titleTextStyle,
),
leading: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.arrow_back,
color: Theme.of(context).primaryIconTheme.color!,
),
),
),
body: BlocBuilder<SystemDataBloc, SystemDataState>(
builder: (context, state) {
if (state is SystemDataError) {
return const SomethingWentWrongScreen();
} else if (state is YoutubeLiveDataLoaded) {
return Column(
mainAxisSize: MainAxisSize.max,
children: [
MyYoutubePlayer(
videoId: state.systemData.youtubeLive!.videoId!,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
state.systemData.youtubeLive!.videoTitle!,
style: const TextStyle(
color: Colors.black,
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
)
],
);
}
return const CircularProgressIndicatorWidget();
},
),
);
}
}
class MyYoutubePlayer extends StatefulWidget {
final String videoId;
const MyYoutubePlayer({Key? key, required this.videoId}) : super(key: key);
#override
State<MyYoutubePlayer> createState() => _MyYoutubePlayerState();
}
class _MyYoutubePlayerState extends State<MyYoutubePlayer> {
late YoutubePlayerController _controller;
#override
void initState() {
super.initState();
_controller = YoutubePlayerController(
initialVideoId: widget.videoId,
params: const YoutubePlayerParams(
showControls: true,
showFullscreenButton: true,
desktopMode: false,
privacyEnhanced: true,
useHybridComposition: true,
),
);
_controller.onEnterFullscreen = () {
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeRight,
DeviceOrientation.landscapeLeft,
]);
};
_controller.onExitFullscreen = () {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
};
}
#override
void dispose() {
_controller.close();
super.dispose();
}
#override
Widget build(BuildContext context) {
return YoutubePlayerIFrame(
controller: _controller,
aspectRatio: 16 / 9,
);
}
}
change this
Widget build(BuildContext context) {
return YoutubePlayerIFrame(
controller: _controller,
aspectRatio: 16 / 9,
);
}
to this
Widget build(BuildContext context) {
return YoutubePlayerScaffold(
autoFullScreen: true,
builder: ((context, player) {
return Container(
width: 100.w,
height: 100.h,
color: Colors.black,
child: Center(
child: player,
),
);
}),
controller: _controller
);
}
Fullscreen only works with YoutubePlayerScaffold Widget

Moving to the next page after splash screen

Dears,
At first am so new to programming and flutter.
I bought an app code and I did the re-skin, but am facing an issue with the splash screen
the code was like this:
import 'package:cirilla/constants/assets.dart';
import 'package:cirilla/constants/constants.dart';
import 'package:flutter/material.dart';
import 'package:ui/painter/zoom_painter.dart';
import 'widgets/zoom_animation.dart';
class SplashScreen extends StatefulWidget {
const SplashScreen({Key? key, this.color, this.loading}) : super(key: key);
final Color? color;
final bool? loading;
#override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> with SingleTickerProviderStateMixin {
Size size = Size.zero;
late AnimationController _controller;
late ZoomAnimation _animation;
AnimationStatus _status = AnimationStatus.forward;
#override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 2500),
vsync: this,
)
..addStatusListener((AnimationStatus status) {
setState(() {
_status = status;
});
})
..addListener(() {
setState(() {});
});
_animation = ZoomAnimation(_controller);
}
#override
void didChangeDependencies() {
setState(() {
size = MediaQuery.of(context).size;
});
super.didChangeDependencies();
}
#override
void didUpdateWidget(covariant SplashScreen oldWidget) {
super.didUpdateWidget(oldWidget);
if (!widget.loading! && _controller.status != AnimationStatus.forward) {
_controller.forward();
}
}
#override
Widget build(BuildContext context) {
if (_status == AnimationStatus.completed) return Container();
return Stack(children: [
SizedBox(
width: double.infinity,
height: double.infinity,
child: CustomPaint(
painter: ZoomPainter(color: widget.color!, zoomSize: _animation.zoomSize.value * size.width),
),
),
Padding(
padding: const EdgeInsets.only(bottom: itemPaddingExtraLarge),
child: Align(
alignment: Alignment.center,
child: Opacity(
opacity: _animation.textOpacity.value,
child: Image.asset(Assets.logo, width: 200, height: 200, fit: BoxFit.fitWidth),
),
),
)
]);
}
#override
void dispose() {
super.dispose();
_controller.dispose();
}
}
'''
and was just fine I turned it to this
import 'package:flutter/material.dart';
import 'package:rive/rive.dart';
class SimpleAnimation extends StatelessWidget {
const SimpleAnimation({Key? key, this.loading}) : super(key: key);
final bool? loading;
#override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: RiveAnimation.asset('assets/splash/splash.riv',
fit: BoxFit.cover)
),
);
}
}
All I need is just to make it go to the next screen after 5 seconds, I tried many things but nothing sometimes I get a black screen after the splash screen I created with RIVE and most the time it just stuck after playing.
just to note, the following code is in home.dart
return Stack(
children: [
widget.store!.data == null ? const Empty() : buildOnBoarding(context),
SplashScreen(loading: widget.store!.loading, color: Colors.white),
],
);
}
Create method like this.Here future. delayed solve our problem to show animation 5 seconds as splash screen
setdata(BuildContext context) async {
await Future.delayed(const Duration(seconds: 5), () {
SchedulerBinding.instance!.addPostFrameCallback((_) {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => WelcomeScreen()),
);
});
});
}
Splash Screen may like this
class SimpleAnimation extends StatelessWidget {
const SimpleAnimation({Key? key, this.loading}) : super(key: key);
final bool? loading;
#override
Widget build(BuildContext context) {
setdata(context);
return Scaffold(
body: Center(
child: Container(
height: 200,
width: 200,
child: RiveAnimation.network(
'https://cdn.rive.app/animations/vehicles.riv',
),
),
),
);
}
}
After splash page
welcome.dart(You must wrap the widget with Scaffold widget.other wise you get black screen
class WelcomeScreen extends StatelessWidget {
const WelcomeScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: Container(
child: Text(
"HOME PAGE",
style: TextStyle(fontSize: 50),
),
),
),
);
}
}
SampleCode:
import 'package:flutter/material.dart';
import 'package:rive/rive.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(MaterialApp(home: SimpleAnimation()));
}
setdata(BuildContext context) async {
await Future.delayed(const Duration(seconds: 5), () {
SchedulerBinding.instance!.addPostFrameCallback((_) {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => WelcomeScreen()),
);
});
});
}
class SimpleAnimation extends StatelessWidget {
const SimpleAnimation({Key? key, this.loading}) : super(key: key);
final bool? loading;
#override
Widget build(BuildContext context) {
setdata(context);
return Scaffold(
body: Center(
child: Container(
height: 200,
width: 200,
child: RiveAnimation.network(
'https://cdn.rive.app/animations/vehicles.riv',
),
),
),
);
}
}
class WelcomeScreen extends StatelessWidget {
const WelcomeScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: Container(
child: Text(
"HOME PAGE",
style: TextStyle(fontSize: 50),
),
),
),
);
}
}

accessing a private method from another class flutter

I'm new to flutter.I have here 3 classes which are the Login(), MainMenu() which is the screen after already logged, and this MyDrawer()which is a drawer of my App.
What I'm trying to do is I want to access the signOut() method from Login(). How would I do it or what should I do to redesign my code. I've tried below accessing it and it receives and exception The method 'call' was called on null.
This is a code snippet from my full code:
class Login extends StatefulWidget {
#override
_LoginState createState() => _LoginState();
}
enum LoginStatus { notSignIn, signIn }
class _LoginState extends State<Login> {
LoginStatus _loginStatus = LoginStatus.notSignIn;
String email, password;
final _key = new GlobalKey<FormState>();
bool _secureText = true;
signOut() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
setState(() {
_loginStatus = LoginStatus.notSignIn;
});
}
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
switch (_loginStatus) {
case LoginStatus.notSignIn:
return Scaffold(
backgroundColor: Colors.cyan,
body: Center(
child: ListView(
shrinkWrap: true,
padding: EdgeInsets.all(15.0),
children: <Widget>[
Center(
child: Container(
padding: const EdgeInsets.all(8.0),
color: Colors.cyan,
child: Form(
key: _key,
break;
case LoginStatus.signIn:
return MainMenu();
break;
}
}
}
class MainMenu extends StatefulWidget {
#override
_MainMenuState createState() => _MainMenuState();
}
class _MainMenuState extends State<MainMenu> {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
)
)
}
class MyDrawer extends StatefulWidget {
final Function onTap;
final VoidCallback signOut;
MyDrawer(
{this.onTap,this.signOut
});
#override
_MyDrawerState createState() => _MyDrawerState();
}
class _MyDrawerState extends State<MyDrawer> {
signOut() {
setState(() {
widget.signOut();
});
}
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return SizedBox(
width: MediaQuery
.of(context)
.size
.width * 0.7,
child: Drawer(
child: Container(
height:100,
color: Colors.white,
child: ListView(
padding: EdgeInsets.all(0),
children: <Widget>[
ListTile(
leading: Icon(Icons.exit_to_app,color: Colors.cyan, size: 30.0),
onTap: () {
signOut();
},
title: Text("Logout",
style: TextStyle(color: Colors.black,fontWeight: FontWeight.w500, fontSize: 18),
),
),
],
),
),
),
);
}
}
I'm really stuck with this problem. Any help would be greatly appreciated. Thanks!

How to get the page is not disposed

I have application which has mappage using location
class _MapPageState extends State<MapPage> {
LocationData currentLocation;
Location _locationService = new Location();
#override
void initState(){
super.initState();
_locationService.onLocationChanged().listen((LocationData result) async {
setState(() {
print(result.latitude);
print(result.longitude);
currentLocation = result;
});
});
}
In this case, setState() works well when mappage is shown.
However after mappage is disposed, there comes error like this.
E/flutter ( 6596): This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
E/flutter ( 6596): The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
So, I have two ideas.
Remove onLocationChanged() listener when page is disposed.
Check if State is disposed or not before setState()
How can I solve this??
You can copy paste two files below and directly replace official example's code
https://github.com/Lyokone/flutterlocation/tree/master/location/example/lib
After Navigate to ListenLocationWidget page,
you can call _stopListen() in dispose()
code snippet
class _MyHomePageState
...
RaisedButton(
child: Text('Open route'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => ListenLocationWidget()),
);
},
),
PermissionStatusWidget(),
Divider(height: 32),
ServiceEnabledWidget(),
Divider(height: 32),
GetLocationWidget(),
Divider(height: 32),
//ListenLocationWidget()
class _ListenLocationState extends State<ListenLocationWidget> {
...
StreamSubscription<LocationData> _locationSubscription;
String _error;
#override
void initState() {
print("initState");
super.initState();
_listenLocation();
}
#override
void dispose() {
print("stopListen");
_stopListen();
super.dispose();
}
Future<void> _listenLocation() async {
_locationSubscription =
location.onLocationChanged.handleError((dynamic err) {
setState(() {
_error = err.code;
});
_locationSubscription.cancel();
}).listen((LocationData currentLocation) {
setState(() {
print("setState");
_error = null;
_location = currentLocation;
});
});
}
Future<void> _stopListen() async {
_locationSubscription.cancel();
}
working demo
full code ListenLocationWidget
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:location/location.dart';
class ListenLocationWidget extends StatefulWidget {
const ListenLocationWidget({Key key}) : super(key: key);
#override
_ListenLocationState createState() => _ListenLocationState();
}
class _ListenLocationState extends State<ListenLocationWidget> {
final Location location = Location();
LocationData _location;
StreamSubscription<LocationData> _locationSubscription;
String _error;
#override
void initState() {
print("initState");
super.initState();
_listenLocation();
}
#override
void dispose() {
print("stopListen");
_stopListen();
super.dispose();
}
Future<void> _listenLocation() async {
_locationSubscription =
location.onLocationChanged.handleError((dynamic err) {
setState(() {
_error = err.code;
});
_locationSubscription.cancel();
}).listen((LocationData currentLocation) {
setState(() {
print("setState");
_error = null;
_location = currentLocation;
});
});
}
Future<void> _stopListen() async {
_locationSubscription.cancel();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Container(
color: Colors.white,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Listen location: ' + (_error ?? '${_location ?? "unknown"}'),
style: Theme.of(context).textTheme.body2,
),
Row(
children: <Widget>[
Container(
margin: const EdgeInsets.only(right: 42),
child: RaisedButton(
child: const Text('Listen'),
onPressed: _listenLocation,
),
),
RaisedButton(
child: const Text('Stop'),
onPressed: _stopListen,
)
],
),
],
),
),
);
}
}
full code main.dart
import 'package:flutter/material.dart';
import 'package:location/location.dart';
import 'package:url_launcher/url_launcher.dart';
import 'get_location.dart';
import 'listen_location.dart';
import 'permission_status.dart';
import 'service_enabled.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Location',
theme: ThemeData(
primarySwatch: Colors.amber,
),
home: const MyHomePage(title: 'Flutter Location Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final Location location = Location();
Future<void> _showInfoDialog() {
return showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Demo Application'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
const Text('Created by Guillaume Bernos'),
InkWell(
child: Text(
'https://github.com/Lyokone/flutterlocation',
style: TextStyle(
decoration: TextDecoration.underline,
),
),
onTap: () =>
launch('https://github.com/Lyokone/flutterlocation'),
),
],
),
),
actions: <Widget>[
FlatButton(
child: const Text('Ok'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: <Widget>[
IconButton(
icon: Icon(Icons.info_outline),
onPressed: _showInfoDialog,
)
],
),
body: Container(
padding: const EdgeInsets.all(32),
child: Column(
children: <Widget>[
RaisedButton(
child: Text('Open route'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => ListenLocationWidget()),
);
},
),
PermissionStatusWidget(),
Divider(height: 32),
ServiceEnabledWidget(),
Divider(height: 32),
GetLocationWidget(),
Divider(height: 32),
//ListenLocationWidget()
],
),
),
);
}
}

How to SetState() of Parent when child is Updated in flutter

I have a list view and inside the list view, there is a child widget which can grow when user tap on that.
I want to scroll to the bottom of the list when the user taps on the child and it grows.
when I pass callback function from the parent to the child to scroll to the bottom.
and call the function when the user tap on the child.
I get the following error: setState() or markNeedsBuild() called during build.
class MyWidget extends StatefulWidget {
#override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
ScrollController _controller = ScrollController();
void scrollToLast() {
print("trying to scroll");
setState(() {
_controller.animateTo(
_controller.position.maxScrollExtent,
duration: Duration(microseconds: 300),
curve: Curves.easeInOut,
);
});
}
#override
Widget build(BuildContext context) {
return ListView(
controller: _controller,
children: <Widget>[
MyChildWidget(
scrollToLast: this.scrollToLast,
)
],
);
}
}
class MyChildWidget extends StatefulWidget {
final VoidCallback scrollToLast;
MyChildWidget({
this.scrollToLast,
});
#override
_MyChildWidgetState createState() => _MyChildWidgetState(
scrollToLast: this.scrollToLast,
);
}
class _MyChildWidgetState extends State<MyChildWidget> {
final VoidCallback scrollToLast;
_MyChildWidgetState({
this.scrollToLast,
});
int count = 5;
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
setState(() {
this.count += 5;
});
this.scrollToLast();
},
child: Column(
mainAxisSize: MainAxisSize.max,
children: List<Widget>.generate(
this.count,
(int index) => Container(
color: Colors.blue,
height: 30,
margin: EdgeInsets.all(10),
),
),
),
);
}
}
You can copy paste run full code below
You can use WidgetsBinding.instance.addPostFrameCallback
code snippet
void scrollToLast() {
print("trying to scroll");
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
_controller.animateTo(
_controller.position.maxScrollExtent,
duration: Duration(microseconds: 300),
curve: Curves.easeInOut,
);
});
});
}
working demo
full code
import 'package:flutter/material.dart';
class MyWidget extends StatefulWidget {
#override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
ScrollController _controller = ScrollController();
void scrollToLast() {
print("trying to scroll");
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
_controller.animateTo(
_controller.position.maxScrollExtent,
duration: Duration(microseconds: 300),
curve: Curves.easeInOut,
);
});
});
}
#override
Widget build(BuildContext context) {
return ListView(
controller: _controller,
children: <Widget>[
MyChildWidget(
scrollToLast: this.scrollToLast,
)
],
);
}
}
class MyChildWidget extends StatefulWidget {
final VoidCallback scrollToLast;
MyChildWidget({
this.scrollToLast,
});
#override
_MyChildWidgetState createState() => _MyChildWidgetState(
/*scrollToLast: this.scrollToLast,*/
);
}
class _MyChildWidgetState extends State<MyChildWidget> {
/* final VoidCallback scrollToLast;
_MyChildWidgetState({
this.scrollToLast,
});*/
int count = 5;
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
setState(() {
this.count += 5;
});
widget.scrollToLast();
},
child: Column(
mainAxisSize: MainAxisSize.max,
children: List<Widget>.generate(
this.count,
(int index) => Container(
color: Colors.blue,
height: 30,
margin: EdgeInsets.all(10),
child: Text('$index'),
),
),
),
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(
title: "Demo",
),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(child: MyWidget()),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}