flutter PageView onPageChanged with setstate - flutter

i am working with PageView but if i swipe to change it will change the page But if i put onPageChanged to setState for me to get to current index it will not change the page.
here is my code
int _indicatorsPages = 0;
final PageController controller =
PageController(initialPage: 0);
change(int page) {
setState(() {
_indicatorsPages = page;
}); }
code from build
Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
leading: Row(
children: [
SizedBox(
width: 10,
),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => SettingsFMC(),
),
);
},
child: Container(
height: 40,
width: 40,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.5),
spreadRadius: 1, blurRadius: 2,
offset: Offset(0, 3), // i change position of shadow
),
],
),
child: Center(
child: Icon(
FontAwesomeIcons.slidersH,
size: 20,
color: Colors.black,
)),
),
),
],
),
elevation: 0,
backgroundColor: Colors.transparent,
actions: [
GestureDetector(
onTap: () async {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Actitvities(),
),
);
final doc = await firestore
.collection('feeds')
.doc(auth.currentUser.uid)
.collection('feedsItems')
.get();
if (doc.docs.isNotEmpty) {
firestore
.collection('feeds')
.doc(auth.currentUser.uid)
.collection('feedsItems')
.get()
.then((value) {
value.docs.forEach((doc) {
doc.reference.update({'seen': true});
});
});
}
},
child: Container(
height: 40,
width: 40,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.5),
spreadRadius: 1, blurRadius: 2,
offset: Offset(0, 3), // i change position of shadow
),
],
),
child: StreamBuilder(
stream: firestore
.collection('feeds')
.doc(auth.currentUser.uid)
.collection('feedsItems')
.where('seen', isEqualTo: false)
.snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: Icon(
Icons.notifications_none_outlined,
size: 20,
color: Colors.black,
));
}
if (snapshot.data.docs.isEmpty) {
return Center(
child: Icon(
Icons.notifications_none_outlined,
size: 20,
color: Colors.black,
));
}
return Badge(
animationType: BadgeAnimationType.scale,
badgeContent: Text('${snapshot.data.docs.length}'),
position: BadgePosition.topStart(),
showBadge: true,
child: Center(
child: Icon(
Icons.notifications_none_outlined,
size: 20,
color: Colors.black,
)),
);
}),
),
),
SizedBox(
width: 10,
),
],
),
extendBodyBehindAppBar: true,
body: userProfileLoading
? Center(
child: CircularProgressIndicator(),
)
: Stack(
children: [
Container(
height: MediaQuery.of(context).size.height / 1.6,
child: StreamBuilder(
stream: firestore
.collection('Image')
.doc(widget.viewId)
.collection('Photos')
.orderBy('timestap', descending: false)
.snapshots(),
builder: (context, AsyncSnapshot snapshot) {
int idx = 0;
List<Widget> list = [];
if (snapshot.connectionState ==
ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
}
if (!snapshot.hasData) {
return Center(
child: Text("No image Found, Add images"),
);
} else {
if (snapshot.hasError) {
return Center(child: Text("fetch error"));
} else {
for (int i = 0;
i < snapshot.data.docs.length;
i++) {
// print('the lent of the document is $idx');
list.add(
FullScreenWidget(
child: Hero(
tag: "customTag",
child: Image.network(
snapshot.data.docs[idx]
.data()['picture'],
fit: BoxFit.cover,
),
),
),
);
idx++;
}
return Stack(
children: [
PageView(
key: _key,
scrollDirection: Axis.horizontal,
controller: controller,
onPageChanged: change,
// onImageChange: (pre, current) {
// print('this current : $current');
// setState(() {
// indicatorsPages = current;
// });
// },
// boxFit: BoxFit.cover,
// autoplay: false,
// animationCurve: Curves.fastOutSlowIn,
// animationDuration:
// Duration(milliseconds: 1000),
// dotIncreasedColor: Colors.orange,
// dotBgColor: Colors.transparent,
// dotPosition: DotPosition.bottomCenter,
// dotVerticalPadding:
// MediaQuery.of(context).size.height / 15,
//showIndicator: false,
// indicatorBgPadding: 7.0,
children: list,
),
Positioned(
right:
MediaQuery.of(context).size.width / 2,
bottom: 75,
child: Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(20),
color: Colors.white),
child: indicat.DotsIndicator(
dotsCount: list.length,
position: _indicatorsPages.toDouble(),
decorator: DotsDecorator(
color:
Colors.grey, // Inactive color
activeColor: Colors.black,
),
)),
)
],
);
}
}
}),
),

You are wrong. When you use pageView, it will call onPageChnaged function after page changed. If you want to change page programmatically, you should use pageView.animateToPage() function.

import 'package:flutter/material.dart';
class OnBoarding extends StatefulWidget {
#override
_OnBoardingState createState() => _OnBoardingState();
}
class _OnBoardingState extends State<OnBoarding> {
PageController controller;
int currentIndex = 0;
#override
void initState() {
controller = PageController();
super.initState();
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blueAccent[200],
body: Stack(
children: [
PageView(
onPageChanged: onchahged,
controller: controller,
children: [
Container(
child: Image.asset('assets/fierceninja.png'),
),
Container(
child: Image.asset('assets/ninja.png'),
),
Container(
child: Image.asset('assets/ninjahead.jpg'),
),
],
),
],
),
);
}
onchahged(int index) {
setState(() {
currentIndex = index;
});
}
}
Here's a complete example.

Related

Infinite Scrolling in GridView.builder

I am Building a flutter e-commerce application. And in the Categories section. There are so much data so I want to implement pagination through infinite scrolling.
This is what I am trying to do, CatHome object is the category either men or women etc.
the code is resulting in pagination, but everytime it is building another page, not infinite scroll. so i cannot access previosly loaded data
class CategoryDetail extends StatefulWidget {
CatHome catHome;
CategoryDetail(this.catHome);
#override
_CategoryDetailstate createState() => _CategoryDetailstate(catHome);
}
class _CategoryDetailstate extends State<CategoryDetail> {
List<FutureOr> _items = [];
CatHome catHome;
_CategoryDetailstate(this.catHome);
var _currentPage = 1;
ScrollController scroll = ScrollController();
var _hasMore = true;
#override
void initState() {
super.initState();
scroll.addListener(() {
if (scroll.position.pixels == scroll.position.maxScrollExtent) {
_fetchMore();
}
});
}
#override
void dispose() {
scroll.dispose();
super.dispose();
}
void _fetchMore() async {
if (_hasMore) {
setState(() {
_currentPage++;
});
var newItems =
await new catitems_api().fetchdeails(catHome, _currentPage);
if (newItems.isEmpty) {
setState(() {
_hasMore = false;
});
} else {
setState(() {
this._items.addAll(newItems);
});
}
}
}
/// Component widget in flashSale layout
Widget build(BuildContext context) {
var data = EasyLocalizationProvider.of(context).data;
return EasyLocalizationProvider(
data: data,
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
AppLocalizations.of(context).tr('Category'),
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 17.0,
color: Colors.black54,
fontFamily: "Gotik"),
),
centerTitle: true,
iconTheme: IconThemeData(color: Color(0xFF6991C7)),
elevation: 0.0,
),
body: SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
Container(
key: Key(UniqueKey().toString()),
height: MediaQuery.of(context).size.height * 0.8,
child: FutureBuilder<List<dynamic>>(
future: catitems_api().fetchdeails(catHome, _currentPage),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
return GridView.builder(
controller: scroll,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 0.7,
mainAxisSpacing: 8.0,
crossAxisSpacing: 8.0,
),
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
CategoryItems items = snapshot.data[index];
return InkWell(
onTap: () {
new productDet_api()
.fetchdeails(items.id)
.then((itemList) {
Navigator.of(context).push(PageRouteBuilder(
pageBuilder: (_, __, ___) =>
new detailProduk(itemList.first),
transitionDuration:
Duration(milliseconds: 950),
transitionsBuilder: (_flashSaleState,
Animation<double> animation,
__,
Widget child) {
return Opacity(
opacity: animation.value,
child: child,
);
}));
});
},
child: Container(
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black12.withOpacity(0.1),
spreadRadius: 0.2,
blurRadius: 5.0,
offset: Offset(0.0, 2.0))
]),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.network(
items.image,
width: 150.0,
height: 150.0,
fit: BoxFit.cover,
),
SizedBox(
height: 10.0,
),
Text(
items.name,
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 14.0,
color: Colors.black),
),
SizedBox(
height: 5.0,
),
Text(
"\$" + items.price.toString(),
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 14.0,
color: Colors.black),
),
],
),
),
);
},
);
},
),
),
],
),
),
),
),
);
}
}

How to get back a value from a customly created widget in Flutter

I am showing a showModalBottomSheet using a function. I want that as soon as it closes, value of a variable should change. I wanted to change value of two variables, but I am not able to change for even one. Please help me with this. I tried to make my own onChanged and also tried to return the value using function, but nothing happens.
This is the function, please scroll to the last of it and check out the onTap function and return.
String showChapterSelectionSheet(
BuildContext context,
List<ChapterModel> chapter_list,
String chapter_name,
final Function(String) onChapterChanged) {
String retValue = chapter_name;
showModalBottomSheet(
context: context,
backgroundColor: Colors.transparent,
elevation: 0,
isScrollControlled: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20), topRight: Radius.circular(20)),
),
builder: (context) {
return StatefulBuilder(
builder: (BuildContext context,
StateSetter setState /*You can rename this!*/) {
return makeDismissible(
context,
child: DraggableScrollableSheet(
initialChildSize: 0.81,
minChildSize: 0.5,
maxChildSize: 0.81,
builder: (_, controller) => Container(
padding: EdgeInsets.all(getProportionateScreenWidth(25)),
height: getProportionateScreenWidth(600),
decoration: BoxDecoration(
color: backgroundColor2,
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
child: Column(
children: [
Padding(
padding: EdgeInsets.only(
top: getProportionateScreenHeight(32),
bottom: getProportionateScreenHeight(16)),
child: Text(
AppLocalizations.of(context)!.chapters,
style: Theme.of(context)
.textTheme
.headline2!
.apply(color: Colors.white),
),
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
controller: controller,
itemCount: chapter_list.length,
itemBuilder: (_, index) {
return GestureDetector(
child: Padding(
padding: EdgeInsets.only(
top: getProportionateScreenHeight(8)),
child: Card(
child: Container(
height: getProportionateScreenHeight(56),
width: getProportionateScreenWidth(341),
decoration: BoxDecoration(
border: Border.all(color: cardColor),
color: chapter_list[index].chapter_name! ==
chapter_name
? backgroundColor
: cardColor,
),
child: Padding(
padding: EdgeInsets.all(0),
child: Center(
child: Row(
children: [
Container(
width:
getProportionateScreenWidth(
32),
child: chapter_list[index]
.chapter_name! ==
chapter_name
? Icon(
Icons.check,
color: brandYellow,
)
: SizedBox()),
Text(
"Chapter ${chapter_list[index].position!}: ",
style: Theme.of(context)
.textTheme
.bodyText2!
.apply(color: brandYellow),
),
Expanded(
child: Text(
chapter_list[index]
.chapter_name!,
style: Theme.of(context)
.textTheme
.bodyText2!
.apply(
color: chapter_list[
index]
.chapter_name! ==
chapter_name
? tertiaryTextColor
: primaryTextColor)),
),
],
),
),
),
),
),
),
onTap: () {
onChapterChanged(chapter_list[index].chapter_name!);
setState(() {
retValue = chapter_list[index].chapter_name!;
});
Navigator.pop(context);
},
);
},
),
),
],
),
),
),
);
},
);
},
);
return retValue;
}
And I am accessing it here -
return InkWell(
onTap: () async {
if(dataList.isNotEmpty) {
chapterName.value = showChapterSelectionSheet(
context,dataList,chapterName.value,(val) {
setState(() {
chapterName.value = val;
print("Val is - $val");
});
}
);
}
},
child: .....
);
In the above InkWell, the print statement is working fine but value is not changing.
And I want to update and use the value here -
child: ValueListenableBuilder(
valueListenable: chapterName,
builder: (context, String val, Widget? child) {
return Text(
val,
style: TextStyle(
color: Colors.white,
fontSize: 15,
),
);
},
),
It is possible you are just missing await before await showModalBottomSheet(..).
You can follow this simplified snippet.
class BVChange extends StatefulWidget {
const BVChange({Key? key}) : super(key: key);
#override
State<BVChange> createState() => _BVChangeState();
}
class _BVChangeState extends State<BVChange> {
String var1 = "Old", var2 = "old1";
Future<String> _showDialog(String v) async {
double _sliderValue = 0.0;
await showModalBottomSheet(
context: context,
builder: (_) {
return StatefulBuilder(
builder: (context, sbSate) => Column(
children: [
Text(_sliderValue.toString()),
Slider(
value: _sliderValue,
onChanged: (sval) {
sbSate(() {
_sliderValue = sval;
});
}),
],
),
);
});
return _sliderValue.toString();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
GestureDetector(
onTap: () async {
final data = await _showDialog(var1);
setState(() {
var1 = data;
});
},
child: Text("var1 : $var1")),
GestureDetector(
onTap: () async {
final data = await _showDialog(var2);
setState(() {
var2 = data;
});
},
child: Text("var 2 : $var2"),
),
],
),
);
}
}

no material widget found flutter

i am trying to access this controller but i don't know why it crashes. as a mistake he gives me that:
no material widget found
iconButtonwidget require a material widget
is a simple view showing the map with various saved points
do I initialize the view badly?
Can anyone tell me what am I wrong?
this is the code I use
class MapTab extends StatefulWidget {
#override
_MapTabState createState() => _MapTabState();
}
class _MapTabState extends State<MapTab> {
Size _size;
MapboxMapController _mapController;
StreamController<Restaurant> _bottomCardStreamController;
_onMapCreated(MapboxMapController controller) {
_mapController = controller;
contentManager.getMerchants().then(
(restaurants) => restaurants.forEach(
(restaurant) => controller.addSymbol(
SymbolOptions(
geometry: LatLng(double.parse(restaurant.coordinates.lat),
double.parse(restaurant.coordinates.long)),
iconImage: "assets/images/map_pin.png",
),
restaurant.toJson(),
),
),
);
controller.onSymbolTapped.add((symbol) async {
Restaurant restaurant = Restaurant.fromJson(symbol.data);
_toggleBottomCard(restaurant);
});
_bottomCardStreamController.stream.listen((restaurant) {
if (restaurant == null) return;
List<CameraUpdate> updates = [
CameraUpdate.zoomTo(15),
CameraUpdate.newLatLng(LatLng(
double.parse(restaurant.coordinates.lat),
double.parse(restaurant.coordinates.long),
)),
];
updates
.forEach((element) async => await controller.animateCamera(element));
});
}
_toggleBottomCard(Restaurant data) {
_bottomCardStreamController.sink.add(data);
}
#override
void initState() {
super.initState();
_bottomCardStreamController = StreamController<Restaurant>.broadcast();
}
#override
void dispose() {
_bottomCardStreamController.close();
super.dispose();
}
#override
Widget build(BuildContext context) {
_size = MediaQuery.of(context).size;
return Stack(
alignment: AlignmentDirectional.center,
children: [
FutureBuilder<Position>(
future: PositionService.getCurrentPosition(),
builder: (context, AsyncSnapshot<Position> positionSnap) {
if (positionSnap.hasError)
return Center(
child: Text(localization.err_localization),
);
if (positionSnap.connectionState != ConnectionState.done)
return Container(
child: Center(
child: CircularProgressIndicator(valueColor: new AlwaysStoppedAnimation<Color>(appColors.yellow)),
),
);
var data = positionSnap.data;
var latLng = LatLng(data.latitude, data.longitude);
return FutureBuilder<String>(
future: contentManager.getMapBoxKey(),
builder: (context, tokenSnap) {
if (tokenSnap.hasError)
return Container(
child: Center(
child: Text(localization.err_mapbox_key),
),
);
if (tokenSnap.connectionState != ConnectionState.done)
return Container(
child: Center(
child: CircularProgressIndicator(valueColor: new AlwaysStoppedAnimation<Color>(appColors.yellow)),
),
);
return Container(
height: _size.height,
width: _size.width,
child: MapboxMap(
rotateGesturesEnabled: false,
myLocationEnabled: true,
onStyleLoadedCallback: () {},
zoomGesturesEnabled: true,
onMapClick: (_, __) {
// fa scomparire la bottomCard
_bottomCardStreamController.sink.add(null);
},
accessToken: tokenSnap.data,
onMapCreated: _onMapCreated,
compassEnabled: false,
initialCameraPosition: CameraPosition(
target: latLng,
zoom: 15,
bearing: 0,
tilt: 0,
),
),
);
});
}),
Positioned(
bottom: 10,
right: 10,
height: 50,
width: 50,
child: GestureDetector(
child: Container(
decoration: BoxDecoration(
color: Color.fromARGB(255, 255, 255, 255),
shape: BoxShape.circle,
),
child: Icon(Icons.my_location),
),
onTap: () async {
var position = await PositionService.getCurrentPosition();
var latLng = LatLng(position.latitude, position.longitude);
_mapController.animateCamera(CameraUpdate.newLatLng(latLng));
},
),
),
Positioned(
top: 10,
left: 0,
width: _size.width,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: Icon(
Icons.list,
),
onPressed: () {},
),
Flexible(
child: GestureDetector(
onTap: () async {
await showSearch<Restaurant>(
context: context,
delegate: CustomSearchDelegate(),
query: "",
).then(
(value) => _bottomCardStreamController.sink.add(value),
);
},
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
),
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 3,
vertical: 2,
),
child: TextField(
enabled: false,
decoration: InputDecoration(
icon: Icon(
Icons.search,
color: Colors.grey,
),
hintText: localization.find,
border: InputBorder.none,
),
),
),
),
),
),
IconButton(
icon: Icon(
Icons.filter_alt,
),
onPressed: () {},
)
],
),
),
Positioned(
bottom: 25,
width: _size.width,
child: StreamBuilder<Restaurant>(
stream: _bottomCardStreamController.stream,
builder: (_, snap) {
if (snap.data == null)
return Container();
else
return RestaurantMapCard(snap.data,
mapController: _mapController);
},
),
),
],
);
}
}
Wrap your root(first widget) with the MaterialApp widget.
Widget build(BuidContext context){
return MaterialApp(
home: Stack() // your stack and other widgets are here.
);
}

Flutter Firebase: not able update Database

I want to update my Collection with an NumberPicker in a Alert Dialog. I do not get any errors in code or from the emulator. When i press the button to update the code the terminal do not give any errors. Everything looks fine but for some reason i do not work. When you need more Information just leave a comment with what you excactly need. :)
import 'package:flutter/material.dart';
import 'package:numberpicker/numberpicker.dart';
import 'package:percent_indicator/circular_percent_indicator.dart';
import 'package:testapp/services/Services.dart';
import 'models/Goals.dart';
class Statistics extends StatefulWidget {
#override
_StatisticsState createState() => _StatisticsState();
}
class _StatisticsState extends State<Statistics> {
int _currentFirstValue = 1;
int totalFirst;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: 260,
child: StreamBuilder(
stream: FirestoreService().getGoals(),
builder: (context, AsyncSnapshot<List<Goal>> snapshot) {
if (snapshot.hasError || !snapshot.hasData) {
return Center(child: CircularProgressIndicator(
backgroundColor: Color(0XFF1954A1),
));
}
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 1,
itemBuilder: (BuildContext context, int index) {
// ignore: missing_return
Goal goal = snapshot.data[index];
return Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
margin: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
height: 230,
width: 350,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(10.0)),
boxShadow: [
BoxShadow(
color: Colors.grey[300],
offset: const Offset(0.5, 1),
blurRadius: 4.0,
spreadRadius: 0.1,
),
]),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Text('WeekGoals', style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.w500,
),),
SizedBox(width: 100),
SizedBox(
height: 20,
width: 87,
child: FlatButton(
child: Text('edit', style: TextStyle(
fontSize: 17,
color: Colors.yellow[700]
),),
onPressed: () {
return showDialog(
context: context,
barrierDismissible: true,
builder: (context) => AlertDialog(
content: Column(
children: <Widget>[
Text('weekly goals'),
NumberPicker.integer(
initialValue: _currentFirstValue,
minValue: 1,
maxValue: 100,
onChanged: (newGoal) => setState(() => {
_currentFirstValue = newGoal,
totalFirst = _currentFirstValue,
})
),
Row(
children: <Widget>[
RaisedButton(
child: Text('edit goals'),
onPressed: () async {
Goal goal = Goal(
weekActivityGoal: totalFirst,
);
await FirestoreService().updateGoal(goal);
Navigator.pop(context, false);
},
),
FlatButton(
child: Text('Close'),
onPressed: () {
Navigator.pop(context, false);
},
)
],
)
],
),
)
);
},
),
)
],
),
SizedBox(height: 10),
Row(
children: <Widget>[
Container(
padding: EdgeInsets.symmetric(horizontal: 17.5),
child: CircularPercentIndicator(
header: Text('activitys', style: TextStyle(
fontSize: 17,
),),
radius: 130,
progressColor: Colors.red,
lineWidth: 8,
backgroundColor: Colors.grey[200],
percent: goal.weekActivity*100/goal.weekActivityGoal,
center: Text('${goal.weekActivity}/${goal.weekActivityGoal}'),
),
),
],
),
],
),
),
],
);
});
}),
),
);
}
}
Here this has been helping a lot of people try i out might help you too.
StreamBuilder(
stream: Firestore.instance.collection('Hearings').snapshots(),
builder: (context, snapshot) {
if (snapshot.hasError) return Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('Select lot');
case ConnectionState.waiting:
return Text('Awaiting bids...');
case ConnectionState.active:
{
print('active');
return Text('${snapshot.data}');
}
case ConnectionState.done:
{
print('Done');
return _buildList(context, snapshot.data);
}
}
return null;
}),
));
}
Widget _buildList(BuildContext context, List<DocumentSnapshot> snapshot) {
return ListView(
padding: const EdgeInsets.only(top: 20.0),
children: snapshot.map((data) => _buildListItem(context, data)).toList(),
);
}
Widget _buildListItem(BuildContext context, DocumentSnapshot data) {
final record = Record.fromSnapshot(data);
return Padding(
key: ValueKey(record.name),
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(5.0),
),
child: ListTile(
title: Text(record.name),
trailing: Text(record.votes.toString()),
onTap: () => Firestore.instance.runTransaction((transaction) async {
final freshSnapshot = await transaction.get(record.reference);
final fresh = Record.fromSnapshot(freshSnapshot);
await transaction
.update(record.reference, {'votes': fresh.votes + 1});
}),
),
),
);
}
}
class Record {
final String name;
final int votes;
final DocumentReference reference;
Record.fromMap(Map<String, dynamic> map, {this.reference})
: assert(map['name'] != null),
assert(map['votes'] != null),
name = map['name'],
votes = map['votes'];
Record.fromSnapshot(DocumentSnapshot snapshot)
: this.fromMap(snapshot.data, reference: snapshot.reference);
#override
String toString() => "Record<$name:$votes>";
}
This is where the link this info came from.

Listtile Multi-select - Flutter Firestore Streambuilder

i need help to build a quiz app with flutter,
i use firestore for my data, and i want to add a multi choices question, so when a user tap on one choice, this one is highlighted, like this example
(i use this gif from another question, because i didn't know how to explain)
this is what i have for now
this is my code :
Widget _buildListItem(BuildContext context, DocumentSnapshot document) {
return ListTile(
title: Container(
margin: EdgeInsets.all(8.0),
padding: EdgeInsets.fromLTRB(210, 0.0, 0.0, 0.0),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Colors.pink[800], // set border color
width: 3.0), // set border width
borderRadius: BorderRadius.all(
Radius.circular(10.0)), // set rounded corner radius
boxShadow: [
BoxShadow(
blurRadius: 5,
color: Colors.black,
offset: Offset(0.5, 1))
] // make rounded corner of border
),
child: Row(
children: <Widget>[
Container(
child: Text(
document['rep'],
style: TextStyle(
fontSize: 50.0,
color: Colors.black,
),
),
)
]
),
),
onTap: () {
Firestore.instance.runTransaction(
(transaction) async {
DocumentSnapshot freshSnap =
await transaction.get(document.reference);
await transaction.update(freshSnap.reference, {
'votes': freshSnap['votes'] + 1,
});
});
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: StreamBuilder(
stream: Firestore.instance.collection('questions').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return const Text('Loading ...');
return ListView.builder(
padding: EdgeInsets.fromLTRB(50.0, 300.0, 50.0, 0.0),
itemExtent: 100.0,
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) =>
_buildListItem(context, snapshot.data.documents[index]),
);
}),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => new Home()));
},
child: Text("Home"),
),
);
}
thank you so much !
Wrap list tile with colored container :
itemBuilder: (context, index){
return Container(
color: isSelected[index] ? Colors.blue : null,
child: ListTile(title:'test'),
);
}
Change selection status when item is taped.
ListTile(
title: Text('test'),
selected: isSelected[index],
onTap: () {
setState(() {
isSelected[index] = !isSelected[index];
});
},
),
final List<bool> isSelected;
Try it on DartPad