when i play audio that time my song is loading that time showing error in IOS and when back from that page then i got this error "_dependents.isempty' is not true".
For android its working fine.
this is my card's page from here I going to details page where I am playing my song
import 'package:audioplayers/audioplayers.dart';
import 'package:cwc/constants/constants.dart';
import 'package:cwc/ui/video/video_player.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import '../podcast_details_page.dart';
class PodcastCompoentPurple extends StatefulWidget {
final cwcAudioListData;
const PodcastCompoentPurple({Key? key, this.cwcAudioListData,}) : super(key: key);
#override
State<PodcastCompoentPurple> createState() => _PodcastCompoentPurpleState();
}
class _PodcastCompoentPurpleState extends State<PodcastCompoentPurple> {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(18, 0, 18, 0),
child: GestureDetector(
onTap: () async{
isBtnHide=false;
await Navigator.push(context, MaterialPageRoute(builder: (context){
return PodcastDetailsPage(cwcAudioListData:widget.cwcAudioListData);
}));
print("s3 $playing");
if (playing==true) {
//pause song
var res = await audioPlayer.pause();
if (res == 1) {
setState(() {
playing = false;
print("s2 $playing");
});
}
}
print("s1 $playing");
},
child: Container(
height: 234,
// width: 260,
width: double.infinity,
decoration: BoxDecoration(
color: widget.cwcAudioListData['packages'][0]["name"]
.toString()
.toLowerCase() ==
"starter"
? Color(0xff69C583).withOpacity(.25)
:widget.cwcAudioListData['packages'][0]["name"]
.toString()
.toLowerCase() ==
"explorer"
? Color(0xFFC691D3).withOpacity(0.25)
: Color(0xFFF6931E).withOpacity(0.25),
// color: Colors.red,
borderRadius: const BorderRadius.all(
Radius.circular(10),
),
),
child: Padding(
padding: const EdgeInsets.fromLTRB(10, 10, 10, 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: 145,
// width: 300,
width: double.infinity,
decoration: BoxDecoration(
color: widget.cwcAudioListData['packages'][0]["name"]
.toString()
.toLowerCase() ==
"starter"
? Color(0xff69C583).withOpacity(.25)
: widget.cwcAudioListData['packages'][0]["name"]
.toString()
.toLowerCase() ==
"explorer"
? Color(0xFFC691D3).withOpacity(0.25)
: Color(0xFFF6931E).withOpacity(0.25),
// color: Colors.red,
borderRadius: const BorderRadius.all(
Radius.circular(10),
),
image: DecorationImage(
image: NetworkImage('${widget.cwcAudioListData['coverImage']}'),
fit: BoxFit.cover,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: CircleAvatar(
backgroundColor: Color(0xffF1F2F6).withOpacity(0.5),
radius: 23,
child: Icon(
Icons.headphones,
size: 24,
color: Color(0xffF1F2F6).withOpacity(1),
),
),
),
],
),
),
SizedBox(
height: 10,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'${widget.cwcAudioListData['title']}',
style: GoogleFonts.poppins(
fontWeight: FontWeight.w600,
fontSize: 14,
color: Color(0xFF444444)),textAlign: TextAlign.center,
),
Text(
'${widget.cwcAudioListData['description']}',
maxLines: 2,
style: GoogleFonts.poppins(
fontSize: 12, color: Color(0xFF444444)),
),
],)
],
),
),
),
),
);
}
}
This is my details page.
import 'package:audioplayers/audioplayers.dart';
import 'package:cwc/constants/constants.dart';
import 'package:cwc/constants/top_card.dart';
import 'package:cwc/ui/video/video_screen.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart';
import 'package:flutter/material.dart';
class PodcastDetailsPage extends StatefulWidget {
final cwcAudioListData;
const PodcastDetailsPage({Key? key, this.cwcAudioListData}) : super(key: key);
#override
_PodcastDetailsPageState createState() => _PodcastDetailsPageState();
}
class _PodcastDetailsPageState extends State<PodcastDetailsPage> {
Duration duration = new Duration();
Duration position = Duration();
var url = '';
#override
void initState() {
url=widget.cwcAudioListData['upload'].toString();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xffffffff).withOpacity(1),
body: SafeArea(
child: Stack(
children: [
Container(
width: double.infinity,
height: 350,
decoration: BoxDecoration(
color: Color(0xffF6931E),
image: DecorationImage(
image: NetworkImage('${widget.cwcAudioListData["coverImage"]}'),
fit: BoxFit.cover,
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(18, 12, 0, 0),
child: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: const CircleAvatar(
radius: 23,
backgroundColor: Colors.white,
child: Icon(Icons.arrow_back_ios_new,
color: Colors.black),
),
),
),
const SizedBox(
height: 138,
),
Padding(
padding: EdgeInsets.fromLTRB(18, 0, 18, 15),
child: Container(
height: 80,
),
),
],
),
),
Padding(
padding: const EdgeInsets.only(top: 270.0),
child: Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topRight: Radius.circular(24.0),
topLeft: Radius.circular(24.0),
),
),
// height: 50,
width: double.infinity,
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(19, 33, 0, 0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'${widget.cwcAudioListData["title"]}',
style: GoogleFonts.poppins(
fontSize: 18,
color: Color(0xff444444),
fontWeight: FontWeight.w600,
),
),
Text(
"${formateDat(DateTime.parse(widget.cwcAudioListData['uploadDate']))} at ${DateFormat("hh:mm a").format(DateFormat("yyyy-MM-ddTHH:mm:ssZ").parseUTC("${widget.cwcAudioListData['uploadDate']}").toLocal())}",
// 'Sept, 10th 2021',
style: GoogleFonts.poppins(
fontSize: 12,
color: Color(0xff8F9698),
fontWeight: FontWeight.w600,
),
),
Text(
'FREE to watch',
style: GoogleFonts.poppins(
fontSize: 14,
color: Color(0xff69C583),
fontWeight: FontWeight.w500,
),
),
],
),
)
],
),
Padding(
padding: const EdgeInsets.fromLTRB(20, 20, 0, 0),
child: Text(
'Video Description',
style: GoogleFonts.poppins(
fontSize: 18,
color: Color(0xFF69C583),
fontWeight: FontWeight.w500),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(20, 8, 17, 22),
child: Text(
'${widget.cwcAudioListData["description"]}',
style: GoogleFonts.poppins(
fontSize: 13,
fontWeight: FontWeight.normal,
color: Color(0xff444444),
),
),
),
],
),
),
),
)
],
),
),
bottomNavigationBar: isBtnHide == false
? Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 10),
child: Row(
children: [
SizedBox(
width: 30,
),
Expanded(
child: ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Color(0xFF158998)),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: BorderSide(
color: Colors.teal, width: 0.0)))),
onPressed: () async {
setState(() {
isBtnHide = true;
});
getAudio();
},
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Text(
'Listen Now',
style: GoogleFonts.poppins(fontSize: 14),
),
),
),
),
const SizedBox(
width: 30,
),
],
),
),
)
: Container(
color: Colors.white,
height: 80,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 29.0),
child:
duration.toString().split(".")[0].toString() == "0:00:00" ? Padding(
padding: const EdgeInsets.all(8.0),
child: CircularProgressIndicator(color: selectBlueColor,),
): InkWell(
onTap: () {
getAudio();
},
child: Icon(
playing == false ||
position.inSeconds.toDouble() ==
duration.inSeconds.toDouble()
? Icons.play_circle_outline
: Icons.pause_circle_outline,
size: 40,
color: selectBlueColor,
),
),
),
Column(
children: [
slider(),
Row(
children: [
Text(
"${position.toString().split(".")[0]}",
style: TextStyle(fontWeight: FontWeight.w700),
),
SizedBox(
width: MediaQuery.of(context).size.width / 2.55,
),
Text(
"${duration.toString().split(".")[0]}",
style: TextStyle(fontWeight: FontWeight.w300),
),
],
)
],
)
],
),
),
);
}
Widget slider() {
return Container(
width: MediaQuery.of(context).size.width / 1.3,
child: Slider.adaptive(
activeColor: selectBlueColor,
inactiveColor: Colors.grey[350],
value: position.inSeconds.toDouble(),
min: 0.0,
max: duration.inSeconds.toDouble(),
onChanged: (double value) {
print(duration.inSeconds.toDouble());
setState(() {
audioPlayer.seek(Duration(seconds: value.toInt()));
});
}));
}
Future<void> getAudio() async {
// playing is false by default
print(playing);
if (playing) {
//pause song
var res = await audioPlayer.pause();
if (res == 1) {
setState(() {
playing = false;
});
}
} else {
//play song
var res = await audioPlayer.play(url, isLocal: true);
if (res == 1) {
setState(() {
print(res);
playing = true;
});
}
}
audioPlayer.onDurationChanged.listen((Duration d) {
// print('Max duration: $d');
if (mounted) {
setState(() => duration = d);
}
});
audioPlayer.onAudioPositionChanged.listen((Duration dd) {
if (mounted) {
setState(() {
position = dd;
});
}
});
}
}
formateDat(DateTime date) {
final DateFormat formatter = DateFormat.MMM();
String formatted = formatter.format(date);
formatted = "${formatted} " + "${date.day}";
var week = DateFormat('EEEE').format(date);
var we = week[0] + week[1] + week[2];
return "$we, " + formatted;
}
This is my error
this is my video recording.
Related
i have 4 List and i want to change them by tapping on gesturedetector on tap event, but i receive an error. I tried call setState , but as i understood only stateful widget can do it. This lists already receive i just want to rebuild widget, i tried use it from state, but it also won't work.
error
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:vltest/Models/_request.dart';
import 'package:vltest/settings.dart';
import 'package:http/http.dart' as http;
import 'Models/_workers.dart';
import 'database.dart';
List<Requests> ActiveRequests = List.empty();
List<Requests> ClosedRequests = List.empty();
List<Requests> ActiveRequestsTO = List.empty();
List<Requests> ClosedRequestsTO = List.empty();
class RequestsPage extends StatefulWidget {
const RequestsPage();
#override
_RequestsPageState createState() => _RequestsPageState();
}
class _RequestsPageState extends State<RequestsPage> {
ScrollController controller = ScrollController();
bool closeTopContainer = false;
double topContainer = 0;
List<Widget> itemsData = [];
void getPostsData(List<Requests> list) {
List<Requests> responseList = list;
List<Widget> listItems = [];
responseList.forEach((post) {
listItems.add(Container(
height: 150,
margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20.0)),
color: Colors.white,
boxShadow: [
BoxShadow(color: Colors.black.withAlpha(100), blurRadius: 10.0),
]),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
post.shopAddress,
style: const TextStyle(
fontSize: 15, fontWeight: FontWeight.bold),
),
SizedBox(
height: 10,
),
Text(
post.problemPart,
style: const TextStyle(
fontSize: 12,
color: Colors.red,
fontWeight: FontWeight.bold),
),
SizedBox(
height: 10,
),
Text(
post.serialNumber,
style: const TextStyle(
fontSize: 15,
color: Colors.black,
fontWeight: FontWeight.bold),
)
],
),
//requestPhoto(post)
],
),
)));
});
setState(() {
itemsData = listItems;
});
}
void updatePostsData(List<Requests> list) {
List<Requests> responseList = list;
List<Widget> listItems = [];
responseList.forEach((post) {
GenerateRequestCards(listItems, post);
});
}
void GenerateRequestCards(List<Widget> listItems, Requests post) {
listItems.add(Container(
height: 150,
margin: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20.0)),
color: Colors.white,
boxShadow: [
BoxShadow(color: Colors.black.withAlpha(100), blurRadius: 10.0),
]),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
post.shopAddress,
style: const TextStyle(
fontSize: 15, fontWeight: FontWeight.bold),
),
SizedBox(
height: 10,
),
Text(
post.problemPart,
style: const TextStyle(
fontSize: 12,
color: Colors.red,
fontWeight: FontWeight.bold),
),
SizedBox(
height: 10,
),
Text(
post.serialNumber,
style: const TextStyle(
fontSize: 15,
color: Colors.black,
fontWeight: FontWeight.bold),
)
],
),
//requestPhoto(post)
],
),
)));
setState(() {
itemsData = listItems;
});
}
Image requestPhoto(Requests post) {
if (post.imageUrl == "") {
return Image.network(
post.imageUrl,
height: double.infinity,
);
} else {
return Image.network(
"https://i.ibb.co/TctYZfx/Logo-Main-3-1.jpg",
height: double.infinity,
);
}
}
#override
void initState() {
super.initState();
WidgetsBinding.instance
.addPostFrameCallback((_) => loadUserInfo().then((value) {
setState(() {});
}));
controller.addListener(() {
double value = controller.offset / 119;
setState(() {
topContainer = value;
closeTopContainer = controller.offset > 50;
});
});
}
#override
Widget build(BuildContext context) {
final Size size = MediaQuery.of(context).size;
final double categoryHeight = size.height * 0.30;
return SafeArea(
child: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.white,
leading: Icon(
Icons.arrow_back,
color: Colors.black,
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.search, color: Colors.black),
onPressed: () {},
),
IconButton(
icon: Icon(Icons.person, color: Colors.black),
onPressed: () {},
)
],
),
body: Container(
height: size.height,
child: Column(
children: <Widget>[
const SizedBox(
height: 10,
),
AnimatedOpacity(
duration: const Duration(milliseconds: 200),
opacity: closeTopContainer ? 0 : 1,
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
width: size.width,
alignment: Alignment.topCenter,
height: closeTopContainer ? 0 : categoryHeight,
child: CategoriesScroller(
ActiveRequests: ActiveRequests,
ClosedRequests: ClosedRequests,
ActiveRequestsTO: ActiveRequestsTO,
ClosedRequestsTO: ClosedRequestsTO),
),
),
Expanded(
child: ListView.builder(
controller: controller,
itemCount: itemsData.length,
physics: BouncingScrollPhysics(),
itemBuilder: (context, index) {
double scale = 1.0;
if (topContainer > 0.5) {
scale = index + 0.5 - topContainer;
if (scale < 0) {
scale = 0;
} else if (scale > 1) {
scale = 1;
}
}
return Opacity(
opacity: scale,
child: Transform(
transform: Matrix4.identity()..scale(scale, scale),
alignment: Alignment.bottomCenter,
child: Align(
heightFactor: 0.7,
alignment: Alignment.topCenter,
child: itemsData[index]),
),
);
})),
],
),
),
),
);
}
Future<void> loadUserInfo() async {
Workers workers = await DBProvider.db.getWorkerInfo();
ActiveRequests = await getRequestsInfo(workers, "repair", "active");
ClosedRequests = await getRequestsInfo(workers, "repair", "closed");
ActiveRequestsTO = await getRequestsInfo(workers, "maintenance", "active");
ClosedRequestsTO = await getRequestsInfo(workers, "maintenance", "closed");
getPostsData(ActiveRequests);
setState(() {});
}
Future<void> updateLoadersData() async {
Workers workers = await DBProvider.db.getWorkerInfo();
ActiveRequests = await getRequestsInfo(workers, "repair", "active");
ClosedRequests = await getRequestsInfo(workers, "repair", "closed");
ActiveRequestsTO = await getRequestsInfo(workers, "maintenance", "active");
ClosedRequestsTO = await getRequestsInfo(workers, "maintenance", "closed");
setState(() {});
}
Future<List<Requests>> getRequestsInfo(
Workers workers, String type, String status) async {
Map data = {
'login': workers.login,
'type': type,
'status': status,
};
//encode Map to JSON
var body = json.encode(data);
final response = await http.post(
Uri.parse(GlobalSettings.serverHTTP + 'api/requests/list'),
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer ${workers.token}"
},
body: body);
if (response.statusCode == 200) {
Iterable l = json.decode(response.body);
List<Requests> loaders =
List<Requests>.from(l.map((model) => Requests.fromJson(model)));
return loaders;
} else {
throw Exception('Failed to load album');
}
}
List<T> map<T>(List list, Function handler) {
List<T> result = [];
for (var i = 0; i < list.length; i++) {
result.add(handler(i, list[i]));
}
return result;
}
}
class CategoriesScroller extends StatelessWidget {
const CategoriesScroller({
Key? key,
required this.ActiveRequests,
required this.ClosedRequests,
required this.ActiveRequestsTO,
required this.ClosedRequestsTO,
}) : super(key: key);
final List<Requests> ActiveRequests;
final List<Requests> ClosedRequests;
final List<Requests> ActiveRequestsTO;
final List<Requests> ClosedRequestsTO;
#override
Widget build(BuildContext context) {
final double categoryHeight =
MediaQuery.of(context).size.height * 0.30 - 50;
return SingleChildScrollView(
physics: BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
child: Container(
margin: const EdgeInsets.symmetric(vertical: 20, horizontal: 20),
child: FittedBox(
fit: BoxFit.fill,
alignment: Alignment.topCenter,
child: Row(
children: <Widget>[
Container(
width: 150,
margin: EdgeInsets.only(right: 20),
height: categoryHeight,
decoration: BoxDecoration(
color: Colors.orange.shade400,
borderRadius: BorderRadius.all(Radius.circular(20.0))),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: GestureDetector(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Active",
style: TextStyle(
fontSize: 18,
color: Colors.white,
fontWeight: FontWeight.bold),
),
SizedBox(
height: 10,
),
Text(
"Repair",
style: TextStyle(
fontSize: 15,
color: Colors.white,
fontWeight: FontWeight.bold),
),
SizedBox(
height: 10,
),
Text(
ActiveRequests.length.toString(),
style: TextStyle(fontSize: 16, color: Colors.white),
),
],
),
onTap: () {
List<Widget> list = [];
ActiveRequests.forEach((element) {
_RequestsPageState()
.GenerateRequestCards(list, element);
});
},
),
),
),
Container(
width: 150,
margin: EdgeInsets.only(right: 20),
height: categoryHeight,
decoration: BoxDecoration(
color: Colors.orange.shade400,
borderRadius: BorderRadius.all(Radius.circular(20.0))),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: GestureDetector(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Closed",
style: TextStyle(
fontSize: 18,
color: Colors.white,
fontWeight: FontWeight.bold),
),
SizedBox(
height: 10,
),
Text(
"Repair",
style: TextStyle(
fontSize: 15,
color: Colors.white,
fontWeight: FontWeight.bold),
),
SizedBox(
height: 10,
),
Text(
ClosedRequests.length.toString(),
style: TextStyle(fontSize: 16, color: Colors.white),
),
],
),
onTap: () {
List<Widget> list = [];
ClosedRequests.forEach((element) {
_RequestsPageState()
.GenerateRequestCards(list, element);
});
},
),
),
),
Container(
width: 150,
margin: EdgeInsets.only(right: 20),
height: categoryHeight,
decoration: BoxDecoration(
color: Colors.orange.shade400,
borderRadius: BorderRadius.all(Radius.circular(20.0))),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: GestureDetector(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Active",
style: TextStyle(
fontSize: 18,
color: Colors.white,
fontWeight: FontWeight.bold),
),
SizedBox(
height: 10,
),
Text(
"Maintenance",
style: TextStyle(
fontSize: 15,
color: Colors.white,
fontWeight: FontWeight.bold),
),
SizedBox(
height: 10,
),
Text(
ActiveRequestsTO.length.toString(),
style: TextStyle(fontSize: 16, color: Colors.white),
),
],
),
onTap: () {
List<Widget> list = [];
ActiveRequestsTO.forEach((element) {
_RequestsPageState()
.GenerateRequestCards(list, element);
});
},
),
),
),
Container(
width: 150,
margin: EdgeInsets.only(right: 20),
height: categoryHeight,
decoration: BoxDecoration(
color: Colors.orange.shade400,
borderRadius: BorderRadius.all(Radius.circular(20.0))),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: GestureDetector(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Closed",
style: TextStyle(
fontSize: 18,
color: Colors.white,
fontWeight: FontWeight.bold),
),
SizedBox(
height: 10,
),
Text(
"Maintenance",
style: TextStyle(
fontSize: 15,
color: Colors.white,
fontWeight: FontWeight.bold),
),
SizedBox(
height: 10,
),
Text(
ClosedRequestsTO.length.toString(),
style: TextStyle(fontSize: 16, color: Colors.white),
),
],
),
onTap: () {
List<Widget> list = [];
ClosedRequestsTO.forEach((element) {
_RequestsPageState()
.GenerateRequestCards(list, element);
});
},
),
),
),
],
),
),
),
);
}
}
Give me an advice please...
Call setState after checking if it is mouted or not, like
if (mounted) {
setState(() {});
}
Sorry for long delay, honestly, i forgot about conversation, i solve problem by rewrite code , in statefull widget
As you can see in the image, the problem is that when I mark an icon as a favorite, the others also do so, and the truth is that I don't know how to make each marker independent. I am handling the states with provider. here the model.
class HeartIconState with ChangeNotifier {
Icon _hearticon = const Icon(
Icons.favorite_border,
);
Icon get hearticon => _hearticon;
void changeHeart() {
if (_hearticon.icon == Icons.favorite_border) {
_hearticon = const Icon(
Icons.favorite,
);
} else {
_hearticon = const Icon(
Icons.favorite_border,
);
}
notifyListeners();
}
set hearticon(Icon value) {
_hearticon = value;
notifyListeners();
}
}
here the way he calls them.
Align(
alignment: Alignment.bottomRight,
child: IconButton(
icon: Heart.hearticon,
onPressed: Heart.changeHeart,
color: Colors.red,
),
),
I will also put the whole card in case someone is suddenly interested.
Card(
elevation: 5.0,
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
child: InkWell(
child: Container(
color: Colors.white,
width: 200.0,
height: 250.0,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
width: 200.0,
height: 155.0,
child: CachedNetworkImage(
fadeInDuration: const Duration(milliseconds: 200),
fit: BoxFit.cover,
imageUrl: url,
placeholder: (context, urlImage) =>
Container(color: Colors.grey),
errorWidget: (context, urlImage, error) =>
Center(child: Container(color: Colors.grey)))),
Expanded(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
ubicacion != ""
? Text(ubicacion,
style: TextStyle(
fontSize: 12.0, color: Colors.grey[600]),
maxLines: 1)
: Container(),
titulo != ""
? Text(titulo,
style: const TextStyle(
fontSize: 15.0,
color: Colors.black,
fontWeight: FontWeight.normal),
maxLines: 2)
: Container(),
precio != ""
? Text(precio,
style: const TextStyle(
fontSize: 15.0,
color: Colors.black,
fontWeight: FontWeight.normal),
maxLines: 1)
: Container(),
Align(
alignment: Alignment.bottomRight,
child: IconButton(
icon: Heart.hearticon,
onPressed: Heart.changeHeart,
color: Colors.red,
),
),
],
),
),
),
],
),
),
),
),
Because you use the same icon for all, you have use separate statefull class for each card like this :
class MyWidget extends StatefulWidget {
const MyWidget({Key? key}) : super(key: key);
#override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
bool isActive = false;
#override
Widget build(BuildContext context) {
return Card(
elevation: 5.0,
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
child: InkWell(
child: Container(
color: Colors.white,
width: 200.0,
height: 250.0,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
width: 200.0,
height: 155.0,
child: CachedNetworkImage(
fadeInDuration: const Duration(milliseconds: 200),
fit: BoxFit.cover,
imageUrl: url,
placeholder: (context, urlImage) =>
Container(color: Colors.grey),
errorWidget: (context, urlImage, error) =>
Center(child: Container(color: Colors.grey)))),
Expanded(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
ubicacion != ""
? Text(ubicacion,
style: TextStyle(
fontSize: 12.0, color: Colors.grey[600]),
maxLines: 1)
: Container(),
titulo != ""
? Text(titulo,
style: const TextStyle(
fontSize: 15.0,
color: Colors.black,
fontWeight: FontWeight.normal),
maxLines: 2)
: Container(),
precio != ""
? Text(precio,
style: const TextStyle(
fontSize: 15.0,
color: Colors.black,
fontWeight: FontWeight.normal),
maxLines: 1)
: Container(),
Align(
alignment: Alignment.bottomRight,
child: IconButton(
icon: isActive? **first Icon** : **second Icon**,
onPressed: () {
setState(() {
isActive = !isActive;
});
},
color: Colors.red,
),
),
],
),
),
),
],
),
),
),
);
}
}
Here my bottom preferredSize (preferredSize: Size.fromHeight(148.0)) in appBar.
This error raised onlu in IOS not in android. I dont know why?
On every tab this error raising, so I thought I got this error by preferredSize.
But how to solve this I am not understanding.
This error raised onlu in IOS not in android. I dont know why?
On every tab this error raising, so I thought I got this error by preferredSize.
But how to solve this I am not understanding.
this is my code
import 'package:flutter/material.dart';
import 'package:showcaseview/showcaseview.dart';
import 'package:url_launcher/url_launcher.dart' as UrlLauncher;
import 'package:dropdown_button2/dropdown_button2.dart';
import 'dart:developer';
import '../../../APIMnager/APIManager.dart';
import '../../../APIMnager/preferences.dart';
import '../../../Constants/constants.dart';
import 'action_page.dart';
import 'holding_page.dart';
import 'overview_page.dart';
import 'report_page.dart';
class PMSListDataPage extends StatelessWidget {
final panNum;
final singlePMSData;
final allPMSListData;
const PMSListDataPage(
{Key? key, this.panNum, this.singlePMSData, this.allPMSListData})
: super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: ShowCaseWidget(
onStart: (index, key) {
log('onStart: $index, $key');
},
onComplete: (index, key) {
log('onComplete: $index, $key');
print("here me");
if (index == 0) {
Preferences.saveData("showCaseCount2", "2");
}
},
blurValue: 1,
builder: Builder(
builder: (context) => PMSListDataPage1(
panNum: panNum,
singlePMSData: singlePMSData,
allPMSListData: allPMSListData)),
autoPlayDelay: const Duration(seconds: 3),
),
);
}
}
class PMSListDataPage1 extends StatefulWidget {
final panNum;
final singlePMSData;
final allPMSListData;
const PMSListDataPage1(
{Key? key, this.panNum, this.singlePMSData, this.allPMSListData})
: super(key: key);
#override
_PMSListDataPage1State createState() => _PMSListDataPage1State();
}
class _PMSListDataPage1State extends State<PMSListDataPage1> {
var selectedValue;
ApiManager apiManager = ApiManager();
final GlobalKey _one = GlobalKey();
final GlobalKey _two = GlobalKey();
final GlobalKey _three = GlobalKey();
final scrollController = ScrollController();
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: DefaultTabController(
length: 4,
child: Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
leading: Builder(
builder: (BuildContext context) {
return IconButton(
icon: Icon(Icons.arrow_back_ios_rounded),
onPressed: () {
Navigator.pop(context);
},
tooltip: '',
);
},
),
elevation: 0,
backgroundColor: skyBlue,
title: Text(
"PMS",
style: TextStyle(fontSize: tSize16),
),
actions: [
Row(
children: [
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: IconButton(
icon: Image.asset(
"assets/phone_icon.png",
height: 25,
width: 25,
),
onPressed: () {
UrlLauncher.launch('tel:+91$UserRMNumber');
}))
],
)
],
bottom: PreferredSize(
preferredSize: Size.fromHeight(148.0),
child: Column(
children: [
Container(
color: skyBlue,
height: 90,
child:
nameView(widget.singlePMSData, widget.allPMSListData),
),
Padding(
padding: const EdgeInsets.only(bottom: 10.0),
child: TabBar(
overlayColor:
MaterialStateProperty.all(Colors.transparent),
indicatorColor: Colors.white,
unselectedLabelColor: lightBlue,
onTap: (v) {
searchHoldingsQuery.clear();
FocusScope.of(context).unfocus();
},
indicator: UnderlineTabIndicator(
borderSide: BorderSide(
color: Colors.white,
width: 3.2,
style: BorderStyle.solid),
insets: EdgeInsets.only(left: 30.0, right: 30)),
isScrollable: true,
labelColor: Colors.white,
tabs: [
Tab(
child: Text(
'OVERVIEW',
),
),
Tab(
child: Text(
'HOLDINGS',
),
),
Tab(
child: Text(
'REPORTS',
),
),
Tab(
child: Text(
'ACTIONS',
),
),
],
),
),
],
),
),
),
body:
TabBarView(physics: NeverScrollableScrollPhysics(), children: [
Padding(
padding: const EdgeInsets.only(top: 12.0),
child: OverviewPage(),
),
Padding(
padding: const EdgeInsets.only(top: 12.0),
child: HoldingPage(),
),
Padding(
padding: const EdgeInsets.only(top: 12.0),
child: ReportPage(),
),
Padding(
padding: const EdgeInsets.only(top: 12.0),
child: ActionPage(),
),
]),
)),
);
}
}
extension WidgetExtension on _PMSListDataPage1State {
nameView(singlePMSData, allPMSListData) {
return Padding(
padding: const EdgeInsets.only(left: 20, right: 20, top: 5, bottom: 0),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: Colors.white,
),
child: DropdownButtonHideUnderline(
child: DropdownButton2(
onMenuClose: () {},
onTap: () {},
isExpanded: true,
hint: Row(
children: [
SizedBox(
width: 10,
),
Expanded(
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
singlePMSData['name'].toString(),
style: TextStyle(
fontSize: tSize16,
fontWeight: FontWeight.w600,
color: blackColor,
),
overflow: TextOverflow.ellipsis,
),
SizedBox(
height: 6,
),
Row(
children: [
Text(
'₹ ${singlePMSData["current_value"]}',
style: TextStyle(
fontSize: tSize16,
fontWeight: FontWeight.w600,
color: green2Color,
),
overflow: TextOverflow.ellipsis,
),
SizedBox(
width: 10,
),
],
),
],
),
],
),
),
],
),
items: allPMSListData.map<DropdownMenuItem<Object>>((option) {
return DropdownMenuItem(
value: option,
child: Container(
width: double.infinity,
alignment: Alignment.centerLeft,
// padding: const EdgeInsets.fromLTRB(0,8.0,0,6.0),
child: Row(
children: [
SizedBox(
width: 10,
),
Text(
option["name"],
style: TextStyle(
fontSize: tSize16,
fontWeight: FontWeight.w600,
color: blackColor,
),
overflow: TextOverflow.ellipsis,
),
],
),
decoration: BoxDecoration(
border: Border(
top: BorderSide(color: lightGreyColor, width: 1)))),
);
}).toList(),
selectedItemBuilder: (con) {
return allPMSListData.map<Widget>((item) {
return Row(
children: [
SizedBox(
width: 10,
),
Expanded(
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
item['name'].toString(),
style: TextStyle(
fontSize: tSize16,
fontWeight: FontWeight.w600,
color: blackColor,
),
overflow: TextOverflow.ellipsis,
),
SizedBox(
height: 6,
),
Row(
children: [
Text(
"₹ ${item["current_value"]}",
style: TextStyle(
fontSize: tSize16,
fontWeight: FontWeight.w600,
color: green2Color,
),
overflow: TextOverflow.ellipsis,
),
SizedBox(
width: 10,
),
],
),
],
),
],
),
),
],
);
}).toList();
},
value: selectedValue,
onChanged: (dynamic value) {
setState(() {
});
},
icon: Container(
width: 22,
height: 22,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(3),
color: skyBlue,
),
child: Icon(
Icons.keyboard_arrow_down,
color: Colors.white,
size: 17,
),
),
iconOnClick: Container(
width: 22,
height: 22,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(3),
color: skyBlue,
),
child: Icon(
Icons.keyboard_arrow_up,
color: Colors.white,
size: 17,
),
),
iconSize: 14,
buttonHeight: 70,
buttonPadding: const EdgeInsets.only(left: 14, right: 14),
buttonDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(14),
border: Border.all(
color: lightBlue,
),
color: Colors.white,
),
buttonElevation: 1,
itemHeight: 44,
itemPadding: const EdgeInsets.only(left: 14, right: 14),
dropdownMaxHeight: 200,
dropdownPadding: null,
dropdownDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(14),
color: Colors.white,
),
dropdownElevation: 1,
scrollbarRadius: const Radius.circular(40),
scrollbarThickness: 3,
scrollbarAlwaysShow: false,
// offset: const Offset(-10, 0),
),
),
),
);
}
}
I have gridviewbuilder that takes data from itemGriddata which has onTap function that directs it to a new page that takes data from that model as well but when I click on it the error in the title appears, any help or some kind of enlightement would be appreciated
this is gridview page
import 'package:flutter/material.dart';
import 'package:wild_wild_rift/builds/SinglePage.dart';
import 'package:wild_wild_rift/data/model.dart';
import 'package:google_fonts/google_fonts.dart';
class GridViewPage extends StatefulWidget {
#override
_GridViewPage createState() => _GridViewPage();
}
class _GridViewPage extends State<GridViewPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.grey,
automaticallyImplyLeading: true,
title: const Text(
'Champions',
style: TextStyle(
fontFamily: 'Lexend Doca',
color: Colors.white,
fontSize: 32,
fontWeight: FontWeight.bold,
),
),
elevation: 2,
),
body: Column(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(15, 15, 15, 15),
child: GridView.builder(
itemCount: itemGriddata.length,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
childAspectRatio: 1,
),
itemBuilder: (context, index) {
return GridSingleItem(
itemGriddata: itemGriddata[index],
onTap: () async {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SinglePage(itemGriddata[index])));
},
);
},
),
),
),
],
));
}
}
class GridSingleItem extends StatelessWidget {
final itemGriddata;
final Function onTap;
const GridSingleItem({Key key, #required this.itemGriddata, this.onTap})
: super(key: key);
#override
Widget build(BuildContext context) {
return InkWell(
onTap: onTap,
child: ClipRRect(
borderRadius: BorderRadius.circular(5),
child: Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: const Color(0xEEEEEE),
image: DecorationImage(
fit: BoxFit.cover,
image: Image.asset(itemGriddata.image).image,
),
boxShadow: const [
BoxShadow(
blurRadius: 3,
color: Color(0xDA000000),
)
],
borderRadius: BorderRadius.circular(9),
border: Border.all(
color: Colors.black,
),
),
child: Align(
alignment: AlignmentDirectional(-0.45, 0.85),
child: Text(
itemGriddata.name,
style: TextStyle(
fontFamily: 'Lexend Deca',
color: Color(0xFFFFFCFC),
fontWeight: FontWeight.normal,
shadows: [
Shadow(
blurRadius: 8.0,
color: Colors.black,
offset: Offset(1.0, 1.0),
),
],
),
),
),
),
),
);
}
}
this is page that I'd want to take data
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import '../data/model.dart';
class SinglePage extends StatefulWidget {
#override
_SinglePage createState() => _SinglePage();
final Data data;
SinglePage(this.data);
}
class _SinglePage extends State<SinglePage> {
PageController pageViewController;
bool isFirstButton = false;
bool isSecondButton = false;
#override
void initState() {
super.initState();
pageViewController = PageController(initialPage: 0);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: const Color(0xFF090F13),
automaticallyImplyLeading: true,
title: Text(
itemGriddata.name,
style: TextStyle(
fontFamily: 'Lexend Deca',
color: Colors.white,
fontSize: 32,
fontWeight: FontWeight.bold,
),
),
actions: const [],
centerTitle: false,
elevation: 2,
),
backgroundColor: const Color(0xFF262D34),
body: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0, 0, 0, 25),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Row(
mainAxisSize: MainAxisSize.max,
children: [
Material(
color: Colors.transparent,
elevation: 3,
child: Container(
width: MediaQuery.of(context).size.width,
height: 150,
decoration: BoxDecoration(
color: const Color(0xFF090F13),
image: DecorationImage(
fit: BoxFit.cover,
image: Image.asset(
itemGriddata.backgroundimage,
).image,
),
),
),
),
],
),
Padding(
padding:
const EdgeInsetsDirectional.fromSTEB(20, 12, 20, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
children: const [
Text(
'Choose role',
style: TextStyle(
fontFamily: 'Lexend Deca',
color: Color(0xFF8B97A2),
fontSize: 14,
fontWeight: FontWeight.normal,
),
),
],
),
),
Padding(
padding:
const EdgeInsetsDirectional.fromSTEB(0, 12, 1, 0),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(
16, 0, 0, 0),
child: InkWell(
onTap: () async {
isSecondButton = false;
isFirstButton = true;
setState(() {});
await pageViewController.animateToPage(
0,
duration: const Duration(milliseconds: 500),
curve: Curves.ease,
);
},
child: Material(
color: Colors.transparent,
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
child: Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: const Color(0xFF090F13),
borderRadius: BorderRadius.circular(8),
shape: BoxShape.rectangle,
border: isFirstButton
? Border.all(color: Colors.white)
: null),
child: Stack(
children: [
Align(
alignment: const AlignmentDirectional(
0, -0.05),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Image.asset(
'assets/images/icon-position-jungle.png',
width: 50,
height: 50,
fit: BoxFit.cover,
),
const Padding(
padding: EdgeInsetsDirectional
.fromSTEB(0, 8, 0, 0),
child: AutoSizeText(
'BUILD 1',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Lexend Deca',
color: Color(0xFF8B97A2),
fontSize: 14,
fontWeight:
FontWeight.normal,
),
),
),
],
),
),
],
),
),
),
),
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(
16, 0, 0, 0),
child: Material(
color: Colors.transparent,
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
child: Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: const Color(0xFF090F13),
borderRadius: BorderRadius.circular(8),
border: isSecondButton
? Border.all(color: Colors.white)
: null),
child: InkWell(
onTap: () async {
isSecondButton = true;
isFirstButton = false;
setState(() {});
await pageViewController.animateToPage(
1,
duration:
const Duration(milliseconds: 500),
curve: Curves.ease,
);
},
child: Stack(
children: [
Align(
alignment: const AlignmentDirectional(
0, -0.05),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Image.asset(
'assets/images/icon-position-jungle.png',
width: 50,
height: 50,
fit: BoxFit.cover,
),
const Padding(
padding: EdgeInsetsDirectional
.fromSTEB(0, 8, 0, 0),
child: AutoSizeText(
'BUILD 2',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Lexend Deca',
color: Color(0xFF8B97A2),
fontSize: 14,
fontWeight:
FontWeight.normal,
),
),
),
],
),
),
],
),
),
),
),
),
],
),
),
),
Padding(
padding:
const EdgeInsetsDirectional.fromSTEB(20, 8, 20, 8),
child: Row(
mainAxisSize: MainAxisSize.max,
children: const [
Text(
'Builds',
style: TextStyle(
fontFamily: 'Lexend Deca',
color: Color(0xFF8B97A2),
fontSize: 14,
fontWeight: FontWeight.normal,
),
),
],
),
),
SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(
16, 8, 16, 0),
child: Container(
width: MediaQuery.of(context).size.width,
height: 200,
decoration: BoxDecoration(
color: const Color(0x00090F13),
boxShadow: const [
BoxShadow(
blurRadius: 3,
color: Colors.transparent,
offset: Offset(0, 2),
)
],
borderRadius: BorderRadius.circular(8),
),
child: SizedBox(
width: double.infinity,
height: 500,
child: PageView(
controller: pageViewController,
scrollDirection: Axis.horizontal,
children: [
Image.asset(
'assets/images/image_1.png',
width: 100,
height: 100,
fit: BoxFit.cover,
),
Image.asset(
'assets/images/image_2.png',
width: 100,
height: 100,
fit: BoxFit.scaleDown,
),
],
),
),
),
),
],
),
),
],
),
),
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(20, 0, 20, 8),
child: Row(
mainAxisSize: MainAxisSize.max,
children: const [
Text(
'Text',
style: TextStyle(
fontFamily: 'Poppins',
color: Color(0xFF8B97A2),
),
),
],
),
),
],
),
),
);
}
}
and this is the model with data
final dynamic itemGriddata = [
Data(
name: "Ahri",
image: "assets/images/Ahri.png",
backgroundimage: "assets/images/Ahri_0.jpg"),
Data(
name: "Akali",
image: "assets/images/Akali.png",
backgroundimage: "assets/images/Akali_0.jpg")
];
class Data {
final String name;
final String image;
final String backgroundimage;
Data({this.name, this.image, this.backgroundimage});
}
The issue is that your SinglePage widget has a prop named final Data data; but the _SinglePageState widget is calling itemGriddata for your title and images. You'll need to change your code like so:
class SinglePage extends StatefulWidget {
const SinglePage(Key? key, this.data): super(key: key);
final Data data;
#override
State<StatefulWidget> createState() => _SinglePageState();
}
class _SinglePageState extends State<SinglePage> {
// use widget.data to get name, image, and backgroundImage
// ex... widget.data.name or widget.data.image
#override
Widget build(BuildContext context) {
return Text(widget.data.name);
}
}
You're passing the data correctly to SinglePage, but just change a few lines to ensure you're calling something with actual data! :D
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;