I've gotten a flutter problem.
I wanna try to update my screen after
setState(() => {
widgetScreenBuilder = screenWidgets[currentScreen]
});
in my category selector has been called. I've tried to make it so I have one main screen which has the function for my category selector and then I'd like to have the current screen/widget as a function. Then I could change the screen/widget below my selector just by changing the function. I just can't find a way to refresh the page / the body of the main screen after I've changed the function (widget below category selector)
My main screen:
import 'package:flutter/material.dart';
import 'package:app/widgets/categorySelector.dart';
import 'package:app/data/appData.dart';
class MainScreen extends StatefulWidget {
#override
_MainScreen createState() => _MainScreen();
}
class _MainScreen extends State<MainScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).primaryColorDark,
appBar: AppBar(
backgroundColor: Theme.of(context).primaryColorDark,
elevation: 0.0,
title: Center(
child: Text(
"Tournaments",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 26.0,
letterSpacing: 1.1
)
),
),
),
body: Column(
children: <Widget>[
CategorySelector(),
widgetScreenBuilder
],
),
);
}
}
My category selector:
import 'package:app/data/appData.dart';
import 'package:flutter/material.dart';
class CategorySelector extends StatefulWidget {
#override
_CategorySelectorState createState() => _CategorySelectorState();
}
class _CategorySelectorState extends State<CategorySelector> {
final List<String> categories = ['All games', 'New game', "New player", "Top players"];
#override
Widget build(BuildContext context) {
return Container(
height: 75.0,
color: Theme.of(context).primaryColorDark,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: categories.length,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
if (currentScreen != index) {
currentScreen = index;
setState(() => {
widgetScreenBuilder = screenWidgets[currentScreen]
});
}
},
child: Center(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0),
child: Text(
categories[index],
style: TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.bold,
letterSpacing: 1.2,
color: index == currentScreen ? Colors.white : Colors.white50
)
)
),
),
);
}
)
);
}
}
The appData.dart file where widgetScreenBuilder, screenWidgets and currentScreen is located:
import 'package:app/widgets/allGames.dart';
int currentScreen = 0;
List screenWidgets = [AllGames(), NewGame()];
var widgetScreenBuilder = screenWidgets[currentScreen];
I'm new to app development, dart and flutter so any help would be appreciated!
Thanks <3
I can't understand you question well,
But i think you should try didChangeDependencies
Check it : https://api.flutter.dev/flutter/widgets/State/didChangeDependencies.html
change your MainScreen class to this :
class MainScreen extends StatefulWidget {
#override
_MainScreen createState() => _MainScreen();
}
class _MainScreen extends State<MainScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).primaryColorDark,
appBar: AppBar(
backgroundColor: Theme.of(context).primaryColorDark,
elevation: 0.0,
title: Center(
child: Text("Tournaments",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 26.0,
letterSpacing: 1.1)),
),
),
body: CategorySelector(), // delete column and just put CategorySelector()
);
}
}
and change your CategorySelector class to this :
class CategorySelector extends StatefulWidget {
#override
_CategorySelectorState createState() => _CategorySelectorState();
}
class _CategorySelectorState extends State<CategorySelector> {
final List<String> categories = [
'All games',
'New game',
"New player",
"Top players"
];
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Container(
height: 75.0,
color: Theme.of(context).primaryColorDark,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: categories.length,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
if (currentScreen != index) {
currentScreen = index;
setState(
() =>
{widgetScreenBuilder = screenWidgets[currentScreen]},
);
}
},
child: Center(
child: Padding(
padding:
EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0),
child: Text(
categories[index],
style: TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.bold,
letterSpacing: 1.2,
color: index == currentScreen
? Colors.white
: Colors.white54),
),
),
),
);
},
),
),
widgetScreenBuilder, // add widgetScreenBuilder here
],
);
}
}
Your code is working properly now :)
setState() can only make changes in its own class.
Related
I'm developing a classified listing app like the OLX but I currently have challenges accessing the subcategories from the Categories widgets. Whenever, any category is clicked, I'm expecting such category to appear as the header of the subcategory being accessed. The error occurs at the "DocumentSnapshot argument = ModalRoute.of(context)!.settings.arguments;" I've tried several methods without success. Please, can someone help spot what I,m not doing right? thanks in advance.
import 'package:flutter/material.dart';
class CategoryListScreen extends StatelessWidget {
const CategoryListScreen({Key? key}) : super(key: key);
static const String id = 'categoryListScreen';
#override
Widget build(BuildContext context) {
final CollectionReference _categories =
FirebaseFirestore.instance.collection('categories');
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.white,
iconTheme: IconThemeData(color: Colors.cyan.shade800),
title: Text(
"Categories",
style: GoogleFonts.montserrat(
color: Colors.black, fontWeight: FontWeight.bold),
),
),
body: StreamBuilder(
stream: _categories.snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> streamSnapshot) {
if (streamSnapshot.hasError) {
return Container();
}
if (streamSnapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
itemCount: streamSnapshot.data!.docs.length,
itemBuilder: (context, index) {
final DocumentSnapshot doc = streamSnapshot.data!.docs[index];
return Padding(
padding: const EdgeInsets.all(16.0),
child: ListTile(
//To subcategories
onTap: () {
Navigator.pushNamed(context, SubCatList.id, arguments: doc);
},
leading: Image.network(
doc['catImage'],
width: 40,
),
title: Text(
doc['catName'],
style: GoogleFonts.montserrat(
fontSize: 15, fontWeight: FontWeight.bold),
),
trailing: const Icon(
Icons.arrow_forward_ios,
size: 12,
),
),
);
},
);
},
),
);
}
}
class SubCatList extends StatelessWidget {
const SubCatList({Key? key}) : super(key: key);
static const String id = 'subCatList';
#override
Widget build(BuildContext context) {
DocumentSnapshot argument = ModalRoute.of(context)!.settings.arguments; //this is is where the error is.
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.white,
iconTheme: IconThemeData(color: Colors.cyan.shade800),
title: Text(
//"SubCat",
argument['catName'],
style: GoogleFonts.montserrat(
color: Colors.black, fontWeight: FontWeight.bold),
),
),
);
}
}
I pull some variables in Firebase and I create a widget list with these variables. I want to control widget visibility when I click a widget. When I use the Visibility widget and set "visible: widgetVisibility" value, all widgets are changed at the same time. I only want the widget I clicked to change. How can I do that?
body: StreamBuilder<QuerySnapshot>(
stream: _keyService.getKeys(),
builder: (context, snapshot) {
return !snapshot.hasData
? const Center(child: CircularProgressIndicator())
: ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot mypost = snapshot.data!.docs[index];
return Padding(
padding: EdgeInsets.all(size * 0.3),
child: InkWell(
onTap: () {
valueVisible = !valueVisible;
},
child: Container(
decoration: BoxDecoration(
color: ColorItems.mainColor,
border: Border.all(width: 5, color: Colors.grey),
borderRadius: BorderRadius.all(Radius.circular(20))),
child: Padding(
padding: EdgeInsets.all(size),
child: Container(
child: Row(
children: [
Expanded(
child: Text(
"${mypost['key']}",
style: const TextStyle(
color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold),
),
),
const Text(
": ",
style:
TextStyle(color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold),
),
const SizedBox(
width: 20,
),
Expanded(
child: Visibility(
visible: valueVisible,
child: Text(
"${mypost['value']}",
style: const TextStyle(
color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold),
),
))
],
),
),
),
),
),
);
},
);
})
Additionally, screenshots is here..
This might not be the optimal solution, but I always create a List for that purpose:
instead of one valueVisible bool I create a List and add a bool for each item in the list.
...itemBuilder: (context, index) { valueVisibleList.add(true)...
and in the button I then use the current item index to change only the corresponding bool
onTap: () { setState(({
valueVisibleList[index] = !valueVisibleList[index];
})
},
Just use a Map<String, bool> where the keys are the post's key and the value its visibility. The visibility should default to true if the key is not present. And the state should only change inside a setState function.
It would be something like the following (Check out the live demo on DartPad):
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
final posts = [
for (var i = 0; i < 100; i++) {'key': 'key$i', 'value': '$i'}
];
class _MyHomePageState extends State<MyHomePage> {
final valueVisible = <String, bool>{};
#override
Widget build(BuildContext context) {
const size = 16.0;
return Scaffold(
body: ListView.builder(
itemCount: posts.length,
itemBuilder: (context, index) {
final mypost = posts[index];
return Padding(
padding: const EdgeInsets.all(size * 0.3),
child: InkWell(
onTap: () {
setState(() {
valueVisible[mypost['key']!] =
!(valueVisible[mypost['key']!] ?? true);
});
},
child: Container(
decoration: BoxDecoration(
color: const Color(0xffff9400),
border: Border.all(width: 5, color: Colors.grey),
borderRadius: const BorderRadius.all(Radius.circular(20))),
child: Padding(
padding: const EdgeInsets.all(size),
child: Row(
children: [
Expanded(
child: Text(
"${mypost['key']}",
style: const TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold),
),
),
const Text(
": ",
style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold),
),
const SizedBox(
width: 20,
),
Expanded(
child: Visibility(
visible: valueVisible[mypost['key']!] ?? true,
child: Text(
"${mypost['value']}",
style: const TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold),
),
),
)
],
),
),
),
),
);
},
),
);
}
}
I am trying to get data from my api and display it using Card widget .I want to align everything in an even manner without using a table. I have a written a code for it. But still there are a few rows which are not aligned properly.
Please write a detailed answer
Here is my table:
Here is my code:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:http/http.dart';
import 'Posts.dart';
late List<Post> drivers;
class MyApp extends StatefulWidget {
// to set the root of app.
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.green,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
late final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Center(
child: const Text("Driver Table",
style: TextStyle(
fontWeight: FontWeight.w900,
),
),
),
),
body: Container(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children:[
Expanded(
child: Container(
height: 70,
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey,
),
borderRadius: const BorderRadius.all(Radius.circular(20))
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: const [
Text('Did',
style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.w900
),
),
Text('Dname',style: TextStyle(
fontSize: 24,
color: Colors.white,
fontWeight: FontWeight.w900
),),
Text('Age',style: TextStyle(
fontSize: 24,
color: Colors.white,
fontWeight: FontWeight.w900
),),
],
),
),
),
]
),
Expanded(
child: Container(
child:_buildBody(context),
),
)
],
),
color:const Color(0xFF303030),
),
//
);
}
// build list view & manage states
FutureBuilder<List<Post>> _buildBody(BuildContext context) {
final HttpService httpService = HttpService();
return FutureBuilder<List<Post>>(
future: httpService.getPosts(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
final List<Post>? posts = snapshot.data; //marked
return _buildPosts(context, posts!);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
);
}
// build list view & its tile
ListView _buildPosts(BuildContext context, List<Post> posts) {
Row(
children: [
Container(
child: const Text('Did',
style: TextStyle(
color: Colors.white,
),
),
),
Container(
child: const Text('Dname',style: TextStyle(
color: Colors.white,
),),
),
Container(
child: const Text('Age',style: TextStyle(
color: Colors.white,
),),
),
],
);
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: posts.length,
padding: const EdgeInsets.all(20),
itemBuilder: (context, index) {
return Container(
height:70,
child: Card(
shadowColor: Colors.white,
color:const Color(0xFF303030),
elevation: 1,
child: IntrinsicHeight(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(posts[index].Did,style: const TextStyle(fontWeight: FontWeight.bold,
color:Colors.white,),),
Text(posts[index].Dname,style: const TextStyle(fontWeight: FontWeight.bold,
color:Colors.white,),),
Text(posts[index].Age,style: const TextStyle(fontWeight: FontWeight.bold,color:Colors.white,),
),
],
),
),
),
);
},
);
}
}
class HttpService {
Future<List<Post>> getPosts() async {
Response res = await get(
Uri.parse('http://localhost/localconnect/driver_change.php'));
print(res.body);
if (res.statusCode == 200) {
List<dynamic> body = jsonDecode(res.body);
List<Post> posts = body.map(
(dynamic item) => Post.fromJson(item),
).toList();
return posts;
} else {
throw "Unable to retrieve posts.";
}
}
}
Posts.dart
import 'dart:convert';
List<Post> userFromJson(String str) => List<Post>.from(json.decode(str).map((x) => Post.fromJson(x)));
String userToJson(List<Post> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Post{
Post({
required this.Did,
required this.Dname,
required this.Age,
});
String Did;
String Dname;
String Age;
factory Post.fromJson(Map<String, dynamic> json) => Post(
Did: json["Did"],
Dname: json["Dname"],
Age: json["Age"],
);
Map<String, dynamic> toJson() => {
"Did": Did,
"Dname": Dname,
"Age": Age,
};
}
For every Text widget use
textAlign: TextAlign.center,
and on every Row Row
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
Main issue is coming from ListView.builder's
padding: const EdgeInsets.all(20), //remove this padding
Remove the padding here and no need to use IntrinsicHeight widget.
I wanted to send Data/images from one page to another. In the Homepage when I tap on the add Icon button image should be passed to the Cart page and if the icon is tapped again image is removed from the Cart page. But, the cart page should be accessed from bottom navigation bar.
but it is showing an error called 1 positional argument(s) expected, but 0 found.
Try adding the missing arguments.. when it calls the cart page.
HomePage.dart file
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blueGrey,
),
home: NavBar(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<Dish> _dishes = List<Dish>();
List<Dish> _cartList = List<Dish>();
#override
void initState() {
super.initState();
_populateDishes();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 16.0, top: 8.0),
child: GestureDetector(
child: Stack(
alignment: Alignment.topCenter,
children: <Widget>[
Icon(
Icons.shopping_cart,
size: 36.0,
),
if (_cartList.length > 0)
Padding(
padding: const EdgeInsets.only(left: 2.0),
child: CircleAvatar(
radius: 8.0,
backgroundColor: Colors.red,
foregroundColor: Colors.white,
child: Text(
_cartList.length.toString(),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 12.0,
),
),
),
),
],
),
onTap: () {
if (_cartList.isNotEmpty)
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Cart(_cartList),
),
);
},
),
)
],
),
body: _buildGridView(),
);
}
ListView _buildListView() {
return ListView.builder(
itemCount: _dishes.length,
itemBuilder: (context, index) {
var item = _dishes[index];
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8.0,
vertical: 2.0,
),
child: Card(
elevation: 4.0,
child: ListTile(
leading: Icon(
item.icon,
color: item.color,
),
title: Text(item.name),
trailing: GestureDetector(
child: (!_cartList.contains(item))
? Icon(
Icons.add_circle,
color: Colors.green,
)
: Icon(
Icons.remove_circle,
color: Colors.red,
),
onTap: () {
setState(() {
if (!_cartList.contains(item))
_cartList.add(item);
else
_cartList.remove(item);
});
},
),
),
),
);
},
);
}
GridView _buildGridView() {
return GridView.builder(
padding: const EdgeInsets.all(4.0),
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemCount: _dishes.length,
itemBuilder: (context, index) {
var item = _dishes[index];
return Card(
elevation: 4.0,
child: Stack(
fit: StackFit.loose,
alignment: Alignment.center,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
item.icon,
color: (_cartList.contains(item))
? Colors.grey
: item.color,
size: 100.0,
),
Text(
item.name,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.subhead,
)
],
),
Padding(
padding: const EdgeInsets.only(
right: 8.0,
bottom: 8.0,
),
child: Align(
alignment: Alignment.bottomRight,
child: GestureDetector(
child: (!_cartList.contains(item))
? Icon(
Icons.add_circle,
color: Colors.green,
)
: Icon(
Icons.remove_circle,
color: Colors.red,
),
onTap: () {
setState(() {
if (!_cartList.contains(item))
_cartList.add(item);
else
_cartList.remove(item);
});
},
),
),
),
],
));
});
}
void _populateDishes() {
var list = <Dish>[
Dish(
name: 'Chicken Zinger',
icon: Icons.fastfood,
color: Colors.amber,
),
Dish(
name: 'Chicken Zinger without chicken',
icon: Icons.print,
color: Colors.deepOrange,
),
Dish(
name: 'Rice',
icon: Icons.child_care,
color: Colors.brown,
),
Dish(
name: 'Beef burger without beef',
icon: Icons.whatshot,
color: Colors.green,
),
Dish(
name: 'Laptop without OS',
icon: Icons.laptop,
color: Colors.purple,
),
Dish(
name: 'Mac wihout macOS',
icon: Icons.laptop_mac,
color: Colors.blueGrey,
),
];
setState(() {
_dishes = list;
});
}
}
Cart.dart file
import 'package:flutter/material.dart';
import 'dish_object.dart';
class Cart extends StatefulWidget {
final List<Dish> _cart;
Cart(this._cart);
#override
_CartState createState() => _CartState(this._cart);
}
class _CartState extends State<Cart> {
_CartState(this._cart);
List<Dish> _cart;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Cart'),
),
body: ListView.builder(
itemCount: _cart.length,
itemBuilder: (context, index) {
var item = _cart[index];
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 2.0),
child: Card(
elevation: 4.0,
child: ListTile(
leading: Icon(
item.icon,
color: item.color,
),
title: Text(item.name),
trailing: GestureDetector(
child: Icon(
Icons.remove_circle,
color: Colors.red,
),
onTap: () {
setState(() {
_cart.remove(item);
});
},
),
),
),
);
},
),
);
}
}
NavBar.dart file
import 'package:flutter/material.dart';
import 'package:sharewallpaper/cart.dart';
import 'package:sharewallpaper/main.dart';
class NavBar extends StatefulWidget {
#override
_NavBarState createState() => _NavBarState();
}
class _NavBarState extends State<NavBar> {
int _currentIndex = 0;
final List<Widget> _children = [
MyHomePage(),
Cart(), ** This line is throwing an error **
];
void onTappedBar(int index) {
setState(() {
_currentIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: _children[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
onTap: onTappedBar,
currentIndex: _currentIndex,
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('Home')),
BottomNavigationBarItem(
icon: Icon(Icons.bookmark), title: Text('BookMark')),
],
),
);
}
}
Yep, it will throw an error because the constructor of the Cart class is expecting one parameter to be passed in. You could use a named constructor instead like this:
class Cart extends StatefulWidget {
final List<Dish> _cart;
Cart(this._cart);
That way, you can call it like so:
Cart(cart: _cartList),
But if you actually need the cart list, I would recommend that you write a provider to keep track of the cart data across screens.
My code is as follows:
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;
getNews() async{
News newsClass = News();
await newsClass.getNews();
articles = newsClass.news;
setState(() {
_loading = false;
});
}
#override
void initState() {
getNews();
categories = getCategories();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("News"),
Text("App", style: TextStyle(
color: Colors.blueAccent
),)
],
),
centerTitle: true,
elevation: 0.0,
),
body: _loading ? Center(
child: CircularProgressIndicator(),
) : SingleChildScrollView(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Column(
children: <Widget>[
/// Categories
Container(
height: 70,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: categories.length,
itemBuilder: (context, index){
return CategoryTile(
imageUrl: categories[index].imageUrl,
categoryName: categories[index].categoryName,
);
}),
),
/// Blog
Container(
padding: EdgeInsets.only(top: 16),
child: ListView.builder(
itemCount: articles.length,
shrinkWrap: true,
physics: ClampingScrollPhysics(),
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),
child: Stack(
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.circular(6),
child: CachedNetworkImage(
imageUrl: imageUrl, width: 120, height: 60, fit: BoxFit.cover,)
),
Container(
alignment: Alignment.center,
width: 120, height: 60,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
color: Colors.black26,
),
child: Text(categoryName, style: TextStyle(
color: Colors.white,
fontSize: 14,
fontWeight: FontWeight.w500
),),
)
],
),
),
);
}
}
class BlogTile extends StatelessWidget {
final String imageUrl, title, desc;
BlogTile({#required this.imageUrl,#required this.title,#required this.desc});
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.circular(6),
child: Image.network(imageUrl)
),
SizedBox(height: 8,),
Text(title, style: TextStyle(
fontSize: 17, color: Colors.black87, fontWeight: FontWeight.w500
),),
SizedBox(height: 8,),
Text(desc, style: TextStyle(
color: Colors.black54
),)
],
),
);
}
}
When I run the code it shows the loading screen which is not going off, the content which i want to display is not showing. Please help by providing your valuable answer. Thank you in advance.
The error I am getting is as follows:
E/flutter ( 5339): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: Failed assertion: boolean expression must not be null
Since you are initialising your _loading variable inside the first statement of the initState. You can as well initialise it directly when declaring it.
Like this:
bool _loading = true;
Try the code below:
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;
getNews() async{
News newsClass = News();
await newsClass.getNews();
articles = newsClass.news;
}
#override
void initState() {
getNews();
categories = getCategories();
setState(() {
_loading = false;
});
super.initState();
}
I hope this helps.