Future function reloads infinitely? flutter - flutter

i am building a simple ecommerce app but i am stuck at a position when my future function reloads infinitely:
Future getCartData() async {
print("function one");
print("this is the token mytoken");
String url = 'https://myurl/apis/getCartItems';
http.Response response = await http.post(Uri.parse(url),
headers: {
'Authorization': "token mytoken",
"Content-Type": "application/json",
},
body: json.encode({
"username": "admin",
}));
print(response.body);
var data = json.decode(response.body);
print("cart data recieved :");
print(data.length);
//set state
setState(() {
lengthData=data.length.toString();
totalPrice=0;
});
return data;
}
i am using set state becouse i need to set this value once the data return but this set state reloading again and again when i remove it future function run only once but it not update the values of "lengthData" and "totalPrice".
my init function:
initState(){
getCartData();
super.initState();
}
and here is my futurebuilder:
child:FutureBuilder(
future: getCartData(),
builder: (context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
// still waiting for data to come
return Center(
child: CircularProgressIndicator(),
);
} else if (snapshot.hasData &&
snapshot.data.isEmpty) {
return Center(child: Text("No Products"));
;
} else {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (BuildContext context, index) {
List list = snapshot.data;
totalPrice = totalPrice + list[index]['price'];
print("this is the total:$totalPrice");
return Container(
margin: EdgeInsets.only(top: 20),
height: 130,
child: Stack(
children: <Widget>[
Align(
alignment: Alignment(0, 0.8),
child: Container(
height: 100,
margin: EdgeInsets.symmetric(
horizontal: 16.0),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: shadow,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(
10))),
child: Row(
mainAxisAlignment: MainAxisAlignment
.end,
children: <Widget>[
Container(
padding: EdgeInsets.only(
top: 12.0, right: 12.0),
width: 200,
child: Column(
crossAxisAlignment: CrossAxisAlignment
.start,
children: <Widget>[
Text(
'${list[index]['title']}',
textAlign: TextAlign.right,
style: TextStyle(
fontWeight: FontWeight
.bold,
fontSize: 12,
color: darkGrey,
),
),
Align(
alignment: Alignment
.centerRight,
child: Container(
width: 160,
padding: const EdgeInsets
.only(
left: 32.0,
top: 8.0,
bottom: 8.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: <Widget>[
ColorOption(
Colors.red),
Text(
"\₹${list[index]['price']}",
textAlign: TextAlign
.center,
style: TextStyle(
color: darkGrey,
fontWeight: FontWeight
.bold,
fontSize: 18.0),
)
],
),
),
)
],
),
),
Theme(
data: ThemeData(
accentColor: Colors.black,
textTheme: TextTheme(
headline6: TextStyle(
fontFamily: 'Montserrat',
fontSize: 14,
color: Colors.black,
fontWeight: FontWeight
.bold),
bodyText1: TextStyle(
fontFamily: 'Montserrat',
fontSize: 12,
color: Colors.grey[400],
),
)),
child: NumberPicker(
value: 2,
minValue: 1,
maxValue: 10,
onChanged: (value) {
// setState(() {
// quantity = value;
// });
},
))
])),
),
Positioned(
top: 5,
child: SizedBox(
height: 150,
width: 200,
child: Stack(children: <Widget>[
Positioned(
left: 25,
child: SizedBox(
height: 150,
width: 150,
child: Transform.scale(
scale: 1.2,
child: Image.asset('assets/bottom_yellow.png'),
),
),
),
Positioned(
left: 50,
top: 5,
child: SizedBox(
height: 80,
width: 80,
child: Image.network(
'$Imagename',
fit: BoxFit.contain,
)),
),
Positioned(
right: 30,
bottom: 25,
child: Align(
child: IconButton(
icon: Image.asset('assets/red_clear.png'),
onPressed: (){
deleteCartData('${list[index]['id']}');
},
),
),
)
]),
)
),
],
),
);
}
):Center(child: Text("no data"));
}
},
)
can someone please help me and suggest me a better way to solve it <3.
Thanks in Advance <3.

You need to return a Future from your 'getCartData()' method, now you are returning just a Hashmap instead of a Future which the futureBuilder needs. You can do it like this:
return Future.value(data);
One more thing is that you must just pass the reference to the method and not call it, like this:
future: getCartData,
Also please specify the return types, use Future<Map<String, dynamic>> or whatever you are returning (this will help you in the future) :D
And one more, you don't need to call your method in 'initState()' since the FutureBuilder will do it for you :)

Related

Flutter - Managing CarouselSlider to match the width of it's parent and making right and left edges transparent

I am using CarouselSlider in Flutter to get the output as below (Special Event section):
But getting result as below :
The Issue is It should be with same width as top and bottom widget vertically (you can see in first image), In result Image, there is little more width between right and left transparent area and middle portion. So, middle portion width and the transparency of left and right edge is concern here.
How can I get the same result?
I have done so far as below:
Container(
child: CarouselSlider(
options: CarouselOptions(
enlargeCenterPage: true,
disableCenter: false,
scrollDirection: Axis.horizontal,
onPageChanged: (index, reason) {
setState(() {
activeSpecialEventPage = index;
});
}),
items: <Widget>[
for (var i = 0; i < special_events.length; i++)
GestureDetector(
onTap: () async {
await getCurrentLocation();
if (getDouble(prefCurrLat) != null &&
getDouble(prefCurrLong) != null) {
NavigationUtils.push(context, routeDetailScreen,
arguments: {
argDetailScreenTitle:
Localization.of(context).labelExhibitions,
argCurrentLat: getDouble(prefCurrLat),
argCurrentLong: getDouble(prefCurrLong),
argEventObj: special_events[i]
});
}
},
child: Container(
width: MediaQuery.of(context).size.width,
child: Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.w),
topRight: Radius.circular(10.h),
bottomRight: Radius.circular(10.w),
bottomLeft: Radius.circular(10.h)),
child: Image.network(
special_events[i].image.toString(),
errorBuilder: (context, url, error) => Center(
child: SizedBox(
width: 160.w,
height: 160.h,
child: Image.asset(imgPlaceHolder))),
loadingBuilder: (BuildContext context,
Widget child,
ImageChunkEvent? loadingProgress) {
if (loadingProgress == null) {
return child;
}
return Center(
child: Image.asset(imgPlaceHolder,
width: 160.w,
height: 160.h,
fit: BoxFit.cover),
);
},
width: 327.w,
height: 200.h,
fit: BoxFit.cover)),
Positioned(
bottom: 16.h,
left: 20.w,
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: blackColorOP11,
width: 300.w,
child: Text(
special_events[i].name.toString(),
style: TextStyle(
fontWeight: FontWeight.w600,
fontFamily: "Poppins",
fontSize: 24.sp,
color: Colors.white),
softWrap: false,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
special_events[i].dateText != null &&
special_events[i]
.dateText
.toString()
.length >
0
? Container(
color: blackColorOP11,
child: Text(
getFormatedDateForSpecialEvent(
special_events[i]
.dateText
.toString()),
style: TextStyle(
fontWeight: FontWeight.w400,
fontFamily: "Poppins",
fontSize: 12.sp,
color: Colors.white),
softWrap: false,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
)
: Container(),
],
),
),
)
],
),
),
)
],
),
)
: buildNoDataWidget(Localization.of(context).labelNoSpecialEvents);
There are a number of variables you can play with here. I've assumed you've used the carousel_slider package.
In the CarouselOptions you can change the aspectRatio and viewportRatio and resolve your issue right away. For example a viewportFraction: 0.7 would work for your code sample.
However if you want your viewPort to remain the same, you would have to change the width and height of your Image.network AND the aspectRatio to something like:
- CarouselOptions
aspectRatio: 20 / 9
Image.network
width: 360,
height: 200
If there's a specific height or width you must strictly abide to you should play with these 3 values to ensure it work.
I've tested the below code, with some alterations, with dummy data and values and they work well together.
class SpecialEvents {
final String image;
final DateTime dateText;
final String name;
SpecialEvents(
{required this.image, required this.name, required this.dateText});
}
List<SpecialEvents> special_events = [
SpecialEvents(
name: "Road",
image:
"https://images.unsplash.com/photo-1666069810128-e7dfe3b0d653?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=692&q=80",
dateText: DateTime.now()),
SpecialEvents(
name: "NY",
image:
"https://images.unsplash.com/photo-1665806558925-930b7210d8bb?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80",
dateText: DateTime.now())
];
CarouselSlider(
options: CarouselOptions(
enlargeCenterPage: true,
aspectRatio: 20 / 9,
// viewportFraction: 0.7,
// padEnds: false,
disableCenter: false,
scrollDirection: Axis.horizontal,
onPageChanged: (index, reason) {
setState(() {
activeSpecialEventPage = index;
});
}),
items: special_events
.map((SpecialEvents se) => GestureDetector(
onTap: () async {
debugPrint("tap function");
},
child: ClipRRect(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10),
bottomRight: Radius.circular(10),
bottomLeft: Radius.circular(10)),
child: Stack(
children: [
Image.network(se.image.toString(),
errorBuilder: (context, url, error) =>
Center(
child: SizedBox(
width: 160,
height: 160,
child: Image.asset(
"imgPlaceHolder"))),
loadingBuilder: (BuildContext context,
Widget child,
ImageChunkEvent?
loadingProgress) {
if (loadingProgress == null) {
return child;
}
return Center(
child: Image.asset(
"image place holder URL",
width: 160,
height: 160,
fit: BoxFit.cover),
);
},
width: 360,
height: 200,
fit: BoxFit.cover),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.end,
children: [
Row(
children: [
Expanded(
child: Container(
color: Colors.black26,
width: 300,
child: Padding(
padding: const EdgeInsets
.symmetric(
vertical: 8.0,
horizontal: 20),
child: Column(
crossAxisAlignment:
CrossAxisAlignment
.start,
children: [
Text(
se.name.toString(),
style:
const TextStyle(
fontWeight:
FontWeight
.w600,
fontSize: 24,
color: Colors
.white),
softWrap: false,
maxLines: 1,
overflow: TextOverflow
.ellipsis,
),
Text(
se.dateText
.toString(),
style:
const TextStyle(
fontWeight:
FontWeight
.w400,
fontSize: 12,
color: Colors
.white),
softWrap: false,
maxLines: 1,
overflow: TextOverflow
.ellipsis,
)
],
),
),
),
),
],
),
],
)
],
)),
))
.toList())
Hope that helps explain it.
There is a property on CarouselSlider, onPageChanged.
you need to maintain a int, e.g. currentPageIndex as below,
...
onPageChanged: (index, _) {
setState(
() {
currentPageIndex = index;
}
);
}
...
And then inside itemBuilder do like this,
...
itemBuilder: (context, index, _) {
return Opacity(
opacity: index == currentPageIndex ? 1.0 : 0.2,
child: Your_Widget(),
);
}
...

Snapshot from StreamBuilder

I am working on a ListView inside a Streambuilder with data from Cloud Firestore.
Here you have the code:
//inicio stream
StreamBuilder<List<Evento>>(
stream: eventosProvider
.eventosbares,
builder: (context, snapshot) {
if (snapshot
.data.isNotEmpty) {
return SizedBox(
height: 155,
child: ListView.builder(
scrollDirection:
Axis.horizontal,
itemCount: snapshot
.data.length,
itemBuilder:
(context,
index) {
var dateString =
snapshot
.data[
index]
.fechaEvento;
var date = DateFormat(
'd-M-yyyy HH:mm',
'de_DE')
.parse(
dateString);
return Card(
shape:
RoundedRectangleBorder(
borderRadius:
BorderRadius
.circular(
10),
),
child:
Container(
height: 178,
width: 280,
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(
left: 8.0,
right: 8.0,
top: 8.0),
child:
ClipRRect(
borderRadius:
BorderRadius.circular(8),
child:
Image.network(
snapshot.data[index].imagenEvento,
width: 278.0,
height: 80.0,
fit: BoxFit.fill,
),
),
),
Padding(
padding:
const EdgeInsets.all(8.0),
child:
Row(
mainAxisAlignment:
MainAxisAlignment.start,
children: [
CircleAvatar(
radius: 20.0,
backgroundImage: NetworkImage(snapshot.data[index].fotoPerfilAutor),
backgroundColor: Colors.transparent,
),
Padding(
padding: const EdgeInsets.all(2.0),
child: Container(
width: 150,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
snapshot.data[index].tituloEvento,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 13,
),
),
Text(
DateFormat('EEEEE dd MMM yyyy HH:mm', 'es_ES').format(date),
style: TextStyle(fontSize: 10),
),
],
),
),
),
SizedBox(
width: 10,
),
Text(
snapshot.data[index].num_invitados,
style: TextStyle(color: ColoresApp.naranjaTop, fontWeight: FontWeight.bold, fontSize: 14),
),
SizedBox(
width: 5,
),
CircleAvatar(
radius: 10.0,
backgroundImage: AssetImage("assets/friends.png"),
backgroundColor: Colors.transparent,
)
],
),
),
]),
),
);
}),
);
} else {
return Text(
"No hay eventos en bares",
style: TextStyle(
color:
Colors.white),
);
}
}),
I am getting the following exception using this code, the app is not exiting, it only shows a red error background for a moment, but it is not acceptable:
======== Exception caught by widgets library =======================================================
The following NoSuchMethodError was thrown building StreamBuilder<List<Evento>>(dirty, state: _StreamBuilderBaseState<List<Evento>, AsyncSnapshot<List<Evento>>>#d6fd3):
The getter 'isNotEmpty' was called on null.
Receiver: null
Tried calling: isNotEmpty
I have tried changing the line:
if (snapshot.data.isNotEmpty)
with
if (snaphot.hasData)
but then, the exception is gone, but there is a blank space thrown, not the else part of the if clause.
What should I do to know if the snapshop has really data or is waiting to get them?
EDIT
Here you have the service loading the Stream:
Stream<List<Evento>> getEventosBares(){
return _db
.collection('eventos').where('interes', isEqualTo: 'bares')
.snapshots()
.map((snapshot) => snapshot.docs
.map((doc) => Evento.fromJson(doc.data()))
.toList());
}
And here you have the provider:
Stream<List<Evento>> get eventosbares => firestoreService.getEventosBares();
Try adding a null check:
builder: (context, snapshot) {
if (snapshot.data != null && snapshot.data.isNotEmpty) {
return SizedBox(...);

Pass document content from one screen to another in flutter firestore

In the code below, I am trying to pass data from the home screen to the detail screen when user clicks on any of the product listed on the home screen. I seem to be having difficulty here.
Similar Question but does not solve my issue
Excerpt of the code at the home screen.
StreamBuilder(
stream: FirebaseFirestore.instance
.collection("name")
.limit(12)
.orderBy("Published Date", descending: true)
.snapshots(),
builder: (context, snapshot){
if (!snapshot.hasData) {
return Center(
child: spinkit,
);
}
return GridView.builder(
physics: ScrollPhysics(),
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: snapshot.data.docs.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 10.0,
mainAxisSpacing: 10,
),
itemBuilder: (BuildContext context, int index){
if(snapshot.connectionState == ConnectionState.waiting){
return Center(
child: spinkit,
);
}
print("${snapshot.data.documents[index].get('Product Title')}");
return GestureDetector(
onTap: (){
// ===> SEND USER TO THE DETAILS SCREEN <===
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ProductDetailsScreen()),
);
},
child: ClipRRect(
borderRadius: BorderRadius.circular(5),
child: Stack(
children: [
Container(
height: 150,
width: 150,
child: Image.network(
snapshot.data.documents[index].get('image') ?? spinkit,
fit: BoxFit.cover,
width: double.infinity,
height: double.infinity,
),
),
Positioned(
left: 0,
bottom: 0,
child: Container(
height: 20,
width: 150,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.black38,
Colors.black38,
],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
)),
),
),
Positioned(
left: 4,
bottom: 5,
child: Text(
snapshot.data.documents[index].get('name') ?? "Product Name",
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Palette.whiteColor,
fontSize: 11,
fontWeight: FontWeight.bold),
),
)
],
),
),
);
}
);
},
)
And excerpt of the code at the Details Screen. what you see at the detail screen is data that I have populated manually. it is not coming from firestore.
class ProductDetailsScreen extends StatefulWidget {
#override
_ProductDetailsScreenState createState() => _ProductDetailsScreenState();
}
class _ProductDetailsScreenState extends State<ProductDetailsScreen> {
final productDb = FirebaseFirestore.instance.collection("name");
User user = FirebaseAuth.instance.currentUser;
final spinkit = SpinKitHourGlass(
color: Colors.white,
size: 50.0,
);
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: _onBackPressed,
child: Scaffold(
body: SafeArea(
child: Padding(
padding: EdgeInsets.only(left: 15, right: 15, top: 3, bottom: 10),
child: FutureBuilder(
future: productDb.get(),
builder: (context, snapshot){
if(snapshot.connectionState == ConnectionState.waiting){
return Center(
child: spinkit,
);
}
return Container(
child: ListView(
children: [
Column(
children: [
Center(
child: Container(
width: 350,
child: Card(
elevation: 5,
child: Container(
padding: EdgeInsets.all(8),
child: Container(
height: 220,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.fill,
image: AssetImage("asset/images/headphone.jpg",)
)
),
),
),
),
),
),
SizedBox(height: 10,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("Item Name",
style: TextStyle(
color: Palette.blackColor,
fontSize: 18,
fontWeight: FontWeight.w300
),),
Text("Item Price",
style: TextStyle(
color: Palette.blackColor,
fontSize: 18,
fontWeight: FontWeight.w300
),),
],
),
SizedBox(height: 10,),
Text("Item Description",
style: TextStyle(
color: Palette.blackColor,
fontSize: 18,
fontWeight: FontWeight.w300
),),
Container(
height: 1,
width: 100,
color: Colors.black12,
),
SizedBox(height: 10,),
Container(
height: 140,
width: 350,
child: SingleChildScrollView(
child: Wrap(
children: [
Text(
"What is Lorem Ipsum Lorem Ipsum is simply dummy "
"text of the printing and typesetting industry"
" Lorem Ipsum has been the industry's standard"
" dummy text ever since the 1500s when an "
"unknown printer took a galley of type and "
"scrambled it to make a type specimen book "
"it has?",
textAlign: TextAlign.justify,
style: TextStyle(
color: Palette.blackColor,
fontSize: 16,
),),
]
),
),
),
],
),
],
),
);
},
),
)),
),
);
}
}
In your GestureDetector onTap
// ===> SEND USER TO THE DETAILS SCREEN WITH DOC<===
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ProductDetailsScreen(snapshot.data.documents[index])),
);
Then
class ProductDetailsScreen extends StatefulWidget {
ProductDetailsScreen(this.doc);
QueryDocumentSnapshot doc;
#override
_ProductDetailsScreenState createState() => _ProductDetailsScreenState();
}
Access in _ProductDetailsScreenState as widget.doc.
The document data will be found at widget.doc.data as a Map<String, dynamic>.

How to make infinity scroll layout in flutter? (Updated)

I'm trying to make listview using data from REST API, the position is below my image , but the layout reach its limit, so i can't create it , and showing this error
here my code, (Updated Code)
import 'package:http/http.dart' as http;
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:schoolofparentingalfa/assets/color/color.dart';
class Home extends StatefulWidget {
#override
Home2 createState() => Home2();
}
class Home2 extends State<Home> {
var colorsop = new Colorsop();
var apiconfig = new ApiConfig();
var apiClient = new ApiClient();
#override
void initState() {
super.initState();
}
//To call list from api
Future<List<Artikel>> getNews() async {
// future is used to handle the error when calling api > Future + async or await
var data = await http.get(
'https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=c4349a84570648eaa7be3cd673cc262b');
var jsonData = json.decode(data.body);
var newsData =
jsonData['articles']; //to retrieve data from articles array of api
List<Artikel> news = []; // create array
for (var data in newsData) {
//assign data into News model array list from articles array of api
Artikel newsItem = Artikel(
data['title'], data['description'], data['urlToImage']);
news.add(newsItem);
}
return news;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(children: <Widget>[
Positioned(
top: 0,
child: Container(
height: 100,
width: MediaQuery.of(context).size.width,
color: Colors.yellow[800],
child: Align(
alignment: Alignment.center,
child: Text("Halo, Selamat Datang", style: TextStyle(color: Colors.white, fontSize: 25),))),
),
Positioned(
top: 90,
bottom: 0,
right: 0,
left: 0,
child: Container(
width: MediaQuery.of(context).size.width,
height: 600,
decoration: BoxDecoration(
color: Colors.white,
),
child: GridView.count(
crossAxisCount: 1,
children: [
Container( // Container 1
child: Row(
children: <Widget>[
Image.asset(
'lib/assets/image/kelas_online.png',
height: 120,
width: 150,
),
Image.asset(
'lib/assets/image/tanyaahli.png',
height: 120,
width: 150,
),
],
),
),
Container( // Container 2
child: Row(
children: <Widget>[
Image.asset(
'lib/assets/image/workshop_online.png',
height: 120,
width: 150,
),
Image.asset(
'lib/assets/image/MitraSekolah.png',
height: 120,
width: 150,
),
],
),
),
Container( //Container 3
margin: EdgeInsets.only(top: 15, bottom: 30, left: 20),
padding: EdgeInsets.symmetric(horizontal: 15),
child: FutureBuilder(
future: getNews(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
//snapshot is same with response
if (snapshot.data == null) {
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
// to retrieve data as all array indexes
itemBuilder: (BuildContext context, int index) {
// is same with holder
return InkWell(
// Inkwell is used to apply card view
onTap: () {
Artikel news = new Artikel(snapshot.data[index].post_link, snapshot.data[index].description, snapshot.data[index].post_image);//is used to onclick
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => new Details(news: news)
));
},
child: Card(
child: Row(
children: <Widget>[
Container(
width: 120.0,
height: 110.0,
child: ClipRRect(
//for corner radius
borderRadius:
BorderRadius.all(Radius.circular(8)),
//to retrieve image from array
child: snapshot.data[index].post_image == null
? Image.network(
'https://cdn2.vectorstock.com/i/1000x1000/70/71/loading-icon-load-icon-wait-for-a-wait-please-wait-vector-24247071.jpg')
: Image.network(
snapshot.data[index].post_image,
width: 100,
fit: BoxFit.fill,
),
),
),
Expanded(
child: ListTile(
//include title and subtitle
title: Text(snapshot.data[index].post_title),
subtitle: Text(snapshot.data[index].post_link == null
? 'Unknown Author'
: snapshot.data[index].post_link),
),
)
],
),
),
);
},
);
}
},
),
),
],
),
)
)
],),
);
}
}
}
class Details extends StatelessWidget{
final Artikel news;
Details({this.news}); // create constructor
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
child: Column(
children: <Widget>[
Stack( //little same with expanded
children: <Widget>[
Container(
height: 400,
child: Image.network('${this.news.post_image}',
fit: BoxFit.fill,),
),
AppBar(
backgroundColor: Colors.transparent,
leading: InkWell(
child: Icon(Icons.arrow_back_ios),
onTap: () => Navigator.pop(context),
),
elevation: 0,
)
],
),
Padding(
padding: const EdgeInsets.all(8),
child: Column(
children: <Widget>[
SizedBox( // for title
height: 10,
),
Text(
'${this.news.post_title}',
style: TextStyle(
color: Colors.black87,
fontWeight: FontWeight.bold,
fontSize: 20,
letterSpacing: 0.2,
wordSpacing: 0.6
),
),
SizedBox( // for description
height: 20,
),
Text(
this.news.post_link,
style: TextStyle(
color: Colors.black54,
fontSize: 16,
letterSpacing: 0.2,
wordSpacing: 0.3
),
)
],
),
)
],
),
),
),
);
}
}
class Artikel {
final String post_title;
final String post_link;
final String post_image;
//Alt+insert > constructor
Artikel(this.post_title, this.post_link, this.post_image);
}
Can anyone help me?
Updated Screenshot .............................................................................
you can replace the code and check
return Scaffold(
body: Stack(children: <Widget>[
Positioned(
top: 0,
child: Container(
height: 100,
width: MediaQuery.of(context).size.width,
color: Colors.yellow[800],
child: Align(
alignment: Alignment.center,
child: Text("Halo, Selamat Datang", style: TextStyle(color: Colors.white, fontSize: 25),))),
),
Positioned(
top: 90,
bottom: 0,
right: 0,
left: 0,
child: Container(
width: MediaQuery.of(context).size.width,
height: 600,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(topLeft:Radius.circular(20), topRight:Radius.circular(20)) ),
child:
GridView.count(
crossAxisCount: 2,
children: List.generate(5, (index) {
return Padding(
padding: const EdgeInsets.all(24.0),
child: GridTile(child: Image.network("https://upload.wikimedia.org/wikipedia/commons/6/6d/Good_Food_Display_-_NCI_Visuals_Online.jpg"),),
);
}) ,),)
)
],),
);

Widget in Future

I am trying to use a dialog widget which will get some info from future builder, when I build the dialog under onTap it works but code looks so weird in that way because I use that build more then once, so I want to make a dialog class then call it when I needed but I couldn't achieve that yet, is this possible? My related code samples are below;
Code in the screen that I tried to call dialog box(homepage.dart):
void showCast() {
showDialog<void>(
context: context,
builder: (context){
return CastDialog();
}
);
}
#override
Widget build(BuildContext context) {
return FutureBuilder<Payload>(
...
...
...
child: GestureDetector(
child: Image.network(
snapshot.data
.movieCast[index]
.image != null
? "http://image.tmdb.org/t/p/w185" +
snapshot.data
.movieCast[index]
.image
: "http://image.tmdb.org/t/p/original/zUqyn3aQXTzeP1n8yd8Udt1twYA.jpg",
fit: BoxFit.contain,),
onTap: () async {
List<dynamic> castVar;
http.Response responseC = await http.get("http://lunedor.pythonanywhere.com/query?castid=${snapshot.data.movieCast[index].castID}&language=${AppLocalizations.of(context).translate('lan_code')}").timeout(const Duration(seconds: 10));
Map<String, dynamic> castV = jsonDecode(responseC.body);
castVar = castV['moviecastimages'];
print(castVar);
String nameC = (snapshot.data.movieCast[index]).toString();
String _movieCast = (snapshot.data.movieCast[index]).toString();
String _url = (snapshot.data.movieCast[index].castID).toString();
return
showCast();
},
),
Code for dialog(dialogs.dart):
class CastDialog extends StatefulWidget{
#override
_CastDialogState createState() => _CastDialogState();
}
class _CastDialogState extends State<CastDialog> {
String nameC;
String _movieCast;
String _url;
List castVar;
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return SimpleDialog(
title:
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(
width: 20,
height: 20,
child: GestureDetector(
onTap: () async{
http.Response responseB = await http.get("https://api.themoviedb.org/3/person/$_url?api_key=1b8cfaea32775f684a7baff93bb1a3fc&language=${AppLocalizations.of(context).translate('lan_code')}").timeout(const Duration(seconds: 10));
Map<String, dynamic> castCB = jsonDecode(responseB.body);
return showDialog(context: context,
builder: (context) {
return SimpleDialog(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(nameC),
SizedBox(
width: 20,
height: 20,
child: GestureDetector(
onTap: (){ Navigator.pop(context);},
child: Icon(Icons.close)),
),
],
),
children: <Widget>[
Divider(
color: Colors.black.withOpacity(0.5),
height: 5,
thickness: 3,
),
Wrap(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: Text(castCB['biography'], style: TextStyle(fontSize: 14),),
),
),
],
),],
);
});
},
child: Icon(Icons.info)),
),
Text(_movieCast),
SizedBox(
width: 20,
height: 20,
child: GestureDetector(
onTap: (){ Navigator.pop(context);},
child: Icon(Icons.close)),
),
],
),
shape: RoundedRectangleBorder(borderRadius: new BorderRadius.circular(15.0)),
children: <Widget>[
Divider(
color: Colors.black.withOpacity(0.5),
height: 5,
thickness: 3,
),
Material(
child: Container(
width: 400,
height: 600,
child: new GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 1.5 /
2.5,
),
itemCount: castVar.length,
itemBuilder: (context, index) {
return Column(
children: <
Widget>[
SizedBox(
height: 220,
child: Stack(
children: <Widget>[
Image.network(castVar[index]['poster'] != null ? "http://image.tmdb.org/t/p/w185" + castVar[index]['poster']
: "https://i.hizliresim.com/bbn0VB.jpg", fit: BoxFit.contain),
Container(
width: MediaQuery
.of(context)
.size
.width,
height: 220,
alignment: Alignment.bottomLeft,
padding: EdgeInsets.only(bottom: 5.0),
margin: const EdgeInsets.only(
left: 5.0),
child: new CircularPercentIndicator(
radius: 40.0,
lineWidth: 5.0,
percent: double.tryParse(
castVar[index]['vote'])/10,
center: Stack(
children: <Widget>[
Text(
castVar[index]['vote'],
style: TextStyle(
foreground: Paint()
..style = PaintingStyle.stroke
..strokeWidth = 3
..color = Colors.black,
),
),
new Text(castVar[index]['vote'],
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.amber,),),
],
),
progressColor: Colors.amber,
)
),],
),
),
Text(castVar[index]['title'], maxLines: 1,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.bold)
),
Text("(" + castVar[index]['year'] + ")", maxLines: 1,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.bold,),
)
],
);
}),
),
),
],
);
}
}