How to solve "a build function has returned null" in flutter app? - flutter

App was working perfectly before and then I had to make some changes to allow or restrict calling feature in the app based on subscription level of the user, by passing the variable value from one screen to another using provider.
one Screen 1 i am using :
Future<void> _verifyPuchase(String id) async {
PurchaseDetails purchase = _hasPurchased(id);
if (purchase != null && purchase.status == PurchaseStatus.purchased) {
print(purchase.productID);
if (Platform.isIOS) {
await _iap.completePurchase(purchase);
print('Achats antérieurs........$purchase');
isPuchased = true;
}
isPuchased = true;
checkIsPurchsed(isPurchsed: isPuchased);
} else {
isPuchased = false;
checkIsPurchsed(isPurchsed: isPuchased);
}
}
and have i have a class on screen 1:
class checkIsPurchsed with ChangeNotifier{
bool isPurchsed;
checkIsPurchsed({this.isPurchsed});
notifyListeners();
}
and on screen 5 I have:
Consumer<checkIsPurchsed>(
builder: (context,isPurchsed,child){
return isPurchsed.isPurchsed ? IconButton(
icon: Icon(Icons.call), onPressed: () => onJoin("AudioCall"),
):Center(child: Text(
'Sorry you have not subscribe the package',
),);
},
),
Consumer<checkIsPurchsed>(
builder: (context,isPurchsed,child){
return isPurchsed.isPurchsed ? IconButton(
icon: Icon(Icons.video_call), onPressed: () => onJoin("VideoCall"),
):Center(child: Text(
'Sorry you have not subscribe the package',
),);
},
),
on screen 5 when i try to open a chat this is what i am getting :
the icon buttons on which i am checking the purchase status appear when chat is opened , but after adding the above mentioned modifications the chat itself isnt opening and instead i am getting the red screen.
Update 1:
class ChatPage extends StatefulWidget {
final User sender;
final String chatId;
final User second;
ChatPage({this.sender, this.chatId, this.second});
#override
_ChatPageState createState() => _ChatPageState();
}
class _ChatPageState extends State<ChatPage> {
bool isBlocked = false;
final db = Firestore.instance;
CollectionReference chatReference;
final TextEditingController _textController = new TextEditingController();
bool _isWritting = false;
final _scaffoldKey = GlobalKey<ScaffoldState>();
//Ads _ads = new Ads();
#override
void initState() {
//_ads.myInterstitial()
//..load()
//..show();
print("object -${widget.chatId}");
super.initState();
chatReference =
db.collection("chats").document(widget.chatId).collection('messages');
checkblock();
}
var blockedBy;
checkblock() {
chatReference.document('blocked').snapshots().listen((onData) {
if (onData.data != null) {
blockedBy = onData.data['blockedBy'];
if (onData.data['isBlocked']) {
isBlocked = true;
} else {
isBlocked = false;
}
if (mounted) setState(() {});
}
// print(onData.data['blockedBy']);
});
}
List<Widget> generateSenderLayout(DocumentSnapshot documentSnapshot) {
return <Widget>[
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Container(
child: documentSnapshot.data['image_url'] != ''
? InkWell(
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
new Container(
margin: EdgeInsets.only(
top: 2.0, bottom: 2.0, right: 15),
child: Stack(
children: <Widget>[
CachedNetworkImage(
placeholder: (context, url) => Center(
child: CupertinoActivityIndicator(
radius: 10,
),
),
errorWidget: (context, url, error) =>
Icon(Icons.error),
height:
MediaQuery.of(context).size.height * .65,
width: MediaQuery.of(context).size.width * .9,
imageUrl:
documentSnapshot.data['image_url'] ?? '',
fit: BoxFit.fitWidth,
),
Container(
alignment: Alignment.bottomRight,
child:
documentSnapshot.data['isRead'] == false
? Icon(
Icons.done,
color: secondryColor,
size: 15,
)
: Icon(
Icons.done_all,
color: primaryColor,
size: 15,
),
)
],
),
height: 150,
width: 150.0,
color: secondryColor.withOpacity(.5),
padding: EdgeInsets.all(5),
),
Padding(
padding: const EdgeInsets.only(right: 10),
child: Text(
documentSnapshot.data["time"] != null
? DateFormat.yMMMd()
.add_jm()
.format(documentSnapshot.data["time"]
.toDate())
.toString()
: "",
style: TextStyle(
color: secondryColor,
fontSize: 13.0,
fontWeight: FontWeight.w600,
)),
)
],
),
onTap: () {
Navigator.of(context).push(
CupertinoPageRoute(
builder: (context) => LargeImage(
documentSnapshot.data['image_url'],
),
),
);
},
)
: Container(
padding: EdgeInsets.symmetric(
horizontal: 15.0, vertical: 10.0),
width: MediaQuery.of(context).size.width * 0.65,
margin: EdgeInsets.only(
top: 8.0, bottom: 8.0, left: 80.0, right: 10),
decoration: BoxDecoration(
color: primaryColor.withOpacity(.1),
borderRadius: BorderRadius.circular(20)),
child: Column(
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Container(
child: Text(
documentSnapshot.data['text'],
style: TextStyle(
color: Colors.black87,
fontSize: 16.0,
fontWeight: FontWeight.w600,
),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text(
documentSnapshot.data["time"] != null
? DateFormat.MMMd()
.add_jm()
.format(documentSnapshot
.data["time"]
.toDate())
.toString()
: "",
style: TextStyle(
color: secondryColor,
fontSize: 13.0,
fontWeight: FontWeight.w600,
),
),
SizedBox(
width: 5,
),
documentSnapshot.data['isRead'] == false
? Icon(
Icons.done,
color: secondryColor,
size: 15,
)
: Icon(
Icons.done_all,
color: primaryColor,
size: 15,
)
],
),
],
),
],
)),
),
],
),
),
];
}
_messagesIsRead(documentSnapshot) {
return <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
InkWell(
child: CircleAvatar(
backgroundColor: secondryColor,
radius: 25.0,
child: ClipRRect(
borderRadius: BorderRadius.circular(90),
child: CachedNetworkImage(
imageUrl: widget.second.imageUrl[0] ?? '',
useOldImageOnUrlChange: true,
placeholder: (context, url) => CupertinoActivityIndicator(
radius: 15,
),
errorWidget: (context, url, error) => Icon(Icons.error),
),
),
),
onTap: () => showDialog(
barrierDismissible: false,
context: context,
builder: (context) {
return Info(widget.second, widget.sender, null);
}),
),
],
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
child: documentSnapshot.data['image_url'] != ''
? InkWell(
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
new Container(
margin: EdgeInsets.only(
top: 2.0, bottom: 2.0, right: 15),
child: CachedNetworkImage(
placeholder: (context, url) => Center(
child: CupertinoActivityIndicator(
radius: 10,
),
),
errorWidget: (context, url, error) =>
Icon(Icons.error),
height: MediaQuery.of(context).size.height * .65,
width: MediaQuery.of(context).size.width * .9,
imageUrl:
documentSnapshot.data['image_url'] ?? '',
fit: BoxFit.fitWidth,
),
height: 150,
width: 150.0,
color: Color.fromRGBO(0, 0, 0, 0.2),
padding: EdgeInsets.all(5),
),
Padding(
padding: const EdgeInsets.only(right: 10),
child: Text(
documentSnapshot.data["time"] != null
? DateFormat.yMMMd()
.add_jm()
.format(documentSnapshot.data["time"]
.toDate())
.toString()
: "",
style: TextStyle(
color: secondryColor,
fontSize: 13.0,
fontWeight: FontWeight.w600,
)),
)
],
),
onTap: () {
Navigator.of(context).push(CupertinoPageRoute(
builder: (context) => LargeImage(
documentSnapshot.data['image_url'],
),
));
},
)
: Container(
padding: EdgeInsets.symmetric(
horizontal: 15.0, vertical: 10.0),
width: MediaQuery.of(context).size.width * 0.65,
margin: EdgeInsets.only(top: 8.0, bottom: 8.0, right: 10),
decoration: BoxDecoration(
color: secondryColor.withOpacity(.3),
borderRadius: BorderRadius.circular(20)),
child: Column(
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Container(
child: Text(
documentSnapshot.data['text'],
style: TextStyle(
color: Colors.black87,
fontSize: 16.0,
fontWeight: FontWeight.w600,
),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text(
documentSnapshot.data["time"] != null
? DateFormat.MMMd()
.add_jm()
.format(documentSnapshot
.data["time"]
.toDate())
.toString()
: "",
style: TextStyle(
color: secondryColor,
fontSize: 13.0,
fontWeight: FontWeight.w600,
),
),
],
),
],
),
],
)),
),
],
),
),
];
}
List<Widget> generateReceiverLayout(DocumentSnapshot documentSnapshot) {
if (!documentSnapshot.data['isRead']) {
chatReference.document(documentSnapshot.documentID).updateData({
'isRead': true,
});
return _messagesIsRead(documentSnapshot);
}
return _messagesIsRead(documentSnapshot);
}
generateMessages(AsyncSnapshot<QuerySnapshot> snapshot) {
return snapshot.data.documents
.map<Widget>((doc) => Container(
margin: const EdgeInsets.symmetric(vertical: 10.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: doc.data['type'] == "Call"
? [
Text(doc.data["time"] != null
? "${doc.data['text']} : " +
DateFormat.yMMMd()
.add_jm()
.format(doc.data["time"].toDate())
.toString() +
" by ${doc.data['sender_id'] == widget.sender.id ? "You" : "${widget.second.name}"}"
: "")
]
: doc.data['sender_id'] != widget.sender.id
? generateReceiverLayout(
doc,
)
: generateSenderLayout(doc)),
))
.toList();
}
#override
Widget build(BuildContext context) {
ChangeNotifierProvider<checkIsPurchsed>(
create: (context)=>checkblock(),
child: Scaffold(
key: _scaffoldKey,
backgroundColor: Colors.white,
appBar: AppBar(
centerTitle: true,
elevation: 0,
title: Text(widget.second.name),
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
color: Colors.white,
onPressed: () => Navigator.pop(context),
),
actions: <Widget>[
Consumer<checkIsPurchsed>(
builder: (context,isPurchsed,child){
return isPurchsed.isPurchsed ? IconButton(
icon: Icon(Icons.call), onPressed: () => onJoin("AudioCall"),
):Center(child: Text(
'Sorry you have not subscribe the package',
),);
},
),
Consumer<checkIsPurchsed>(
builder: (context,isPurchsed,child){
return isPurchsed.isPurchsed ? IconButton(
icon: Icon(Icons.video_call), onPressed: () => onJoin("VideoCall"),
):Center(child: Text(
'Sorry you have not subscribe the package',
),);
},
),
}

The problematic area is:
#override
Widget build(BuildContext context) {
ChangeNotifierProvider<checkIsPurchsed>(
There's no return in front of ChangeNotifierProvider, so it doesn't return a Widget. Correct would be:
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<checkIsPurchsed>(

Related

How do i return a container based on a list of item selected in flutter?

I have a list of items
List<String> items = [
"All",
"Jobs",
"Messages",
"Customers",
];
int current = 0;
And this list is directly responsible for my tab bar:
When i tap an item in the Tab bar i want to return a different container on each of them?
How do i go about this in flutter?
I tried returning an if statement just before the container but it seems i don't get the statement correctly.
this is the container i want to return if the item user select is All, and then put conditions in place for the rest items.
this is how i put the condition but it gives me this error
My return statement and code -
current = 0 ??
Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(
height: 10,
),
Text(
items[current],
style: GoogleFonts.laila(
fontWeight: FontWeight.w500,
fontSize: 30,
color: Colors.deepPurple),
),
],
),
),
current = 1 ?? Text('hello')
FULL WIDGET ADDED
class NotificationsView extends StatefulWidget {
#override
State<NotificationsView> createState() => _NotificationsViewState();
}
class _NotificationsViewState extends State<NotificationsView> {
final controller = Get.put(NotificationsController());
List<String> items = [
"All",
"Jobs",
"Messages",
"Customers",
];
int current = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"Notifications".tr,
style: GoogleFonts.poppins(
color: Color(0xff000000),
fontSize: 16,
fontWeight: FontWeight.w600),
),
centerTitle: false,
backgroundColor: Colors.transparent,
elevation: 0,
automaticallyImplyLeading: false,
leadingWidth: 15,
leading: new IconButton(
icon: new Icon(Icons.arrow_back_ios, color: Color(0xff3498DB)),
onPressed: () => {Get.back()},
),
),
body: RefreshIndicator(
onRefresh: () async {
},
child: ListView(
primary: true,
children: <Widget>[
filter(),
],
),
),
);
}
Widget notificationsList() {
return Obx(() {
if (!controller.notifications.isNotEmpty) {
return CircularLoadingWidget(
height: 300,
onCompleteText: "Notification List is Empty".tr,
);
} else {
var _notifications = controller.notifications;
return ListView.separated(
itemCount: _notifications.length,
separatorBuilder: (context, index) {
return SizedBox(height: 7);
},
shrinkWrap: true,
primary: false,
itemBuilder: (context, index) {
var _notification = controller.notifications.elementAt(index);
if (_notification.data['message_id'] != null) {
return MessageNotificationItemWidget(
notification: _notification);
} else if (_notification.data['booking_id'] != null) {
return BookingNotificationItemWidget(
notification: _notification);
} else {
return NotificationItemWidget(
notification: _notification,
onDismissed: (notification) {
controller.removeNotification(notification);
},
onTap: (notification) async {
await controller.markAsReadNotification(notification);
},
);
}
});
}
});
}
Widget filter() {
return Container(
width: double.infinity,
margin: const EdgeInsets.all(5),
child: Column(
children: [
/// CUSTOM TABBAR
SizedBox(
width: double.infinity,
height: 60,
child: ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: items.length,
scrollDirection: Axis.horizontal,
itemBuilder: (ctx, index) {
return Column(
children: [
GestureDetector(
onTap: () {
setState(() {
current = index;
});
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
margin: const EdgeInsets.all(5),
decoration: BoxDecoration(
color: current == index
? Color(0xff34495E)
: Color(0xffF5F5F5),
borderRadius: BorderRadius.circular(11),
),
child: Center(
child: Padding(
padding: const EdgeInsets.only(
left: 10.0, right: 10.0, top: 5, bottom: 5),
child: Text(
items[index],
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w500,
color: current == index
? Colors.white
: Colors.grey),
),
),
),
),
),
],
);
}),
),
/// MAIN BODY
current = 0 ??
Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(
height: 10,
),
Text(
items[current],
style: GoogleFonts.laila(
fontWeight: FontWeight.w500,
fontSize: 30,
color: Colors.deepPurple),
),
Padding(
padding: const EdgeInsets.only(
left: 20.0, right: 20.0, top: 20.0, bottom: 20),
child: Column(
children: [
Stack(
children: [
Row(
children: [
Container(
decoration: BoxDecoration(
color: Color(0xffEFFAFF),
borderRadius:
BorderRadius.circular(20)),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Image.asset(
'assets/icon/suitcase.png'),
),
),
SizedBox(
width: 15,
),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
'New Job started ',
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Color(0xff151515)),
),
Text(
'Tailoring for John Cletus ',
style: GoogleFonts.poppins(
fontSize: 10,
fontWeight: FontWeight.w400,
color: Color(0xff151515)),
),
],
),
Spacer(),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(2),
color: Color(0xffFFE8E8),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Urgent',
style: GoogleFonts.poppins(
color: Color(0xffC95E5E)),
),
),
),
],
),
],
),
Divider(
height: 5,
color: Color(0xffEFFAFF),
),
],
),
),
],
),
),
current = 1 ?? Text('hello')
],
),
);
}
}
You can use Builder if want to display different type of widget based on the current index.
Builder(
builder: (context) {
switch (current) {
case 0:
return Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(
height: 10,
),
Text(
items[current],
style: GoogleFonts.laila(
fontWeight: FontWeight.w500,
fontSize: 30,
color: Colors.deepPurple),
),
],
),
);
case 1:
return Text('Hello');
default:
return SizedBox.shrink();
}
},
);
Below approach will solve your problem. If you need further assistance, please feel free to comment.
int _currentIndex = 0;
var _containers = <Widget>[
AllContainer(),
JobsContainer(),
MessagesContainer(),
CustomerContainer(),
];
Widget _bottomTab() {
return BottomNavigationBar(
currentIndex: _currentIndex,
onTap: _onItemTapped, //
type: BottomNavigationBarType.fixed,
selectedLabelStyle: const TextStyle(color: Colors.blue),
selectedItemColor: WAPrimaryColor,
unselectedLabelStyle: const TextStyle(color: Colors.blue),
unselectedItemColor: Colors.grey,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(label: 'All'),
BottomNavigationBarItem(
label: 'Jobs'),
BottomNavigationBarItem(
label: 'Messages'),
BottomNavigationBarItem( label: 'Customer'),
],
);
}
void _onItemTapped(int index) async {
print('bottom index::: $index');
setState(() {
_currentIndex = index;
});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
bottomNavigationBar: _bottomTab(),
body: Center(child: _containers.elementAt(_currentIndex)),
),
);
}
You can use conditional if on widget level,
like
/// MAIN BODY
if (current == 0)
Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
...
),
if (current == 1) Text('hello')
Also can be use else if
if (current == 0)
Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
) //you shouldnt put coma
else if (current == 1) Text('hello')
],
),
);
But creating a separate method will be better instead of putting it here
Widget getWidget(int index) {
/// MAIN BODY
if (current == 0) // or switch case
return Container(
margin: const EdgeInsets.only(top: 30),
height: MediaQuery.of(context).size.height * 1,
); //you shouldnt put coma
else if (current == 1) return Text('hello');
return Text("default");
}
And call the method getWidget(current).
Also there are some widget like PageView, IndexedStack will help to organize the code structure

Flutter getX not updating UI after ading items to obs list

I'm using GetX to manage the state of my ecommerce app, and I'm stuck with the shopping cart.
I'm using Sqflite package to store carts locally.
issue: when i add a product to cart list it's not updating it automatically untill i restart the app i see the added items
Cart controller
addProductToCart(ProductModel product) async {
List<Map> items =
await _repository.getLocalByCondition('carts', 'productId', product.id);
if (items.length > 0) {
product.quantity = items.first['productQuantity'] + 1;
return await _repository.updateLocal(
'carts', 'productId', product.toMap());
}
product.quantity = 1;
return await _repository.saveLocal('carts', product.toMap());
}
#override
void onInit() {
super.onInit();
getCarts();
}
Add to cart product details
_addToCart(BuildContext context, ProductModel product) async {
int result = await _cartController.addProductToCart(product);
if (result > 0) {
Fluttertoast.showToast(msg: 'Item added to cart successfully!');
} else {
Fluttertoast.showToast(msg: 'Error to add product!');
}
}
Cart screen
Obx(() {
return Scaffold(
appBar: AppBar(
title: Text('Cart (${_cartController.cartList.length} items)',
style: TextStyle(color: Colors.black))),
bottomNavigationBar: InkWell(
onTap: () {
//_checkout(_cartController.cartList);
},
child: Container(
color: Colors.black,
height: 55,
margin: EdgeInsets.all(8),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Checkout',
style: TextStyle(color: Colors.white),
),
SizedBox(
width: 10,
),
Text(
'£' + _cartController.total.toString(),
style: TextStyle(color: Colors.white),
)
],
),
)),
body: _cartController.loading.isTrue
? Center(child: CircularProgressIndicator())
: _cartController.cartList.length > 0
? ListView.builder(
padding:
EdgeInsets.symmetric(horizontal: 8, vertical: 12),
itemBuilder: (context, index) {
return Dismissible(
key: Key(this
._cartController
.cartList[index]
.id
.toString()),
onDismissed: (val) async {
var x= await _cartController.deleteCartItem(
index, this._cartController.cartList[index].id);
if(x!>0) Fluttertoast.showToast(msg: 'deleted');
else{ Fluttertoast.showToast(msg: x.toString());
}
},
background: Container(
child: Align(
alignment: Alignment.centerRight,
child: Padding(
padding: const EdgeInsets.only(right: 28.0),
child: Icon(
Icons.delete_outline_outlined,
size: 36,
color: Colors.white,
),
)),
color: Colors.redAccent),
child: Card(
elevation: 5,
shape: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(7),
)),
child: Container(
margin: EdgeInsets.all(4),
height: 120,
child: Row(
children: [
Expanded(
flex: 3,
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(5),
topRight: Radius.circular(5)),
child: Image.network(
_cartController.cartList[index].photo,
width: 150,
height: 120,
fit: BoxFit.cover,
),
),
),
Expanded(
flex: 5,
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
_cartController
.cartList[index].name,
overflow: TextOverflow.clip,
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'${_cartController.cartList[index].price - _cartController.cartList[index].discount} ' +
" x " +
_cartController
.cartList[index].quantity
.toString(),
style: TextStyle(
fontWeight: FontWeight.w500),
),
),
],
)),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
IconButton(
icon: Icon(Icons.keyboard_arrow_up),
onPressed: () {
_cartController.total.value += this
._cartController
.cartList[index]
.price -
this
._cartController
.cartList[index]
.discount;
this
._cartController
.cartList[index]
.quantity++;
},
),
Text(_cartController
.cartList[index].quantity
.toString()),
IconButton(
icon: Icon(Icons.keyboard_arrow_down),
onPressed: () {
if (_cartController
.cartList[index].quantity >
1) {
_cartController.total.value -= (this
._cartController
.cartList[index]
.price -
this
._cartController
.cartList[index]
.discount);
this
._cartController
.cartList[index]
.quantity--;
}
},
),
],
))
],
),
),
),
);
},
itemCount: _cartController.cartList.length,
)
: Center(
child: Text('Your Shopping cart is empty'),
));
});
You need to add product in _cartController.cartList.
_addToCart(BuildContext context, ProductModel product) async {
cartList.add(product);
....
}

ListView.builder returns Null check operator used on a null value

I'm developing a job search app that scrapes data from Indeed using Python which is being sent back to my Flutter UI as JSON data. The JSON data is being received successfully, however, Im getting an error of Null check operator used on a null value. The error appears to be stemming from the _jobSearch widget.
The relevant error-causing widget was ListView lib/ui/home_page.dart:256
Exception caught by scheduler library
Null check operator used on a null value
Here is the code:
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:flutter_job_portal/theme/colors.dart';
import 'package:flutter_job_portal/theme/images.dart';
import 'package:flutter_job_portal/ui/bottom_menu_bar.dart';
import 'package:flutter_job_portal/ui/job_detail_page.dart';
String job = ""; //user's response will be assigned to this variable
String final_response = "";
final _formkey = GlobalKey<FormState>(); //key created to interact with the form
//function to validate and save user form
Future<void> _savingData() async {
final validation = _formkey.currentState.validate();
if (!validation) {
return;
}
_formkey.currentState.save();
}
Future<List<Job>> _getJobs() async {
final url = 'http://127.0.0.1:5000/job';
final response1 = await http.post(Uri.parse(url), body: json.encode({'job': job}));
final response2 = await http.get(Uri.parse(url));
final decoded = json.decode(response2.body);
List<Job> jobs = [];
for (var i in decoded) {
Job job = Job(i['Title'], i['Company'], i['Location'], i['Salary']);
jobs.add(job);
}
return jobs;
}
class Job {
final String title;
final String company;
final String location;
final String salary;
Job(this.title, this.company, this.location, this.salary);
}
class HomePage extends StatelessWidget {
const HomePage({Key key}) : super(key: key);
Widget _appBar(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 10),
child: Row(
children: [
CircleAvatar(
backgroundImage: AssetImage(Images.user1),
),
Spacer(),
IconButton(
icon: Icon(Icons.notifications_none_rounded),
onPressed: () {},
)
],
),
);
}
Widget _header(BuildContext context) {
return Container(
margin: EdgeInsets.symmetric(vertical: 12),
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Hello, Alex!",
style: TextStyle(
fontSize: 15,
color: KColors.subtitle,
fontWeight: FontWeight.w500,
)),
SizedBox(
height: 6,
),
Text("Swipe to find your future",
style: TextStyle(
fontSize: 20,
color: KColors.title,
fontWeight: FontWeight.bold)),
SizedBox(
height: 10,
),
Row(
children: [
Expanded(
child: Container(
height: 45,
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: KColors.lightGrey,
borderRadius: BorderRadius.circular(10)),
child: Form(
key: _formkey,
child: TextFormField(
decoration: InputDecoration(
hintText: 'Search job title or keywords',
),
onSaved: (value) {
job =
value; //getting data from the user form and assigning it to job
},
),
),
),
),
SizedBox(
width: 16,
),
Container(
decoration: BoxDecoration(
color: KColors.primary,
borderRadius: BorderRadius.circular(10),
),
height: 40,
child: IconButton(
color: KColors.primary,
icon: Icon(Icons.search, color: Colors.white),
onPressed: () async {
_savingData();
_getJobs();
},
),
)
],
)
],
),
);
}
Widget _recommendedSection(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 10),
margin: EdgeInsets.symmetric(vertical: 12),
height: 200,
width: MediaQuery.of(context).size.width,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Recommended",
style: TextStyle(fontWeight: FontWeight.bold, color: KColors.title),
),
SizedBox(height: 10),
Expanded(
child: ListView(
scrollDirection: Axis.horizontal,
children: [
_recommendedJob(context,
company: "Google",
img: Images.google,
title: "UX Designer",
sub: "\$45,000 Remote",
isActive: true),
_recommendedJob(context,
company: "DropBox",
img: Images.dropbox,
title: "Research Assist",
sub: "\$45,000 Remote",
isActive: false)
],
),
),
],
),
);
}
Widget _recommendedJob(
BuildContext context, {
String img,
String company,
String title,
String sub,
bool isActive = false,
}) {
return Padding(
padding: const EdgeInsets.only(right: 10),
child: GestureDetector(
onTap: () {
Navigator.push(context, JobDetailPage.getJobDetail());
},
child: AspectRatio(
aspectRatio: 1.3,
child: Container(
decoration: BoxDecoration(
color: isActive ? KColors.primary : Colors.white,
borderRadius: BorderRadius.circular(7),
),
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: 40,
width: 40,
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
color: isActive ? Colors.white : KColors.lightGrey,
borderRadius: BorderRadius.circular(7),
),
child: Image.asset(img),
),
SizedBox(height: 16),
Text(
company,
style: TextStyle(
fontSize: 12,
color: isActive ? Colors.white38 : KColors.subtitle,
),
),
SizedBox(height: 6),
Text(
title,
style: TextStyle(
fontSize: 14,
color: isActive ? Colors.white : KColors.title,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 6),
Text(
sub,
style: TextStyle(
fontSize: 12,
color: isActive ? Colors.white38 : KColors.subtitle,
),
),
],
),
),
),
),
);
}
Widget _jobSearch(BuildContext context) {
return new Container(
child: FutureBuilder(
future: _getJobs(),
builder: (context, snapshot) {
if (snapshot.data == null) {
return Container(
child: Center(
child: Text('Loading...'),
));
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(snapshot.data[index].location),
);
},
);
}
},
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: KColors.background,
bottomNavigationBar: BottomMenuBar(),
body: SafeArea(
child: Container(
width: MediaQuery.of(context).size.width,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_appBar(context),
_header(context),
_recommendedSection(context),
_jobSearch(context)
],
),
),
),
),
);
}
}

setState() or markNeedsBuild() called during build. when call native ad

import 'package:facebook_audience_network/ad/ad_native.dart';
import 'package:facebook_audience_network/facebook_audience_network.dart';
import 'package:flutter/material.dart';
import 'package:share/share.dart';
import 'package:social_share/social_share.dart';
import 'package:clipboard_manager/clipboard_manager.dart';
// ignore: camel_case_types
class listview extends StatefulWidget {
const listview({
Key key,
#required this.records,
}) : super(key: key);
final List records;
#override
_listviewState createState() => _listviewState();
}
// ignore: camel_case_types
class _listviewState extends State<listview> {
#override
void initState() {
super.initState();
FacebookAudienceNetwork.init(
testingId: "35e92a63-8102-46a4-b0f5-4fd269e6a13c",
);
// _loadInterstitialAd();
// _loadRewardedVideoAd();
}
// ignore: unused_field
Widget _currentAd = SizedBox(
width: 0.0,
height: 0.0,
);
Widget createNativeAd() {
_showNativeAd() {
_currentAd = FacebookNativeAd(
adType: NativeAdType.NATIVE_AD,
backgroundColor: Colors.blue,
buttonBorderColor: Colors.white,
buttonColor: Colors.deepPurple,
buttonTitleColor: Colors.white,
descriptionColor: Colors.white,
width: double.infinity,
height: 300,
titleColor: Colors.white,
listener: (result, value) {
print("Native Ad: $result --> $value");
},
);
}
return Container(
width: double.infinity,
height: 300,
child: _showNativeAd(),
);
}
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: this.widget.records.length,
itemBuilder: (BuildContext context, int index) {
var card = Container(
child: Card(
margin: EdgeInsets.only(bottom: 10),
elevation: 10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(1.0),
),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: () {
print(this.widget.records);
},
child: Image.asset(
"assets/icons/avatar.png",
height: 45,
),
),
),
Padding(
padding: const EdgeInsets.only(left: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
(this
.widget
.records[index]['fields']['Publisher Name']
.toString()),
style: TextStyle(fontWeight: FontWeight.bold),
),
Text(
(this
.widget
.records[index]['fields']['Date']
.toString()),
style: TextStyle(
fontSize: 12,
),
),
],
),
)
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: MediaQuery.of(context).size.width * 0.90,
// height: MediaQuery.of(context).size.height * 0.20,
decoration: BoxDecoration(
border: Border.all(
color: Colors.purple,
width: 3.0,
),
),
child: Center(
child: Padding(
padding: const EdgeInsets.all(18.0),
child: Text(
(this
.widget
.records[index]['fields']['Shayari']
.toString()),
style: TextStyle(
color: Colors.green,
fontWeight: FontWeight.bold,
),
),
),
),
),
),
SizedBox(
height: 5,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
GestureDetector(
onTap: () {
ClipboardManager.copyToClipBoard(this
.widget
.records[index]['fields']['Shayari']
.toString())
.then((result) {
final snackBar = SnackBar(
content: Text('Copied to Clipboard'),
);
Scaffold.of(context).showSnackBar(snackBar);
});
print(this
.widget
.records[index]['fields']['Shayari']
.toString());
},
child: Image.asset(
"assets/icons/copy.png",
height: 25,
),
),
GestureDetector(
onTap: () async {
SocialShare.checkInstalledAppsForShare().then(
(data) {
print(data.toString());
},
);
},
child: Image.asset(
"assets/icons/whatsapp.png",
height: 35,
),
),
GestureDetector(
onTap: () async {
Share.share("Please Share https://google.com");
},
child: Image.asset(
"assets/icons/share.png",
height: 25,
),
),
],
),
SizedBox(
height: 5,
),
],
),
),
);
return Column(
children: [
card,
index != 0 && index % 5 == 0
? /* Its Show When Value True*/ createNativeAd()
: /* Its Show When Value false*/ Container()
],
);
},
);
}
}
I Am Having This Error setState() or markNeedsBuild() called during build.
I Try To Call Facebook Native Ads Between My Dynamic List View But Showing this error when I call native ad createNativeAd This is My Widget Where I set Native ad
This is code where I call ad
** return Column(
children: [
card,
index != 0 && index % 5 == 0
? /* Its Show When Value True*/ createNativeAd()
: /* Its Show When Value false*/ Container()
],
);
},
);**

Flutter - How to add scrollview to column with listview in flutter

I have a container with a column that have three containers and one listview wrapped with expanded which works perfectly but am trying to add a scrollview to the whole container so that on the three scroll with the listview, please how can I achieve this? Below is what my code looks like.
List<Content> content = [];
_fetchComments() async {
setState(() {
isLoading = true;
_isDealButtonRefresh = true;
});
try {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
print('connected');
String baseURL;
debugPrint("my select:$_mySelection");
if (_mySelection == null && _myFeatureSelection == null) {
baseURL = "myjson link";
} else if (_myFeatureSelection != null) {
baseURL =
"my json link" +
_myFeatureSelection;
debugPrint("feature enter");
_mySelection = null;
} else if (_mySelection != null && _myFeatureSelection == null) {
baseURL = "my json link" +
_mySelection;
}
print("our url:$baseURL");
final response = await http.get(baseURL);
if (response.statusCode == 200) {
print(response.body);
content = (json.decode(response.body) as List)
.map((data) => new Content.fromJson(data))
.toList();
setState(() {
print(response.body);
isLoading = false;
_isDealButtonRefresh = false;
});
} else {
print(response.body);
throw Exception('Failed to load post');
}
}
} on SocketException catch (_) {
print('not connected');
setState(() => isLoading = false);
Navigator.pushReplacement(
context,
new MaterialPageRoute(
builder: (BuildContext context) => NoInternet()));
}
}
initState() {
super.initState();
_fetchComments();
}
body: Container(
child: Column(children: <Widget>[
Container(),
Container(),
Container(),
Expanded(child: ListView.separated(
separatorBuilder:
(context, index) => Divider(
color: Colors.grey,
),
itemCount: content == null
? 0
: _searchResult.length,
itemBuilder:
(context, position) {
final current =
_searchResult[position];
double myrate = double.parse(
_searchResult[position]
.ratings ==
null
? "0"
: _searchResult[position]
.ratings);
debugPrint("rato:$myrate");
return FutureBuilder<String>(
future: getDistance(
current.lat,
current.lng)
.then((value) =>
value.toString()),
builder:
(context, snapshot) {
return Container(
child:
GestureDetector(
onTap: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (BuildContext ctx) => Maps(_searchResult[position])));
},
child:
Column(
children: <
Widget>[
Row(
children: <
Widget>[
Expanded(
child:Container(
height:150,
width: MediaQuery.of(context).size.width,
child: SizedBox(
child: FadeInImage(image: NetworkImage(_searchResult[position].thumbnail_name), placeholder: AssetImage("assets/640x360.png"),
fit: BoxFit.cover,),
),
)),
],
),
Container(
padding:
const EdgeInsets.all(5.0),
child:
Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: Column(
children: <Widget>[
Container(
padding: const EdgeInsets.only(bottom: 1.0),
child: Text(
_searchResult[position].title,
style: TextStyle(fontFamily: 'Montserrat', fontSize: 13, fontWeight: FontWeight.bold),
),
),
Container(
padding: const EdgeInsets.only(bottom: 1.0),
child: Text(
_searchResult[position].address,
maxLines: 2,
style: TextStyle(fontFamily: 'Montserrat', fontSize: 10, color: Colors.black54),
),
),
Container(
padding: const EdgeInsets.only(bottom: 1.0),
child: _status != PermissionStatus.denied
? snapshot.hasData
? Text(
snapshot.data + " " + "km",
maxLines: 1,
style: TextStyle(fontFamily: 'Montserrat', fontSize: 10, fontWeight: FontWeight.bold, color: colorBlue),
)
: SizedBox(
child: CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation<Color>(
colorBlue,
),
strokeWidth: 1,
),
height: 5.0,
width: 5.0,
)
: Icon(
Icons.do_not_disturb,
color: Colors.red,
size: 15,
), ),
SizedBox(
height: 2,
),
Container(
child: Text(
_searchResult[position].price + " " + "USD",
style: TextStyle(
color: colorPink,
fontWeight: FontWeight.bold,
fontSize: 12,
fontFamily: 'Montserrat',
),
),
)
],
crossAxisAlignment: CrossAxisAlignment.start,
),
flex: 9,
),
Column(
children: <Widget>[
Container(
padding: const EdgeInsets.only(bottom: 0),
child: SmoothStarRating(
allowHalfRating: false,
onRatingChanged: (v) {
setState(() {});
},
starCount: 5,
rating: myrate,
size: 12.0,
filledIconData: Icons.star,
halfFilledIconData: Icons.star_half,
color: Colors.orange,
borderColor: Colors.orange,
spacing: 0.0)),
Text(
"(" + myrate.toStringAsFixed(1) + ")",
style: TextStyle(color: Colors.black, fontFamily: 'Montserrat', fontSize: 10, fontWeight: FontWeight.bold, fontStyle: FontStyle.normal),
),
],
)
],
),
)
],
)));
});
}))
])
)
In the above code the listview fetch it data from json rest API.
You could add the 3 inner containers as children of the listview.
Something like this:
Widget getListView(yourListWithData) {
List<Widget> listViewChildren = [
Container(),
Container(),
Container(),
];
listViewChildren.addAll(
yourListWithData
.map(
(e) => Text(e), //text widget as an example, use your own widget
)
.toList(),
);
return ListView(
children: listViewChildren,
);
}
And then you can get rid of the Column and make the listview the only child of the parent container:
Container(
child: getListView(yourListWithData),
);
To solve that:
Add SingleChildScrollView Widget at the beginning with physics: ClampingScrollPhysics() propertie .
Add shrinkWrap: true propertie to your Listview .
SingleChildScrollView(
scrollDirection: Axis.vertical,
physics: ClampingScrollPhysics(),
child: Container(
child: Column( crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(),
Container(),
Container(),
Expanded(child: Listview.builder(shrinkWrap: true,))
])
)
I hope to help you
So finally after many months of research, I was able to resolve this by giving the height of each container. Since I want the height of the listview to cover most of the space in the activity I didn't set the height for the Container with the ListView. First I changed the Expanded() above to Container(), set ListView shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), . Find below my updated code:
body: Container(
child: Column(children: <Widget>[
Container(height: MediaQuery.of(context).size.height * 0.16,
),
Container(height: MediaQuery.of(context).size.height * 0.16,
),
Container(height: MediaQuery.of(context).size.height * 0.16,
),
Container(child: ListView.separated(shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
separatorBuilder:
(context, index) => Divider(
color: Colors.grey,
),
itemCount: content == null
? 0
: _searchResult.length,
itemBuilder:
(context, position) {
final current =
_searchResult[position];
double myrate = double.parse(
_searchResult[position]
.ratings ==
null
? "0"
: _searchResult[position]
.ratings);
debugPrint("rato:$myrate");
return FutureBuilder<String>(
future: getDistance(
current.lat,
current.lng)
.then((value) =>
value.toString()),
builder:
(context, snapshot) {
return Container(
child:
GestureDetector(
onTap: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (BuildContext ctx) => Maps(_searchResult[position])));
},
child:
Column(
children: <
Widget>[
Row(
children: <
Widget>[
Expanded(
child:Container(
height:150,
width: MediaQuery.of(context).size.width,
child: SizedBox(
child: FadeInImage(image: NetworkImage(_searchResult[position].thumbnail_name), placeholder: AssetImage("assets/640x360.png"),
fit: BoxFit.cover,),
),
)),
],
),
Container(
padding:
const EdgeInsets.all(5.0),
child:
Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: Column(
children: <Widget>[
Container(
padding: const EdgeInsets.only(bottom: 1.0),
child: Text(
_searchResult[position].title,
style: TextStyle(fontFamily: 'Montserrat', fontSize: 13, fontWeight: FontWeight.bold),
),
),
Container(
padding: const EdgeInsets.only(bottom: 1.0),
child: Text(
_searchResult[position].address,
maxLines: 2,
style: TextStyle(fontFamily: 'Montserrat', fontSize: 10, color: Colors.black54),
),
),
Container(
padding: const EdgeInsets.only(bottom: 1.0),
child: _status != PermissionStatus.denied
? snapshot.hasData
? Text(
snapshot.data + " " + "km",
maxLines: 1,
style: TextStyle(fontFamily: 'Montserrat', fontSize: 10, fontWeight: FontWeight.bold, color: colorBlue),
)
: SizedBox(
child: CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation<Color>(
colorBlue,
),
strokeWidth: 1,
),
height: 5.0,
width: 5.0,
)
: Icon(
Icons.do_not_disturb,
color: Colors.red,
size: 15,
), ),
SizedBox(
height: 2,
),
Container(
child: Text(
_searchResult[position].price + " " + "USD",
style: TextStyle(
color: colorPink,
fontWeight: FontWeight.bold,
fontSize: 12,
fontFamily: 'Montserrat',
),
),
)
],
crossAxisAlignment: CrossAxisAlignment.start,
),
flex: 9,
),
Column(
children: <Widget>[
Container(
padding: const EdgeInsets.only(bottom: 0),
child: SmoothStarRating(
allowHalfRating: false,
onRatingChanged: (v) {
setState(() {});
},
starCount: 5,
rating: myrate,
size: 12.0,
filledIconData: Icons.star,
halfFilledIconData: Icons.star_half,
color: Colors.orange,
borderColor: Colors.orange,
spacing: 0.0)),
Text(
"(" + myrate.toStringAsFixed(1) + ")",
style: TextStyle(color: Colors.black, fontFamily: 'Montserrat', fontSize: 10, fontWeight: FontWeight.bold, fontStyle: FontStyle.normal),
),
],
)
],
),
)
],
)));
});
}))
])
)