Related
I am trying to scrape a countdown website using Flutter webscraper package. I successfully scraped the images and titles, but couldn't scrape the timer running, as it changes according to the timer, so after doing some research I saw that if I disable the JavaScript I can scrape the counter but I'm unable to do so..
class _SchedulesState extends State<Schedules> {
late List<Map<String, dynamic>> scheduleWall = [];
late List<Map<String, dynamic>> scheduleEpisode = [];
late List<Map<String, dynamic>> scheduleName = [];
late List<Map<String, dynamic>> scheduleDay = [];
late List<Map<String, dynamic>> scheduleHour = [];
late List<Map<String, dynamic>> scheduleMins = [];
bool scheduleLoaded = false;
int page = 1;
void scheduleFetch() async {
final scheduleScraper = WebScraper("https://animecountdown.com");
isJavaScriptSimpleObject(false);
if (await scheduleScraper.loadWebPage("")) {
scheduleWall = scheduleScraper.getElement(
'countdown-content-main-columns-column-items-item-left-poster > img',
['src'],
);
scheduleName = scheduleScraper.getElement(
'countdown-content-main-columns-column-items-item-right > countdown-content-main-columns-column-items-item-right-title',
['title'],
);
scheduleEpisode = scheduleScraper.getElement(
'countdown-content-main-columns-column-items-item-right > countdown-content-main-columns-column-items-item-right-episode',
['title'],
);
scheduleDay = scheduleScraper.getElement(
'div.countdown-item.day > div.countdown-item-number',
['title'],
);
scheduleHour = scheduleScraper.getElement(
'div.countdown-item.hour > div.countdown-item-number',
['title'],
);
scheduleMins = scheduleScraper.getElement(
'div.countdown-item.min > div.countdown-item-number',
['title'],
);
// ignore: avoid_print
print(scheduleName);
setState(() {
scheduleLoaded = true;
});
}
}
#override
void initState() {
super.initState();
scheduleFetch();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xff121212),
body: scheduleLoaded
? SafeArea(
child: SingleChildScrollView(
child: Wrap(
children: [
for (int i = 0; i < scheduleWall.length; i++)
Padding(
padding: const EdgeInsets.only(
left: 25.0, top: 20.0, right: 25.0, bottom: 20.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(20.0),
child: Stack(
children: [
CachedNetworkImage(
imageUrl: "https:" +
scheduleWall[i]['attributes']['src'],
color: Colors.grey,
colorBlendMode: BlendMode.multiply,
fit: BoxFit.cover,
width: 400,
height: 450.0,
placeholder: (context, url) {
return const Padding(
padding: EdgeInsets.all(8.0),
child: Center(
child: SpinKitPulse(
size: 40.0,
color: Colors.cyan,
),
),
);
},
),
Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Text(scheduleName[i]['title'],
maxLines: 2,
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 30.0)),
),
),
const SizedBox(
height: 115.0,
),
Center(
child: Text(scheduleEpisode[i]['title'],
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 30.0)),
),
const SizedBox(height: 140),
Row(
children: [
Padding(
padding:
const EdgeInsets.only(left: 85.0),
child: Text(scheduleEpisode[i]['title'],
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 2.0)),
),
Padding(
padding:
const EdgeInsets.only(left: 50.0),
child: Text(scheduleEpisode[i]['title'],
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 2.0)),
),
Padding(
padding:
const EdgeInsets.only(left: 50.0),
child: Text(scheduleEpisode[i]['title'],
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 2.0)),
),
const SizedBox(),
],
),
Row(
children: const [
Padding(
padding: EdgeInsets.only(left: 85.0),
child: Text("days",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 20.0)),
),
Padding(
padding: EdgeInsets.only(left: 40.0),
child: Text("hours",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 20.0)),
),
Padding(
padding: EdgeInsets.only(left: 30.0),
child: Text("mins",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 20.0)),
),
],
)
],
)
],
),
),
)
],
),
),
)
: const Center(
child: SpinKitWanderingCubes(color: Colors.cyanAccent),
),
);
}
}
I'm pretty much self-tutoring flutter and I'm working on a personal project. I wrapped it to singlechildscrollview but it still produces the problem. The code below:
class ScheduleDetail extends StatefulWidget {
var data;
ScheduleDetail(this.data);
#override
// ScheduleDetail({Key key, this.todos}) : super(key: key);
_ScheduleDetailState createState() => _ScheduleDetailState();
}
class _ScheduleDetailState extends State<ScheduleDetail>{
String foos = 'One';
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
ScreenUtil.instance =
ScreenUtil(width: 750, height: 1425, allowFontScaling: true)
..init(context);
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
// title: Text("String Master"),
title: SvgPicture.asset('assets/images/Logo_small.svg'),
centerTitle: true,
backgroundColor: Colors.transparent,
),
body: BackgroundImageWidget(
child: Center(
child: Container(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
height: ScreenUtil.getInstance().setHeight(150),
),
Container(
padding: EdgeInsets.symmetric(
horizontal: ScreenUtil.getInstance().setWidth(40),
),
child: Text(
AppStrings.scheduleTitle,
style: TextStyles.appName,
textAlign: TextAlign.center,
),
),
Container(
height: ScreenUtil.getInstance().setHeight(50),
),
SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.82),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: ScreenUtil.getInstance().setWidth(40),
),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
_buildTopCard(),
SizedBox(height: 10),
_buildTimeCard(),
SizedBox(height: 10),
ListTile(
title: Text(
"Calendar",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.green,
fontSize: 16
),
),
),
Container(color: Colors.grey, height: 1),
_buildNoticeExpansionTile(),
Container(color: Colors.grey, height: 1),
_buildMemoExpansionTile(),
],
)),
),
],
)
)
),
],
)),
)));
}
Widget _buildTopCard() {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7.0),
),
elevation: 15,
child: ClipPath(
clipper: ShapeBorderClipper(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7.0))),
child: Stack(
children: <Widget>[
Container(
height: 150,
decoration: BoxDecoration(
border: Border(
top: BorderSide(color: Colors.green, width: 30)),
color: Colors.white,
),
alignment: Alignment.centerLeft,
child: Column(
children: <Widget>[
ListTile(
title: Text(widget.data['eventTitle'],
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.green,
),
),
subtitle: Text(
widget.data['location'],
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.grey.shade600
),
),
),
Container(
padding: EdgeInsets.only(left: 10, right: 10),
child:
Divider(color: Colors.grey),
),
Container(
padding: EdgeInsets.only(left: 10, right: 10),
child: Row (
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
widget.data['startDate'] + " " + widget.data['timeStart'],
style: TextStyle(
color: Colors.grey.shade600,
fontStyle: FontStyle.italic,
fontSize: 14
),
),
Spacer(flex: 2),
Text(
widget.data['startDate'] + " " + widget.data['timeEnd'],
style: TextStyle(
color: Colors.grey.shade600,
fontSize: 14,
fontStyle: FontStyle.italic,
),
),
]
)
),
],
)
),
Positioned(
left: 10,
top: 7,
width: 325,
child: Container(
padding: EdgeInsets.only(bottom: 10, left: 5, right: 5),
color: Colors.transparent,
child: Row (
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
widget.data['startDate'],
style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white, fontSize: 14),
),
Spacer(flex: 2),
Text(
widget.data['timeStart'],
style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white, fontSize: 14),
),
],
)
),
),
],
)
),
);
}
Widget _buildTimeCard() {
return Container(
height: 125,
width: 400,
margin: EdgeInsets.all(5.0),
decoration: BoxDecoration(
color: Colors.black,
border: Border.all(
color: Colors.green,
width: 0.5,
),
borderRadius: BorderRadius.circular(7.0),
),
child: Center(
child: Text(
'TIME OF EVENT',
style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white, fontSize: 14),
),
),
);
}
Widget _buildNoticeExpansionTile() {
return Theme(
data: Theme.of(context).copyWith(unselectedWidgetColor: Colors.white, accentColor: Colors.white),
child: ExpansionTile(
title: new Text(
"Notice",
style: TextStyle(
color: Colors.green,
fontSize: 16
),
),
backgroundColor: Colors.transparent,
children: <Widget>[
Container(
child: ListView.builder(
padding: EdgeInsets.all(0.0),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: widget.data['notice'] != null ? widget.data['notice'].length : 0,
itemBuilder: (BuildContext context, int index){
return
Padding(
padding: EdgeInsets.only(left: 15, bottom: 10),
child: Text(
"\u2022 " + widget.data['notice'][index],
style: TextStyle(
color: Colors.white,
fontSize: 14
),
)
);
}
)
),
]
)
);
}
Widget _buildMemoExpansionTile() {
return
Theme(
data: Theme.of(context).copyWith(unselectedWidgetColor: Colors.white, accentColor: Colors.white),
child: ExpansionTile(
title: new Text(
"Memo",
style: TextStyle(
color: Colors.green,
fontSize: 16
),
),
backgroundColor: Colors.transparent,
children: <Widget>[
ListView.builder(
padding: EdgeInsets.all(0.0),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: widget.data['memo'] != null ? widget.data['memo'].length : 0,
itemBuilder: (BuildContext context, int index){
return
Padding(
padding: EdgeInsets.only(left: 15, bottom: 10),
child: Text(
(index + 1).toString() + ". " + widget.data['memo'][index],
style: TextStyle(
color: Colors.white,
fontSize: 14
),
)
);
}
)
]
)
);
}
}
Perhaps my mistake could be from one of those objects that I have used. However, I can't figure it out even though I searched around the internet. My intention is when the expandable tiles have 'overlapped' the screen size, you would be able to scroll it all the way down.
Wrap the SingleChildScrollView in Expanded Widget.
You can make use of the flutter dev tools for identifying overlapping issues.
I simplified the scaffold then wrapped SingleChildScrollView within Flexible.
I am having problem when I used the scrollcontroller to controll the gridview. I am having the error ( type 'String' is not a subtype of type 'int' of 'index'). But it was perfectly working before using the scrollcontroller. I don't where i need to change in order to remove this error. I also check the other issues regarding this in stackoverflow but couldn't get it. Can anyone check and tell me what can be change here in order to remove the error and show the data and also if my condition is right for loading 10 data in every scroll end.
import 'dart:convert';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:gridview_screoll/grid_content.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'constant.dart';
class ScrollableGrid extends StatefulWidget {
#override
_ScrollableGridState createState() => _ScrollableGridState();
}
class _ScrollableGridState extends State<ScrollableGrid> {
List data = [];
bool isLoading = false;
ScrollController _scrollController;
int pageCount = 1;
#override
void initState() {
// TODO: implement initState
super.initState();
this.fetchTopProducts();
addItemIntoLisT(pageCount);
_scrollController = new ScrollController(initialScrollOffset: 5.0)
..addListener(_scrollListener);
}
_scrollListener() {
if (_scrollController.offset >=
_scrollController.position.maxScrollExtent &&
!_scrollController.position.outOfRange) {
setState(() {
isLoading = true;
if (isLoading) {
pageCount = pageCount + 1;
addItemIntoLisT(pageCount);
}
});
}
}
void addItemIntoLisT(var pageCount) {
for (int i = (pageCount * 10) - 10; i < pageCount * 10; i++) {
fetchTopProducts();
isLoading = false;
}
}
#override
void dispose() {
_scrollController.dispose();
super.dispose();
}
fetchTopProducts() async {
setState(() {
isLoading = true;
});
var url = base_api + "api_frontend/top_products";
var response = await http.get(url);
print(response.body);
if (response.statusCode == 200) {
setState(() {
data.add(json.decode(response.body)['top_products']);
isLoading = false;
});
} else {
setState(() {
data = [];
isLoading = false;
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.1,
backgroundColor: Colors.indigo,
title: Text('GridControll'),
//backgroundColor: Color.fromRGBO(244, 246, 249, 1),
),
body: SingleChildScrollView(
child: Column(
children: [
Container(
height: MediaQuery.of(context).size.height * 88/100,
color: Color.fromRGBO(244, 246, 249, 1),
margin: const EdgeInsets.only(
left: 0.0, bottom: 2.0, right: 0.0, top: 0),
child: getBody2(),
),
],
),
),
);
}
Widget getBody2() {
if (isLoading || data.length == 0) {
return Center(
child: CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation<Color>(primary)));
}
return StaggeredGridView.countBuilder(
padding: const EdgeInsets.all(10.0),
controller: _scrollController,
shrinkWrap: true,
// physics: NeverScrollableScrollPhysics(),
crossAxisCount: 2,
itemCount: data.length - 1,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
//builder: (context) => ProductDetails(item: data2[index]),
builder: (context) => productDetail(data[index]),
),
);
},
child: cardItem2(data[index]));
},
staggeredTileBuilder: (int index) => StaggeredTile.fit(1),
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
);
}
}
Here is grid_content.dart:
import 'package:html_unescape/html_unescape.dart';
import 'package:flutter/material.dart';
Widget cardItem2(item) {
// var img = item['thumbnail'];
// var thumbnail = base_api+"uploads/product_thumbnails/"+img;
var productId = item['product_id'];
var thumbnail = item['thumbnail'];
var unescape = new HtmlUnescape();
var name = unescape.convert(item['name']);
var unit = item['unit'];
var discount = item['discount'];
var price = item['price'];
var discountPrice = item['discount_price'];
return discount != '0%' ? Card(
elevation: 6,
shadowColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(9.0)),
child: Stack(
fit: StackFit.loose,
alignment: Alignment.center,
children: [
Column(
children: <Widget>[
Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.only(topRight: Radius.circular(9), topLeft: Radius.circular(9)),
child: FadeInImage.assetNetwork(
placeholder: 'assets/loading_animated.gif',
image: thumbnail,
height: 110,
width: double.infinity,
fit: BoxFit.cover,
),
),
],
),
Padding(
padding: const EdgeInsets.only(left:6.0, right: 6.0),
child: Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
name,
style: TextStyle(
fontSize: 16.0,
color: Colors.black87,
fontWeight: FontWeight.w100,
),
),
Text(
unit,
style: TextStyle(
fontSize: 12.0,
color: Colors.black45,
fontWeight: FontWeight.w100,
),
),
Row(
children: [
Expanded(
flex: 2,
child: Text(
discountPrice,
style: TextStyle(
fontSize: 16.0,
color: Colors.green,
fontWeight: FontWeight.w500,
),
),
),
Expanded(
flex: 2,
child: Text(
price,
style: TextStyle(
fontSize: 12.0,
color: Colors.black38,
fontWeight: FontWeight.w500,
decoration: TextDecoration.lineThrough,
),
),
),
ButtonTheme(
padding: EdgeInsets.symmetric(vertical: 4.0, horizontal: 6.0), //adds padding inside the button
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, //limits the touch area to the button area
minWidth: 0, //wraps child's width
height: 25,
child: FlatButton(
minWidth: 5,
height: 40,
color: Color.fromRGBO(100, 186, 2, 1),
onPressed: () {
},
child: Icon(Icons.shopping_cart, color: Colors.white,),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
side: BorderSide(color: Color.fromRGBO(100, 186, 2, 1),)),
),
),
],
),
],
),
),
),
],
),
),
],
),
],
),
) : Card(
elevation: 6,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(9.0)),
child: Stack(
fit: StackFit.loose,
alignment: Alignment.center,
children: [
Column(
children: <Widget>[
Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.only(topRight: Radius.circular(9), topLeft: Radius.circular(9)),
child: FadeInImage.assetNetwork(
placeholder: 'assets/loading_animated.gif',
image: thumbnail,
height: 110,
width: double.infinity,
fit: BoxFit.cover,
),
),
],
),
Padding(
padding: const EdgeInsets.only(left:6.0, right: 6.0),
child: Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
name,
style: TextStyle(
fontSize: 16.0,
color: Colors.black87,
fontWeight: FontWeight.w100,
),
),
Text(
unit,
style: TextStyle(
fontSize: 12.0,
color: Colors.black45,
fontWeight: FontWeight.w100,
),
),
Row(
children: [
Expanded(
flex: 1,
child: Text(
price,
style: TextStyle(
fontSize: 15.0,
color: Colors.green,
fontWeight: FontWeight.w500,
),
),
),
ButtonTheme(
padding: EdgeInsets.symmetric(vertical: 4.0, horizontal: 6.0),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
minWidth: 0, //wraps child's width
height: 25,
child: FlatButton(
minWidth: 10,
//height: 40,
color: Color.fromRGBO(100, 186, 2, 1),
onPressed: () {
},
child: Icon(Icons.shopping_cart, color: Colors.white,),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
side: BorderSide(color: Color.fromRGBO(100, 186, 2, 1),)),
),
),
],
),
],
),
),
),
],
),
),
],
),
],
),
);
}
productDetail(item) {
// var img = item['thumbnail'];
// var thumbnail = base_api+"uploads/product_thumbnails/"+img;
var productId = item['product_id'];
var thumbnail = item['thumbnail'];
var unescape = new HtmlUnescape();
var name = unescape.convert(item['name']);
var discount = item['discount'];
var price = item['price'];
var disPrice= item['discount_price'];
var unit = item['unit'];
return Scaffold(
appBar: AppBar(
elevation: 0.1,
iconTheme: IconThemeData(color: Colors.white),
backgroundColor: Colors.red,
title: Center(
child: Padding(
padding: const EdgeInsets.only(right: 50),
child: Text(
'Product Details',
style: TextStyle(color: Colors.white),
),
),
),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 15, right: 25.0),
child: GestureDetector(
child: Stack(
alignment: Alignment.topCenter,
children: <Widget>[
Icon(
Icons.favorite,
),
],
),
onTap: () {},
),
)
],
),
body: SingleChildScrollView(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: FadeInImage.assetNetwork(
placeholder: 'assets/black_circle.gif',
image: thumbnail,
height: 210,
width: 360,
fit: BoxFit.cover,
),
),
),
Center(
child: Card(
color: Colors.white38,
child: Padding(
padding: const EdgeInsets.only(left: 12.0, right: 12, top: 4, bottom: 4),
child: Text(
unit,
style: TextStyle(
fontSize: 11,
color: Colors.black87,
),
),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Center(
child: discount != '0%' ? Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
disPrice,
style: TextStyle(
fontSize: 22,
color: Colors.black87,
fontWeight: FontWeight.bold),
),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
price,
style: TextStyle(
fontSize: 18,
color: Colors.black54,
decoration: TextDecoration.lineThrough,
),
),
),
],
): Text(
price,
style: TextStyle(
fontSize: 22,
color: Colors.black87,
fontWeight: FontWeight.bold),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 4.0),
child: Center(
child: Text(
name,
style: TextStyle(
fontSize: 18,
color: Colors.black54,
),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Divider(),
),
Container(
child: Center(
child: Text(
'Quantity',
style: TextStyle(color: Colors.black45, fontSize: 15),
),
),
),
Container(
child: Center(
child: Text(
'1',
style: TextStyle(
color: Colors.black,
fontSize: 22,
fontWeight: FontWeight.bold),
),
),
//child: Text(store.activeProduct.qty.toString()),
),
Padding(
padding: const EdgeInsets.only(
left: 100.0, right: 100.0, bottom: 10.0),
child: FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
side: BorderSide(color: Color.fromRGBO(41, 193, 126, 1)),
),
color: Color.fromRGBO(41, 193, 126, 1),
padding: EdgeInsets.only(top: 8, bottom: 8),
child: Center(
child: Text(
'BUY NOW',
style: TextStyle(color: Colors.white, fontSize: 16),
),
),
onPressed: () {
}),
),
Padding(
padding: const EdgeInsets.only(
left: 100.0, right: 100.0, bottom: 10.0),
child: FlatButton(
padding: EdgeInsets.only(top: 8, bottom: 8),
child: Center(
child: Text(
'ADD TO CART',
style: TextStyle(color: Color.fromRGBO(41, 193, 126, 1), fontSize: 16),
),
),
onPressed: () {
}),
),
],
),
),
),
);
}
Here is the json file:
{
"top_products": [
{
"product_id": "63",
"category_id": "59",
"name": "Ice Cream",
"price": "$9",
"discount_price": "$8.91",
"discount": "1%",
"unit": "3 kg",
"thumbnail": "http://192.168.0.105/uploads/product_thumbnails/72908baa78a2db38f678283a2e483903.jpg"
},
{
"product_id": "65",
"category_id": "47",
"name": "Malta",
"price": "$5",
"discount_price": "$4.5",
"discount": "10%",
"unit": "1 kg",
"thumbnail": "http://192.168.0.105/uploads/product_thumbnails/a63dcb5e4f883eb946585d287d25c397.jpg"
},
{},
{},
{},
...
],
"message": "Top hundred products",
"status": 200,
"validity": true
}
======== Exception caught by widgets library =======================================================
The following _TypeError was thrown building:
type 'String' is not a subtype of type 'int' of 'index'
When the exception was thrown, this was the stack:
#0 cardItem2 (package:gridview_screoll/grid_content.dart:7:23)
#1 _ScrollableGridState.getBody2.<anonymous closure> (package:gridview_screoll/scroll_grid.dart:130:20)
#2 SliverChildBuilderDelegate.build (package:flutter/src/widgets/sliver.dart:449:22)
#3 SliverVariableSizeBoxAdaptorElement._build.<anonymous closure> (package:flutter_staggered_grid_view/src/widgets/sliver.dart:144:38)
#4 _HashMap.putIfAbsent (dart:collection-patch/collection_patch.dart:140:29)
...
====================================================================================================
itemCount: data.length - 1,
Change this to this:
itemCount: data.length;
I am new to flutter, and working on a shopping cart project. i don't know how exatly i am suppose to ask this question but, here is what i wanted.
I am trying to update my UI when the cart item and prices changes, which means to display sum amount of products from ListView (Stateful widget) to main OrderPage Stateful widget. I know about setState() method, but i think i should use some callback methods here, dont know exactly.
I have explained in short in Image - see below img
What i have done: when user modify cart products, I have saved the value (price/product/count) in to constant value , i calculate the value and save in constant value, and later use that const var in Main widget (Main Ui), which does update when i close and reopen the page, but could not able to update when button pressed (product +/-buttons)
What i want to do is,
Update my total value when +/- buttons are pressed.
Here is my full code:
class cartConstant{
static int packageCount;
static List<int> list;
}
class OrderPage extends StatefulWidget {
#override
_OrderPageState createState() => _OrderPageState();
}
class _OrderPageState extends State<OrderPage> {
int data = 3;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
automaticallyImplyLeading: true,
iconTheme: IconThemeData(
color: Colors.black54, //change your color here
),
backgroundColor: Colors.white,
elevation: 1,
title: Text("Your order Summery",style: TextStyle(color: Colors.black54),),
centerTitle: true,
),
body: Container(
child:
FutureBuilder(
builder: (context, snapshot){
// var datas = snapshot.data;
return
ListView.builder(
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: data,
itemBuilder: (BuildContext context, int index){
// Cart cart = datas[index];
return CartListView();
},
padding: EdgeInsets.symmetric(horizontal: 10.0),
scrollDirection: Axis.vertical,
);
},
),
),
bottomNavigationBar: _buildTotalContainer(),
);
}
Widget _buildTotalContainer() {
return Container(
height: 220.0,
padding: EdgeInsets.only(
left: 10.0,
right: 10.0,
),
child: Column(
children: <Widget>[
SizedBox(
height: 10.0,
),
Padding(
padding: const EdgeInsets.only(top: 10),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Subtotal",
style: TextStyle(
color: Color(0xFF9BA7C6),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
Text(
cartConstant.packageCount.toString(),
style: TextStyle(
color: Color(0xFF6C6D6D),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
],
),
),
SizedBox(
height: 15,
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Discount",
style: TextStyle(
color: Color(0xFF9BA7C6),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
Text(
"0.0",
style: TextStyle(
color: Color(0xFF6C6D6D),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
],
),
SizedBox(
height: 10.0,
),
Divider(
height: 2.0,
),
SizedBox(
height: 20.0,
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Cart Total",
style: TextStyle(
color: Color(0xFF9BA7C6),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
Text(
cartConstant.packageCount.toString(),
style: TextStyle(
color: Color(0xFF6C6D6D),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
],
),
SizedBox(
height: 20.0,
),
GestureDetector(
onTap: () {
// Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => SignInPage()));
},
child: Container(
height: 50.0,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(35.0),
),
child: Center(
child: Text(
"Proceed To Checkout",
style: TextStyle(
color: Colors.white,
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
),
),
),
),
SizedBox(
height: 20.0,
),
],
),
);
}
}
class CartListView extends StatefulWidget {
#override
_CartListViewState createState() => _CartListViewState();
}
class _CartListViewState extends State<CartListView> {
int _counter = 1;
int getPrice(int i,int priceC){
cartConstant.packageCount = i*priceC;
return cartConstant.packageCount;
}
#override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 15.0),
child: Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
decoration: BoxDecoration(
border: Border.all(color: Color(0xFFD3D3D3), width: 2.0),
borderRadius: BorderRadius.circular(10.0),
),
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 10.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
InkWell(
onTap: (){
setState(() {
_counter++;
if (_counter > 20) {
_counter = 20;
}
});
},
child: Icon(Icons.add, color: Color(0xFFD3D3D3))),
Text(
"$_counter",
style: TextStyle(fontSize: 18.0, color: Colors.grey),
),
InkWell(
onTap:(){
setState(() {
_counter--;
if (_counter < 2) {
_counter = 1;
}
});
},
child: Icon(Icons.remove, color: Color(0xFFD3D3D3))),
],
),
),
),
SizedBox(
width: 20.0,
),
Container(
height: 70.0,
width: 70.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/food.jpg"),
fit: BoxFit.cover),
borderRadius: BorderRadius.circular(35.0),
boxShadow: [
BoxShadow(
color: Colors.black54,
blurRadius: 5.0,
offset: Offset(0.0, 2.0))
]),
),
SizedBox(
width: 20.0,
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Employee Package",
style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold),
),
SizedBox(height: 5.0),
SizedBox(height: 5.0),
Container(
height: 25.0,
width: 120.0,
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
Row(
children: <Widget>[
Text("Price",
style: TextStyle(
color: Color(0xFFD3D3D3),
fontWeight: FontWeight.bold)),
SizedBox(
width: 5.0,
),
InkWell(
onTap: () {},
child: Text(
getPrice(_counter, 2000).toString(),
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.red,
),
),
),
SizedBox(
width: 10.0,
),
],
),
],
),
),
],
),
Spacer(),
GestureDetector(
onTap: () {
},
child: Icon(
Icons.cancel,
color: Colors.grey,
),
),
],
),
),
);
}
}
you can also check from my cart screen shot below:
You can copy paste run full code below
You can use callback refresh() and pass callback to CartListView
code snippet
class _OrderPageState extends State<OrderPage> {
int data = 3;
void refresh() {
setState(() {});
}
...
itemBuilder: (BuildContext context, int index) {
// Cart cart = datas[index];
return CartListView(refresh);
},
...
class CartListView extends StatefulWidget {
VoidCallback callback;
CartListView(this.callback);
...
InkWell(
onTap: () {
setState(() {
_counter++;
if (_counter > 20) {
_counter = 20;
}
});
widget.callback();
},
working demo
full code
import 'package:flutter/material.dart';
class cartConstant {
static int packageCount;
static List<int> list;
}
class OrderPage extends StatefulWidget {
#override
_OrderPageState createState() => _OrderPageState();
}
class _OrderPageState extends State<OrderPage> {
int data = 3;
void refresh() {
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
automaticallyImplyLeading: true,
iconTheme: IconThemeData(
color: Colors.black54, //change your color here
),
backgroundColor: Colors.white,
elevation: 1,
title: Text(
"Your order Summery",
style: TextStyle(color: Colors.black54),
),
centerTitle: true,
),
body: Container(
child: FutureBuilder(
builder: (context, snapshot) {
// var datas = snapshot.data;
return ListView.builder(
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: data,
itemBuilder: (BuildContext context, int index) {
// Cart cart = datas[index];
return CartListView(refresh);
},
padding: EdgeInsets.symmetric(horizontal: 10.0),
scrollDirection: Axis.vertical,
);
},
),
),
bottomNavigationBar: _buildTotalContainer(),
);
}
Widget _buildTotalContainer() {
return Container(
height: 220.0,
padding: EdgeInsets.only(
left: 10.0,
right: 10.0,
),
child: Column(
children: <Widget>[
SizedBox(
height: 10.0,
),
Padding(
padding: const EdgeInsets.only(top: 10),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Subtotal",
style: TextStyle(
color: Color(0xFF9BA7C6),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
Text(
cartConstant.packageCount.toString(),
style: TextStyle(
color: Color(0xFF6C6D6D),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
],
),
),
SizedBox(
height: 15,
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Discount",
style: TextStyle(
color: Color(0xFF9BA7C6),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
Text(
"0.0",
style: TextStyle(
color: Color(0xFF6C6D6D),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
],
),
SizedBox(
height: 10.0,
),
Divider(
height: 2.0,
),
SizedBox(
height: 20.0,
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Cart Total",
style: TextStyle(
color: Color(0xFF9BA7C6),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
Text(
"8000",
style: TextStyle(
color: Color(0xFF6C6D6D),
fontSize: 16.0,
fontWeight: FontWeight.bold),
),
],
),
SizedBox(
height: 20.0,
),
GestureDetector(
onTap: () {
// Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => SignInPage()));
},
child: Container(
height: 50.0,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(35.0),
),
child: Center(
child: Text(
"Proceed To Checkout",
style: TextStyle(
color: Colors.white,
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
),
),
),
),
SizedBox(
height: 20.0,
),
],
),
);
}
}
class CartListView extends StatefulWidget {
VoidCallback callback;
CartListView(this.callback);
#override
_CartListViewState createState() => _CartListViewState();
}
class _CartListViewState extends State<CartListView> {
int _counter = 1;
int getPrice(int i, int priceC) {
cartConstant.packageCount = i * priceC;
return cartConstant.packageCount;
}
#override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 15.0),
child: Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
decoration: BoxDecoration(
border: Border.all(color: Color(0xFFD3D3D3), width: 2.0),
borderRadius: BorderRadius.circular(10.0),
),
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 10.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
InkWell(
onTap: () {
setState(() {
_counter++;
if (_counter > 20) {
_counter = 20;
}
});
widget.callback();
},
child: Icon(Icons.add, color: Color(0xFFD3D3D3))),
Text(
"$_counter",
style: TextStyle(fontSize: 18.0, color: Colors.grey),
),
InkWell(
onTap: () {
setState(() {
_counter--;
if (_counter < 2) {
_counter = 1;
}
});
widget.callback();
},
child: Icon(Icons.remove, color: Color(0xFFD3D3D3))),
],
),
),
),
SizedBox(
width: 20.0,
),
Container(
height: 70.0,
width: 70.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/food.jpg"),
fit: BoxFit.cover),
borderRadius: BorderRadius.circular(35.0),
boxShadow: [
BoxShadow(
color: Colors.black54,
blurRadius: 5.0,
offset: Offset(0.0, 2.0))
]),
),
SizedBox(
width: 20.0,
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Employee Package",
style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold),
),
SizedBox(height: 5.0),
SizedBox(height: 5.0),
Container(
height: 25.0,
width: 120.0,
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
Row(
children: <Widget>[
Text("Price",
style: TextStyle(
color: Color(0xFFD3D3D3),
fontWeight: FontWeight.bold)),
SizedBox(
width: 5.0,
),
InkWell(
onTap: () {},
child: Text(
getPrice(_counter, 2000).toString(),
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.red,
),
),
),
SizedBox(
width: 10.0,
),
],
),
],
),
),
],
),
Spacer(),
GestureDetector(
onTap: () {},
child: Icon(
Icons.cancel,
color: Colors.grey,
),
),
],
),
),
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: OrderPage(),
);
}
}
When the button is tapped, you just need to update the Subtotal amount and cart total.
Step 1 : Replace the harcoded value by a variable. So, something like :
Row(
children: <Widget>[
Text(
"Subtotal",
style: ...
),
Text(
"$subTotal",
style: ....
),
],
),
Step 2 : Now, add a code to calcualte subTotal and cartTotal. You already have code which increments and decrements the variable _counter. You just need to tweak that part like :
setState( (){
_counter++;
// So, the quantity is increased. Just get the price of current item and add in the sub total.
subTotal += priceC;
cartTotal = subTotal - discount;
} );
i am tried to run my project and this error still appearing
Failed assertion: boolean expression must not be null
i was run it more than 30 times and it was worked but now it doesn't and i don't know the reason for this problem i am not change any thing in my code before the error , and i tried some solutions and it doesn't work also , so what should i do now !
this is my screen which has the problem
class _TourguideDetailesState extends State<TourguideDetailes>
with TickerProviderStateMixin {
AppProvider appProvider;
ScrollController scrollController = ScrollController(initialScrollOffset: 0);
AnimationController animationController;
#override
void initState() {
animationController = AnimationController(
duration: Duration(milliseconds: 2000), vsync: this);
animationController.forward();
super.initState();
}
#override
void dispose() {
animationController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
appProvider = Provider.of<AppProvider>(context);
return Scaffold(
backgroundColor: AppTheme.getTheme().backgroundColor,
body: Stack(
children: <Widget>[
NestedScrollView(
controller: scrollController,
physics: NeverScrollableScrollPhysics(),
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverPersistentHeader(
pinned: true,
floating: true,
delegate: ContestTabHeader(
(MediaQuery.of(context).size.height),
appProvider.selectedTourguide,
() {
scrollController.animateTo(MediaQuery.of(context).size.height - MediaQuery.of(context).size.height / 5,
duration: Duration(milliseconds: 500), curve: Curves.fastOutSlowIn);
},
getGuideDetails(),
),
),
];
},
body: ListView(
padding: EdgeInsets.only(top: 24),
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 24, right: 24),
child: getGuideDetails(isInList: true),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Divider(
height: 1,
),
),
Padding(
padding: const EdgeInsets.only(left: 24, right: 24),
child: Row(
children: <Widget>[
Expanded(
child: Text(
"Biography",
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 18,
letterSpacing: 0.5,
),
),
),
],
),
),
Padding(
padding:
EdgeInsets.only(left: 24, right: 24, top: 4, bottom: 8),
child: Text(
appProvider.selectedTourguide.bio == null
? ""
: appProvider.selectedTourguide.bio,
style: TextStyle(
fontSize: 14,
color: AppTheme.getTheme().disabledColor,
),
)),
Padding(
padding: const EdgeInsets.only(left: 24, right: 24),
child: Row(
children: <Widget>[
Expanded(
child: Text(
"Native Language",
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 18,
letterSpacing: 0.5,
),
),
),
],
),
),
Padding(
padding:
EdgeInsets.only(left: 24, right: 24, top: 4, bottom: 8),
child: Text(
appProvider.selectedTourguide.nativeLanguage == null ? "" : appProvider.selectedTourguide.nativeLanguage,
style: TextStyle(
fontSize: 14,
color: AppTheme.getTheme().disabledColor,
),
)),
Padding(
padding:
EdgeInsets.only(left: 24, right: 24, top: 4, bottom: 8),
),
SizedBox(
height: 16,
),
Padding(
padding: const EdgeInsets.only(
left: 16, right: 16, bottom: 16, top: 16),
child: Container(
height: 48,
decoration: BoxDecoration(
color: AppTheme.getTheme().primaryColor,
borderRadius: BorderRadius.all(Radius.circular(24.0)),
boxShadow: <BoxShadow>[
BoxShadow(
color: AppTheme.getTheme().dividerColor,
blurRadius: 8,
offset: Offset(4, 4),
),
],
),
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.all(Radius.circular(24.0)),
highlightColor: Colors.transparent,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BookingScreen(
index: appProvider.selectedTourguide,
),
fullscreenDialog: true,
));
},
child: Center(
child: Text(
"Book now",
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
color: Colors.white),
),
),
),
),
),
),
SizedBox(
height: MediaQuery.of(context).padding.bottom,
),
],
),
),
Padding(
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
child: Container(
height: AppBar().preferredSize.height,
child: Row(
children: <Widget>[
SizedBox(
height: AppBar().preferredSize.height,
child: Padding(
padding: EdgeInsets.only(top: 8, left: 8),
child: Container(
width: AppBar().preferredSize.height - 8,
height: AppBar().preferredSize.height - 8,
decoration: BoxDecoration(color: AppTheme.getTheme().disabledColor.withOpacity(0.4), shape: BoxShape.circle),
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.all(
Radius.circular(32.0),
),
onTap: () {
if (scrollController.offset != 0.0) {
scrollController.animateTo(0.0, duration: Duration(milliseconds: 500), curve: Curves.easeInOutQuad);
} else {
Navigator.pop(context);
}
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(Icons.arrow_back, color: AppTheme.getTheme().backgroundColor),
),
),
),
),
),
),
Expanded(
child: SizedBox(),
),
],
),
),
)
],
),
);
}
Widget getGuideDetails({bool isInList = false}) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
appProvider.selectedTourguide.name,
textAlign: TextAlign.left,
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 22,
color: isInList == null
? AppTheme.getTheme().textTheme.body1.color
: Colors.white,
),
),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(
appProvider.selectedTourguide.address,
style: TextStyle(
fontSize: 14,
color: isInList == null
? AppTheme.getTheme().disabledColor.withOpacity(0.5)
: Colors.white,
),
),
SizedBox(
width: 4,
),
Icon(
FontAwesomeIcons.mapMarkerAlt,
size: 12,
color: AppTheme.getTheme().primaryColor,
),
],
),
isInList == null
? SizedBox()
: Padding(
padding: const EdgeInsets.only(top: 4),
child: Row(
children: <Widget>[
Text(
" ${appProvider.selectedTourguide.review} Reviews",
style: TextStyle(
fontSize: 14,
color: isInList
? AppTheme.getTheme().disabledColor
: Colors.white,
),
),
],
),
),
],
),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Row(
children: <Widget>[
Text(
appProvider.selectedTourguide.tariffValue= null ? '' : appProvider.selectedTourguide.tariffValue,
textAlign: TextAlign.left,
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 22,
color: isInList == null
? AppTheme.getTheme().textTheme.body1.color
: Colors.white,
),
),
Text(
appProvider.selectedTourguide.currency= null ? '' : appProvider.selectedTourguide.currency,
textAlign: TextAlign.left,
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 22,
color: isInList == null
? AppTheme.getTheme().textTheme.body1.color
: Colors.white,
),
),
],
),
Text(
"/per hour",
style: TextStyle(
fontSize: 14,
color: isInList == null
? AppTheme.getTheme().disabledColor.withOpacity(0.5)
: Colors.white,
),
),
],
),
],
);
}
}
class ContestTabHeader extends SliverPersistentHeaderDelegate {
final Widget ui;
final VoidCallback callback;
final TourGuide tourguideData;
final double heightValue;
ContestTabHeader(
this.heightValue,
this.tourguideData,
this.callback,
this.ui,
);
#override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
var minValue = (shrinkOffset < heightValue - heightValue / 5? shrinkOffset: heightValue / 5);
return Container(
height: heightValue - minValue,
decoration: BoxDecoration(
color: AppTheme.getTheme().primaryColor,
boxShadow: <BoxShadow>[
BoxShadow(
color: AppTheme.getTheme().dividerColor,
blurRadius: 8,
offset: Offset(4, 4),
),
],
),
child: Stack(
alignment: Alignment.bottomCenter,
children: <Widget>[
Positioned(
bottom: 0,
left: 0,
right: 0,
top: 0,
child: Container(
width: MediaQuery.of(context).size.width,
child: Image.network(
tourguideData.photo == null
? 'https://i.ytimg.com/vi/TWaReNkjTLk/maxresdefault.jpg'
: tourguideData.photo,
fit: BoxFit.cover,
),
),
),
Positioned(
bottom: MediaQuery.of(context).padding.bottom + 16,
left: 0,
right: 0,
child: Opacity(
opacity: getOpValue(minValue, heightValue / 5),
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 24, right: 24),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(24)),
child: new BackdropFilter(
filter:
new ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
child: Container(
color: Colors.black12,
padding: const EdgeInsets.all(4.0),
child: Column(
children: <Widget>[
SizedBox(
height: 4,
),
Padding(
padding: const EdgeInsets.only(
left: 16, right: 16, top: 8),
child: ui,
),
Padding(
padding: const EdgeInsets.only(
left: 16, right: 16, bottom: 16, top: 16),
child: Container(
height: 48,
decoration: BoxDecoration(
color: AppTheme.getTheme().primaryColor,
borderRadius:
BorderRadius.all(Radius.circular(24.0)),
boxShadow: <BoxShadow>[
BoxShadow(
color: AppTheme.getTheme().dividerColor,
blurRadius: 8,
offset: Offset(4, 4),
),
],
),
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.all(
Radius.circular(24.0)),
highlightColor: Colors.transparent,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
BookingScreen(),
fullscreenDialog: true,
),
);
},
child: Center(
child: Text(
"Book now",
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 16,
color: Colors.white),
),
),
),
),
),
),
],
),
),
),
),
),
SizedBox(
height: 16,
),
Center(
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(24)),
child: new BackdropFilter(
filter:
new ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
child: Container(
color: Colors.black12,
child: Material(
color: Colors.transparent,
child: InkWell(
highlightColor: Colors.transparent,
splashColor: AppTheme.getTheme()
.primaryColor
.withOpacity(0.2),
borderRadius:
BorderRadius.all(Radius.circular(38)),
onTap: () {
try {
callback();
} catch (e) {}
},
child: Padding(
padding: const EdgeInsets.only(
left: 16, right: 16, top: 4, bottom: 4),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
'More Details',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
),
),
Padding(
padding: const EdgeInsets.only(top: 2),
child: Icon(
Icons.keyboard_arrow_down,
color: Colors.white,
size: 24,
),
)
],
),
),
),
),
),
),
),
),
],
),
),
)
],
),
);
}
double getOpValue(double minValue, double maxValue) {
var data = (1.0 - (minValue / maxValue));
if (data < 0.0) {
return 0.0;
} else if (data >= 0 && data <= 1) {
return data;
} else {
return 1.0;
}
}
#override
double get maxExtent => heightValue;
#override
double get minExtent => heightValue / 5;
#override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
return true;
}
}
Look at the Text Widget, hope it helps. Too lazy to read the whole thing carefully. By the way, you can replace a == null ? 'whatever' : a with a ?? 'whatever'. ?? is equal with if null
Row(
children: <Widget>[
Text(
/// The problem is probably here, missing '='
appProvider.selectedTourguide.tariffValue= null ? '' : appProvider.selectedTourguide.tariffValue,
textAlign: TextAlign.left,
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 22,
color: isInList == null
? AppTheme.getTheme().textTheme.body1.color
: Colors.white,
),
),
Text(
/// The problem is probably here, missing '='
appProvider.selectedTourguide.currency= null ? '' : appProvider.selectedTourguide.currency,
textAlign: TextAlign.left,
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 22,
color: isInList == null
? AppTheme.getTheme().textTheme.body1.color
: Colors.white,
),
),
],
),