Flutter Scroll View auto scroll - scrollview

I have automated the scrolling of top coloured containers using animateto(). However, when I scroll down the screen, the scroll does not pause, but continues even though the scrolling boxes are off the screen. How do I pause scrolling when the boxes are off the screen and restart scrolling when the come into view...automatically. Note: I do not want to use any Flutter dependency.
Here is my code:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late ScrollController _scrollController;
double _place = 0;
#override
void initState() {
_scrollController = ScrollController();
super.initState();
WidgetsBinding.instance.addPostFrameCallback((context) async {
double x = 0;
while (x < 10) {
_place = x;
_doMove();
x++;
await Future.delayed(const Duration(seconds: 5));
}
});
}
_doMove() {
_scrollController.animateTo(105 * _place,
duration: Duration(seconds: 1), curve: Curves.easeInOut);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Material App',
home: Scaffold(
appBar: AppBar(
title: Text('Material App Bar'),
),
body: SingleChildScrollView(
child: Column(
children: [
Container(
height: 100,
child: ListView.builder(
itemCount: 20,
controller: _scrollController,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) => Container(
margin: const EdgeInsets.all(2),
width: 100,
color: Colors.amber,
child: Center(
child: Text(
'$index',
textAlign: TextAlign.center,
),
),
),
),
),
Column(
children: List.generate(
20,
(index) => ListTile(
title: Text('Person $index'),
),
),
)
],
),
)),
);
}
}

Related

The box "name" is already open and of type Box<dynamic>

The error is The box "todo_box" is already open and of type Box.
The relevant error-causing widget was: MyHomePage MyHomePage:file:///D:/Flutter_app/alimi_final/lib/schedule.dart:27:13
When the exception was thrown, this was the stack:
I have no idea about this error.
my code
main.dart
import 'package:hive/hive.dart';
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:work_a/map.dart';
import 'package:work_a/schedule.dart';
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:work_a/boxes.dart';
import 'package:work_a/model/todo.dart';
import 'package:work_a/screens/list_screen.dart';
import 'package:hive_flutter/hive_flutter.dart';
//const bool kIsWeb = identical(0, 0.0);
//Future<Box> openHiveBox(todo_box) async {
//if (!kIsWeb && !Hive.isBoxOpen(todo_box))
//Hive.init((await getApplicationDocumentsDirectory()).path);
//return await Hive.openBox(todo_box);
//}
Future<void> main() async{
WidgetsFlutterBinding.ensureInitialized();
final appDocumentDirectory = await getApplicationDocumentsDirectory();
Hive.init(appDocumentDirectory.path);
await Hive.initFlutter();
Hive.registerAdapter(TodoAdapter());
await Hive.openBox('todo_box');
runApp(MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _alimihomeState();
}
class _alimihomeState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'allimi',
theme: ThemeData(primaryColor: Colors.blue),
home: MyAppBar(),
debugShowCheckedModeBanner: false,
);
}
}
class MyAppBar extends StatelessWidget {
const MyAppBar({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('알리미'),
backgroundColor: Color.fromRGBO(31, 39, 76, 1.0),
centerTitle: true,
elevation: 0.0,
),
drawer: Drawer(
child: ListView(
children: [
UserAccountsDrawerHeader(
currentAccountPicture: CircleAvatar(
backgroundImage: AssetImage('images/userimage.jpg'),
),
accountName: Text('한동대생'),
accountEmail: Text('00000000#handong.ac.kr'),
decoration: BoxDecoration(
color: Color.fromRGBO(31, 39, 76, 1.0),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(30.0),
bottomRight: Radius.circular(30.0),
),
),
),
ListTile(
leading: Icon(
Icons.circle,
color: Colors.black,
size: 10.0,
),
visualDensity: VisualDensity(vertical: -3),
horizontalTitleGap: 1.0,
title: Text('내 스케줄'),
onTap: (){
Navigator.push(
context,
MaterialPageRoute(builder: (context) => schedule()),
);
},
),
SizedBox(
height: 5.0,
),
ListTile(
leading: Icon(
Icons.circle,
color: Colors.black,
size: 10.0,
),
visualDensity: VisualDensity(vertical: -3),
horizontalTitleGap: 1.0,
title: Text('지도 보기'),
onTap: (){
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MyMap()),
);
},
),
SizedBox(
height: 5.0,
),
ListTile(
leading: Icon(
Icons.circle,
color: Colors.black,
size: 10.0,
),
visualDensity: VisualDensity(vertical: -3),
horizontalTitleGap: 1.0,
title: Text('설정'),
onTap: (){},
),
SizedBox(
height: 295.0,
),
],
),
),
body: Center(
child: Column(
children: [
SizedBox(
height: 70.0,
),
CircleAvatar(
radius: 90.0,
backgroundColor: Colors.white,
backgroundImage: AssetImage('images/logoimage.jpg'),
),
SizedBox(
height: 30.0,
),
Text(
'한동 알리미',
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 210.0,
),
Text(
'DADAEGEEDEUL',
style: TextStyle(
fontSize: 10.0,
),
),
],
),
),
);
}
}
schedule.dart
import 'package:hive/hive.dart';
import 'package:work_a/boxes.dart';
import 'package:work_a/model/todo.dart';
import 'package:work_a/screens/list_screen.dart';
import 'package:hive_flutter/hive_flutter.dart';
// void main() => runApp(MyApp());
//void main() async {
//// hive initialization
//await Hive.initFlutter();
//Hive.registerAdapter(TodoAdapter());
////await Hive.openBox<Todo>(HiveBoxes.todo);
//}
class schedule extends StatelessWidget {
const schedule({Key? key}) : super(key: key);
static final String title = 'Hive Tutorial';
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue
),
home: MyHomePage(
title: '스케줄',
),
);
}
}
list_screen.dart
import 'package:hive/hive.dart';
import 'package:work_a/boxes.dart';
import 'package:work_a/model/todo.dart';
import 'package:work_a/screens/add_todo_Screen.dart';
import 'package:hive_flutter/hive_flutter.dart';
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Todo Hive Example'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void dispose() async {
Hive.close();
super.dispose();
//await Hive.openBox<Todo>(HiveBoxes.todo);
//await Hive.openBox<dynamic>('todo_box');
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color.fromRGBO(31, 39, 76, 1.0),
title: Text(widget.title),
),
body: ValueListenableBuilder(
valueListenable: Hive.box<Todo>(HiveBoxes.todo).listenable(),
builder: (context, Box<Todo> box, _) {
if (box.values.isEmpty)
return Center(
child: Text("리스트가 비었습니다"),
);
return ListView.builder(
itemCount: box.values.length,
itemBuilder: (context, index) {
Todo? res = box.getAt(index);
return Dismissible(
background: Container(color: Colors.red),
key: UniqueKey(),
onDismissed: (direction) {
res!.delete();
},
child: ListTile(
title: Text(res!.title),
subtitle: Text(res.description),
onTap: () {}),
);
},
);
}),
floatingActionButton: FloatingActionButton(
tooltip: 'Add todo',
child: Icon(Icons.add),
backgroundColor: Color.fromRGBO(31, 39, 76, 1.0),
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => AddTodoScreen(),
),
),
),
);
}
}
add_todo_screen.dart
import 'package:hive/hive.dart';
import 'package:work_a/boxes.dart';
import 'package:work_a/model/todo.dart';
class AddTodoScreen extends StatefulWidget {
AddTodoScreen({Key? key}) : super(key: key);
#override
_AddTodoScreenState createState() => _AddTodoScreenState();
}
class _AddTodoScreenState extends State<AddTodoScreen> {
//void main() async {
// await Hive.openBox<Todo>(HiveBoxes.todo);
//}
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
late String title;
late String description;
validated() {
if (_formKey.currentState != null && _formKey.currentState!.validate()) {
_onFormSubmit();
print("Form Validated");
} else {
print("Form Not Validated");
return;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color.fromRGBO(31, 39, 76, 1.0),
title: Text('스케줄 추가'),
),
body: SafeArea(
child: Form(
key: _formKey,
child: Padding(
padding: EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
autofocus: true,
initialValue: '',
decoration: InputDecoration(
labelText: '스케줄'
),
onChanged: (value) {
setState(() {
title = value;
});
},
validator: (String? value) {
if (value == null || value.trim().length == 0) {
return "required";
}
return null;
},
),
TextFormField(
initialValue: '',
decoration: const InputDecoration(
labelText: '메모',
),
onChanged: (value) {
setState(() {
description = value;
});
},
validator: (String? value) {
if (value == null || value.trim().length == 0) {
return "required";
}
return null;
},
),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary:Color.fromRGBO(31, 39, 76, 1.0),
),
onPressed: () {
validated();
},
child: Text('추가'),
)
],
),
),
),
),
);
}
void _onFormSubmit() {
Box<Todo> contactsBox = Hive.box<Todo>(HiveBoxes.todo);
contactsBox.add(Todo(title: title, description: description));
Navigator.of(context).pop();
}
}
ui_test.dart
import 'package:work_a/screens/add_todo_Screen.dart';
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Todo Hive Example'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color.fromRGBO(31, 39, 76, 1.0),
centerTitle: true,
title: Text(widget.title),
),
body: Container(
child: ListView.builder(
itemBuilder: (context, index) {
return Dismissible(
background: Container(color: Colors.red),
key: UniqueKey(),
onDismissed: (direction) {},
child: ListTile(
title: Text('Title'),
subtitle: Text('Description'),
onTap: () {}),
);
},
),
),
floatingActionButton: FloatingActionButton(
tooltip: 'Add todo',
child: Icon(Icons.add),
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => AddTodoScreen(),
),
),
),
);
}
}
boxs.dart
class HiveBoxes {
static String todo = 'todo_box';
}
todo.dart
import 'package:hive/hive.dart';
part 'todo.g.dart';
#HiveType(typeId: 0)
class Todo extends HiveObject {
#HiveField(0)
String? id;
#HiveField(1)
String title;
#HiveField(2)
String description;
Todo({required this.title, required this.description});
}
and
todo.g.dart
I'm assuming that you are saving Todo objects in todo_box.
Change this:
Hive.openBox('todo_box')
and this:
Hive.openBox<dynamic>('todo_box')
to this:
Hive.openBox<Todo>('todo_box')

My Content from API is not being shown in Flutter

I wrote my code in flutter, and used NewsAPI.org for getting content about news, such as heading, image, content etc. I made a class "News" and ArticleModel() for retrieving and using the information. I used Conditional Operator (? :) for checking if the data is received, then show it, else CircularProgressIndiactor() is shown. After running the app, CircularProgressIndiactor() shows up and no information is shown/loaded. Can anyone help me here??
No error or warning is shown, and code compiles successfully, but no information is shown up.
Here is the main file, home.dart -
import 'package:flutter/material.dart';
import 'package:news_app/helper/data.dart';
import 'package:news_app/helper/news.dart';
import 'package:news_app/models/article_model.dart';
import 'package:news_app/models/category_models.dart';
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
List<CategoryModel> categories = new List<CategoryModel>();
List<ArticleModel> articles = new List<ArticleModel>();
bool loading = true;
#override
void initState() {
// TODO: implement initState
super.initState();
categories = getCategories();
getNews();
}
getNews() async {
News newsClass = News();
await newsClass.getNews();
articles = newsClass.news;
setState(() {
loading = false;
print('Done');
});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Flutter',
style: TextStyle(
color: Colors.black,
),
),
Text(
'News',
style: TextStyle(
color: Colors.blue,
),
),
],
),
//elevation: 2.0,
),
body: loading
? Center(
child: Container(
child: CircularProgressIndicator(),
),
)
: SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
///Categories
Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
height: 70.0,
child: ListView.builder(
itemCount: categories.length,
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemBuilder: (context, index) {
return CategoryTile(
imageUrl: categories[index].imageUrl,
categoryName: categories[index].categoryName,
);
},
),
),
///Blogs
Container(
child: ListView.builder(
shrinkWrap: true,
itemCount: articles.length,
itemBuilder: (context, index) {
return BlogTile(
imageUrl: articles[index].urlToImage,
title: articles[index].title,
desc: articles[index].description,
);
},
),
),
],
),
),
),
),
);
}
}
class CategoryTile extends StatelessWidget {
final imageUrl, categoryName;
CategoryTile({this.imageUrl, this.categoryName});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {},
child: Container(
margin: EdgeInsets.only(right: 16.0),
child: Stack(
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.circular(6.0),
child: Image.network(
imageUrl,
width: 120.0,
height: 160.0,
fit: BoxFit.cover,
),
),
Container(
alignment: Alignment.center,
width: 120.0,
height: 60.0,
decoration: BoxDecoration(
color: Colors.black26,
borderRadius: BorderRadius.circular(6.0)),
child: Text(
categoryName,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 14.0,
),
),
),
],
),
),
);
}
}
class BlogTile extends StatelessWidget {
final String imageUrl, title, desc;
BlogTile(
{#required this.imageUrl, #required this.desc, #required this.title});
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Image.network(imageUrl),
Text(title),
Text(desc),
],
),
);
}
}
Here is the News.dart file -
import 'dart:convert';
import 'package:news_app/models/article_model.dart';
import 'package:http/http.dart' as http;
class News {
List<ArticleModel> news = [];
Future<void> getNews() async{
String url="http://newsapi.org/v2/top-headlines?country=in&category=business&apiKey=xxxxxxxxxxxxxxxxxx";
var response = await http.get(url);
var jsonData = jsonDecode(response.body);
if(jsonData["status"] == "ok") {
jsonData["articles"].forEach((element){
if(element['urlToImage'] != null && element['description'] != null) {
ArticleModel articleModel = ArticleModel(
title: element['title'],
author: element['author'],
description: element['description'],
url: element['url'],
urlToImage: element['urlToImage'],
content: element['content'],
);
news.add(articleModel);
}
});
}
}
}
And at last, ArticleModel.dart -
class ArticleModel {
String author, title, description;
String url, urlToImage;
String content;
ArticleModel({this.title, this.description, this.author, this.content, this.url, this.urlToImage});
}
Updating your request URL from http to https will give you expected result.
Update URL to: "https://newsapi.org/v2/top-headlines?country=in&category=business&apiKey="
Note: Don't share your API key in any open platforms for security reasons.

flutter_staggered_grid_view infinite scroll from api feed

I am using the flutter_staggered_grid_view package (https://github.com/letsar/flutter_staggered_grid_view) to have a feed of images. I want to implement something where first of all I can fetch say 30 images on initial screen load then when I reach the end and the scroll listener fires fetch more from the api. How do I change the below to do this? Can anyone give me any direction on docs etc. I think fundamentally this package is using gridview underneath but I am new to flutter so I'm unsure.
I just want an infinite scroll feed of images from an api.
class HomeScreen extends StatefulWidget {
_HomeState createState() => _HomeState();
}
class _HomeState extends State<HomeScreen> {
final scrollController = ScrollController();
#override
void initState() {
super.initState();
scrollController.addListener(() {
if (scrollController.position.maxScrollExtent ==
scrollController.offset) {
// Get more
print('End of screen');
}
});
}
List<String> imageList = [
'https://cdn.pixabay.com/photo/2020/12/15/16/25/clock-5834193__340.jpg',
'https://cdn.pixabay.com/photo/2020/09/18/19/31/laptop-5582775_960_720.jpg',
'https://media.istockphoto.com/photos/woman-kayaking-in-fjord-in-norway-picture-id1059380230?b=1&k=6&m=1059380230&s=170667a&w=0&h=kA_A_XrhZJjw2bo5jIJ7089-VktFK0h0I4OWDqaac0c=',
'https://cdn.pixabay.com/photo/2019/11/05/00/53/cellular-4602489_960_720.jpg',
'https://cdn.pixabay.com/photo/2017/02/12/10/29/christmas-2059698_960_720.jpg',
'https://cdn.pixabay.com/photo/2020/01/29/17/09/snowboard-4803050_960_720.jpg',
'https://cdn.pixabay.com/photo/2020/02/06/20/01/university-library-4825366_960_720.jpg',
'https://cdn.pixabay.com/photo/2020/11/22/17/28/cat-5767334_960_720.jpg',
'https://cdn.pixabay.com/photo/2020/12/13/16/22/snow-5828736_960_720.jpg',
'https://cdn.pixabay.com/photo/2020/12/15/16/25/clock-5834193__340.jpg',
'https://cdn.pixabay.com/photo/2020/09/18/19/31/laptop-5582775_960_720.jpg',
];
#override
Widget build(BuildContext context) {
/// If you set your home screen as first screen make sure call [SizeConfig().init(context)]
SizeConfig().init(context);
return Scaffold(
body: Platform.isIOS
? Container(
margin: EdgeInsets.only(left: 12, right: 12, top: 5),
child: CustomScrollView(
controller: scrollController,
physics: const BouncingScrollPhysics(
parent: AlwaysScrollableScrollPhysics()),
slivers: <Widget>[
SliverAppBar(
floating: true,
title: SvgPicture.asset(
"assets/images/logo-dark.svg",
height: getProportionateScreenWidth(40),
),
actions: [
// Filter Button
FlatButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FilterScreen(),
),
),
child: Text(
"Filter",
style: Theme.of(context).textTheme.bodyText1,
),
),
],
),
CupertinoSliverRefreshControl(
onRefresh: () async {
await Future.delayed(Duration(seconds: 2));
},
),
SliverStaggeredGrid.countBuilder(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 12,
itemCount: imageList.length,
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.all(
Radius.circular(15),
),
),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(15)),
child: FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: imageList[index],
fit: BoxFit.cover,
),
),
);
},
staggeredTileBuilder: (index) {
return StaggeredTile.count(1, index.isEven ? 1.2 : 1.8);
},
)
],
),
)
: RefreshIndicator(
color: kMainColor,
displacement: 120,
onRefresh: () async {
await Future.delayed(Duration(seconds: 2));
},
child: Container(
margin: EdgeInsets.only(left: 12, right: 12, top: 5),
child: CustomScrollView(
controller: scrollController,
physics: const BouncingScrollPhysics(
parent: AlwaysScrollableScrollPhysics(),
),
slivers: <Widget>[
SliverAppBar(
floating: true,
title: SvgPicture.asset(
"assets/images/logo-dark.svg",
height: getProportionateScreenWidth(40),
),
actions: [
// Filter Button
FlatButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FilterScreen(),
),
),
child: Text(
"Filter",
style: Theme.of(context).textTheme.bodyText1,
),
),
],
),
SliverStaggeredGrid.countBuilder(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 12,
itemCount: imageList.length,
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.all(
Radius.circular(15),
),
),
child: ClipRRect(
borderRadius: BorderRadius.all(
Radius.circular(15),
),
child: FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: imageList[index],
fit: BoxFit.cover,
),
),
);
},
staggeredTileBuilder: (index) {
return StaggeredTile.count(1, index.isEven ? 1.2 : 1.8);
},
)
],
),
),
),
);
}
}
You need to add the ScrollController for the scrolling detection at the bottom for the ListView and GridView. As you need the GridView i have created the ScrollController listner and added to the GridView's contollerfor the detection of the scroll. I have created the demo of it , please check it once. At first time it load the 10 items and when list comes to the bottom then it add more 10 items in it.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class HomeScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return HomeState();
}
}
class HomeState extends State<HomeScreen> {
List dataList = new List<int>();
bool isLoading = false;
int pageCount = 1;
ScrollController _scrollController;
#override
void initState() {
super.initState();
////LOADING FIRST DATA
addItemIntoLisT(1);
_scrollController = new ScrollController(initialScrollOffset: 5.0)
..addListener(_scrollListener);
}
Widget build(BuildContext context) {
return MaterialApp(
title: 'Gridview',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.red,
accentColor: Color(0xFFFEF9EB),
),
home: Scaffold(
appBar: new AppBar(),
body: GridView.count(
controller: _scrollController,
scrollDirection: Axis.vertical,
crossAxisCount: 2,
mainAxisSpacing: 10.0,
physics: const AlwaysScrollableScrollPhysics(),
children: dataList.map((value) {
return Container(
alignment: Alignment.center,
height: MediaQuery.of(context).size.height * 0.2,
margin: EdgeInsets.only(left: 10.0, right: 10.0),
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
),
child: Text("Item ${value}"),
);
}).toList(),
)));
}
//// ADDING THE SCROLL LISTINER
_scrollListener() {
if (_scrollController.offset >=
_scrollController.position.maxScrollExtent &&
!_scrollController.position.outOfRange) {
setState(() {
print("comes to bottom $isLoading");
isLoading = true;
if (isLoading) {
print("RUNNING LOAD MORE");
pageCount = pageCount + 1;
addItemIntoLisT(pageCount);
}
});
}
}
////ADDING DATA INTO ARRAYLIST
void addItemIntoLisT(var pageCount) {
for (int i = (pageCount * 10) - 10; i < pageCount * 10; i++) {
dataList.add(i);
isLoading = false;
}
}
#override
void dispose() {
_scrollController.dispose();
super.dispose();
}
}
https://i.stack.imgur.com/7hcDc.gif

Flutter Http Request is returning null

I am trying to make some http requests to an API. The first is to get data and display it in a list view and the second one is some more data but I want to display it on a new page. The code I have currently is returning null for the second Total request. If I run the total code separately it works fine and displays the data in a list view.
main.dart
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'Product.dart';
import 'Total.dart';
void main() => runApp(MyApp(
products: fetchProducts(),
total: fetchTotal(),
));
List<Product> parseProducts(String responseBody) {
final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Product>((json) => Product.fromJson(json)).toList();
}
Future<List<Product>> fetchProducts() async {
final response =
await http.get('http://10.0.0.102:9000/all/aF63z0R0jlQR7sfOgBAgOCOsQgv1');
if (response.statusCode == 200) {
return parseProducts(response.body);
} else {
throw Exception("Unable to access Server.");
}
}
class MyApp extends StatelessWidget {
final Future<List<Product>> products;
final Future<List<Total>> total;
MyApp({Key key, this.products, this.total}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(
title: 'Product Navigation demo home page',
products: products,
),
);
}
}
class MyHomePage extends StatelessWidget {
final String title;
final Future<List<Product>> products;
final Future<List<Total>> total;
MyHomePage({Key key, this.title, this.products, this.total})
: super(key: key);
// final items = Product.getProducts();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Product Navigation")),
body: Center(
child: FutureBuilder<List<Product>>(
future: products,
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? ProductBoxList(items: snapshot.data)
// return the ListView widget :
: Center(child: CircularProgressIndicator());
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => TotalPage()));
},
child: Icon(Icons.navigation),
backgroundColor: Colors.green,
),
);
}
}
class ProductBoxList extends StatelessWidget {
final List<Product> items;
ProductBoxList({Key key, this.items});
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return GestureDetector(
child: ProductBox(item: items[index]),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductPage(item: items[index]),
),
);
},
);
},
);
}
}
class ProductPage extends StatelessWidget {
ProductPage({Key key, this.item}) : super(key: key);
final Product item;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(this.item.pName),
),
body: Center(
child: Container(
padding: EdgeInsets.all(0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.all(5),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(this.item.pName,
style: TextStyle(fontWeight: FontWeight.bold)),
Text("Price: " + this.item.price),
Text("Barcode: " + this.item.barcode.toString()),
],
)))
]),
),
),
);
}
}
class ProductBox extends StatelessWidget {
ProductBox({Key key, this.item}) : super(key: key);
final Product item;
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(2),
height: 140,
child: Card(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.all(5),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(this.item.pName,
style: TextStyle(fontWeight: FontWeight.bold)),
Text("Price: " + this.item.price),
Text("Barcode: " + this.item.barcode.toString()),
],
)))
]),
));
}
}
List<Total> parseTotal(String responseBody) {
final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Total>((json) => Total.fromJson(json)).toList();
}
Future<List<Total>> fetchTotal() async {
final response = await http.get('http://10.0.0.102:8000/testData.json');
if (response.statusCode == 200) {
return parseTotal(response.body);
} else {
throw Exception("Unable to access Server.");
}
}
class TotalPage extends StatelessWidget {
final String title;
final Future<List<Total>> total;
TotalPage({Key key, this.title, this.total}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Product Navigation")),
body: Center(
child: FutureBuilder<List<Total>>(
future: total,
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
print(snapshot.data);
return snapshot.hasData
? TotalBoxList(items: snapshot.data)
// return the ListView widget :
: Center(child: CircularProgressIndicator());
},
),
),
);
}
}
class TotalBoxList extends StatelessWidget {
final List<Total> items;
TotalBoxList({Key key, this.items});
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return GestureDetector(
child: TotalDisplay(item: items[index]),
);
},
);
}
}
class TotalDisplay extends StatelessWidget {
TotalDisplay({Key key, this.item}) : super(key: key);
final Total item;
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(2),
height: 140,
child: Card(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.all(5),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(this.item.total.toString(),
style: TextStyle(fontWeight: FontWeight.bold)),
],
)))
]),
));
}
}
total.dart
import 'package:flutter/foundation.dart';
class Total {
final double total;
Total(this.total);
factory Total.fromJson(Map<String, dynamic> data) {
return Total(
data['total'],
);
}
}
You can copy paste run full code below
You forgot to pass total
Step 1: MyHomePage
MyHomePage(
title: 'Product Navigation demo home page',
products: products,
total: total, //here
),
Step 2: FloatingActionButton
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => TotalPage(
total: total,
))); //here
},
working demo
full code
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() => runApp(MyApp(
products: fetchProducts(),
total: fetchTotal(),
));
List<Product> parseProducts(String responseBody) {
final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Product>((json) => Product.fromJson(json)).toList();
}
Future<List<Product>> fetchProducts() async {
/*final response =
await http.get('http://10.0.0.102:9000/all/aF63z0R0jlQR7sfOgBAgOCOsQgv1');*/
String jsonString = '''
[
{
"pName":"1",
"price":"2",
"barcode": 3
},
{
"pName":"4",
"price":"5",
"barcode": 6
}
]
''';
final response = http.Response(jsonString, 200);
if (response.statusCode == 200) {
return parseProducts(response.body);
} else {
throw Exception("Unable to access Server.");
}
}
class MyApp extends StatelessWidget {
final Future<List<Product>> products;
final Future<List<Total>> total;
MyApp({Key key, this.products, this.total}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(
title: 'Product Navigation demo home page',
products: products,
total: total, //here
),
);
}
}
class MyHomePage extends StatelessWidget {
final String title;
final Future<List<Product>> products;
final Future<List<Total>> total;
MyHomePage({Key key, this.title, this.products, this.total})
: super(key: key);
// final items = Product.getProducts();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Product Navigation")),
body: Center(
child: FutureBuilder<List<Product>>(
future: products,
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? ProductBoxList(items: snapshot.data)
// return the ListView widget :
: Center(child: CircularProgressIndicator());
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => TotalPage(
total: total,
))); //here
},
child: Icon(Icons.navigation),
backgroundColor: Colors.green,
),
);
}
}
class ProductBoxList extends StatelessWidget {
final List<Product> items;
ProductBoxList({Key key, this.items});
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return GestureDetector(
child: ProductBox(item: items[index]),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductPage(item: items[index]),
),
);
},
);
},
);
}
}
class ProductPage extends StatelessWidget {
ProductPage({Key key, this.item}) : super(key: key);
final Product item;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(this.item.pName),
),
body: Center(
child: Container(
padding: EdgeInsets.all(0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.all(5),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(this.item.pName,
style: TextStyle(fontWeight: FontWeight.bold)),
Text("Price: " + this.item.price),
Text("Barcode: " + this.item.barcode.toString()),
],
)))
]),
),
),
);
}
}
class ProductBox extends StatelessWidget {
ProductBox({Key key, this.item}) : super(key: key);
final Product item;
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(2),
height: 140,
child: Card(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.all(5),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(this.item.pName,
style: TextStyle(fontWeight: FontWeight.bold)),
Text("Price: " + this.item.price),
Text("Barcode: " + this.item.barcode.toString()),
],
)))
]),
));
}
}
List<Total> parseTotal(String responseBody) {
final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
List<Total> a = parsed.map<Total>((json) => Total.fromJson(json)).toList();
return a;
}
Future<List<Total>> fetchTotal() async {
print("fetchTotal");
//final response = await http.get('http://10.0.0.102:8000/testData.json');
String jsonString = '''
[
{
"total":124.4
},
{
"total":123.1
}
]
''';
final response = http.Response(jsonString, 200);
if (response.statusCode == 200) {
return parseTotal(response.body);
} else {
throw Exception("Unable to access Server.");
}
}
class TotalPage extends StatelessWidget {
final String title;
final Future<List<Total>> total;
TotalPage({Key key, this.title, this.total}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Product Navigation")),
body: Center(
child: FutureBuilder<List<Total>>(
future: total,
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? TotalBoxList(items: snapshot.data)
// return the ListView widget :
: Center(child: CircularProgressIndicator());
},
),
),
);
}
}
class TotalBoxList extends StatelessWidget {
final List<Total> items;
TotalBoxList({Key key, this.items});
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return GestureDetector(
child: TotalDisplay(item: items[index]),
);
},
);
}
}
class TotalDisplay extends StatelessWidget {
TotalDisplay({Key key, this.item}) : super(key: key);
final Total item;
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(2),
height: 140,
child: Card(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.all(5),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(this.item.total.toString(),
style: TextStyle(fontWeight: FontWeight.bold)),
],
)))
]),
));
}
}
class Total {
final double total;
Total(this.total);
factory Total.fromJson(Map<String, dynamic> data) {
return Total(
data['total'],
);
}
}
class Product {
String pName;
String price;
int barcode;
Product({this.pName, this.price, this.barcode});
factory Product.fromJson(Map<String, dynamic> data) {
return Product(
pName: data["pName"], price: data["price"], barcode: data["barcode"]);
}
}

Login Validate User through rest api in flutter

I made the Login with Rest API. My App works like if username and password is correct then go to the MainPage of app. If false then throw exception on a page.The Problem is when credential are true or false. It shows the Circular Progress Indicator on next context or Screen.If the credential true. It show like
enter image description here then enter image description here then MainApp enter image description here
If the Crendential is false then exception page is show else of MainAppScreen.
But I want show the error like under the form like this if the user Crendential are wrong.enter image description here
I am doing validation for two days for not getting my required output.My code file main.dart
import 'package:flutter/material.dart';
import 'package:testing/api.dart';
import 'package:testing/sucess.dart';
main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: SignIn(),
);
}
}
class SignIn extends StatefulWidget {
#override
_SignInState createState() => _SignInState();
}
class _SignInState extends State<SignIn> {
TextStyle style = TextStyle(fontFamily: 'Montserrat', fontSize: 20.0);
//Gettting the JwtToken object and making the instance of it
Future<LoginResponse> _futureJwt;
final TextEditingController _controller = TextEditingController();
//Getting the password from the textField
final TextEditingController _controller1 = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
// appBar: AppBar(
// ),
backgroundColor: Colors.white,
body: Container(
alignment: Alignment.center,
// padding: const EdgeInsets.all(8.0),
//if Field have the null values then Get the value from the textField
child: (_futureJwt == null)
? SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// SizedBox(
// height: MediaQuery.of(context).size.height * 1 / 3,
// child: Image.asset(
// "assets/IMG_2382.png",
// fit: BoxFit.cover,
// ),
// ),
// SizedBox(height: 45.0),
Padding(
padding: const EdgeInsets.only(left: 30,right: 30),
child: TextField(
style: style,
decoration: InputDecoration(
contentPadding:
EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
hintText: "Email",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
),
controller: _controller,
),
),
SizedBox(height: 25.0),
Padding(
padding: const EdgeInsets.only(left: 30,right: 30),
child: TextField(
controller: _controller1,
obscureText: true,
style: style,
decoration: InputDecoration(
contentPadding:
EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
hintText: "Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
),
),
),
SizedBox(
height: 35.0,
),
Material(
elevation: 5.0,
borderRadius: BorderRadius.circular(5.0),
color: Colors.white,
child: Container(
width: 150,
height: 50,
child: RaisedButton(
child: Text(
"Login",
textAlign: TextAlign.center,
style: style.copyWith(
color: Colors.white,
fontWeight: FontWeight.bold),
),
color: Colors.grey[800],
// padding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
onPressed: () {
setState(() {
_futureJwt = createLoginState(
_controller.text, _controller1.text);
});
},
),
),
),
SizedBox(
height: 15.0,
),
],
),
)
//If the Conditiion (_futureJwt == null) is false then
: FutureBuilder<LoginResponse>(
//refer the object to the future
future: _futureJwt,
//
builder: (context, snapshot) {
//if the data is getting
if (snapshot.hasData) {
var token = snapshot.data.token;
print(token);
return Sucess();
}
//if the data results an error
else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
},
),
),
);
}
}
sucess.dart
import 'package:flutter/material.dart';
class Sucess extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Text('data'),
);
}
}
api.dart
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:async';
Future<LoginResponse> createLoginState(String username, String password) async {
final http.Response response = await http.post(
'http://192.168.43.76//soledesign/wp-json/jwt-auth/v1/token',
headers: <String, String>{
'Accept': 'application/json',
},
body: {
'username': username,
'password': password,
});
if (response.statusCode == 200) {
print(response.body);
return LoginResponse.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to create album.');
}
}
class LoginResponse {
String token;
String userEmail;
String userNicename;
String userDisplayName;
LoginResponse(
{this.token, this.userEmail, this.userNicename, this.userDisplayName});
LoginResponse.fromJson(Map<String, dynamic> json) {
token = json['token'];
userEmail = json['user_email'];
userNicename = json['user_nicename'];
userDisplayName = json['user_display_name'];
}
}
What you need to do is add an alert box which is displayed when the json response has an error message. Like so:
if (json['ErrorMessage] != null){ ShowAlertDialog(); }