https://www.veed.io/view/a97effbf-7aad-4c0a-8fd7-8fce2be4808e?sharingWidget=true&panel=share
I hate how when I slide between screens the layout overlaps to the next screen before rendering what's supposed to be there. How do I fix this?
This is the code for the page:
class StallPage extends StatefulWidget {
final Stall stall;
const StallPage({super.key, required this.stall});
#override
State<StallPage> createState() => _StallPageState();
}
class _StallPageState extends State<StallPage> {
var selected = 0;
final pageController = PageController();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xff392850), //kBackground,
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CustomAppBar(
Icons.arrow_back_ios_outlined,
Icons.search_outlined,
leftCallback: () => Navigator.of(context).pop(),
rightCallback: () => Navigator.of(context).pushNamed(searchRoute),
),
StallInfo(
stall: widget.stall,
), //
FoodList(
selected,
(int index) {
setState(() {
selected = index;
});
pageController.jumpToPage(index);
},
widget.stall,
),
Expanded(
child: FoodListView(
selected,
(int index) {
setState(() {
selected = index;
});
},
pageController,
widget.stall,
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 25),
height: 60,
child: SmoothPageIndicator(
controller: pageController,
count: widget.stall.menu.length,
effect: CustomizableEffect(
dotDecoration: DotDecoration(
width: 8,
height: 8,
color: Colors.grey.withOpacity(0.5),
borderRadius: BorderRadius.circular(8),
),
activeDotDecoration: DotDecoration(
width: 10,
height: 10,
color: kBackground,
borderRadius: BorderRadius.circular(10),
dotBorder: const DotBorder(
color: kPrimaryColor,
padding: 2,
width: 2,
),
),
),
onDotClicked: (index) => pageController.jumpToPage(index),
),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
backgroundColor: kPrimaryColor,
elevation: 2,
child: IconButton(
icon: Icon(Icons.shopping_cart_outlined),
color: Colors.black,
onPressed: () {
Navigator.of(context).pushNamed(cartRoute);
context.read<TotalPrice>().update();
},
),
),
);
}
}
FoodList: //I'm positive the problems somewhere here
class FoodList extends StatelessWidget {
final int selected;
final Function callback;
final Stall stall;
const FoodList(this.selected, this.callback, this.stall);
#override
Widget build(BuildContext context) {
final category = stall.menu.keys.toList();
return Container(
height: 100,
padding: const EdgeInsets.symmetric(vertical: 30),
child: ListView.separated(
padding: const EdgeInsets.symmetric(horizontal: 25),
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) => GestureDetector(
onTap: () => callback(index),
child: Container(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: selected == index ? kPrimaryColor : Colors.white,
),
child: Text(
category[index],
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
),
),
separatorBuilder: (_, index) => const SizedBox(width: 20),
itemCount: category.length,
),
);
}
}
FoodListView:
class FoodListView extends StatelessWidget {
final int selected;
final Function callback;
final PageController pageController;
final Stall stall;
const FoodListView(
this.selected,
this.callback,
this.pageController,
this.stall,
);
#override
Widget build(BuildContext context) {
final category = stall.menu.keys.toList();
return Container(
padding: EdgeInsets.symmetric(horizontal: 25),
child: PageView(
controller: pageController,
onPageChanged: (index) => callback(index),
children: category
.map((e) => ListView.separated(
padding: EdgeInsets.zero,
itemBuilder: (context, index) => GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => DetailPage(
stall.menu[category[selected]]![index],
),
),
);
},
child:
FoodItem(stall.menu[category[selected]]![index])),
separatorBuilder: (_, index) => const SizedBox(height: 15),
itemCount: stall.menu[category[selected]]!.length,
))
.toList()),
);
}
}
Stall:
class Stall {
String name;
String label;
String logoUrl;
String desc;
num score;
Map<String, List<Food>> menu;
Stall(
this.name,
this.label,
this.logoUrl,
this.desc,
this.score,
this.menu,
);
}
No need to pass selected to FoodListView and also FoodListView will be like following
class FoodListView extends StatelessWidget {
final Function callback;
final PageController pageController;
final Stall stall;
const FoodListView(
this.callback,
this.pageController,
this.stall,
);
#override
Widget build(BuildContext context) {
final menuList = stall.menu.values.toList();
return Container(
padding: EdgeInsets.symmetric(horizontal: 25),
child: PageView.builder(
controller: pageController,
onPageChanged: (index) => callback(index),
itemCount: menuList.length,
itemBuilder: (context, menuIndex) {
final menu = menuList[menuIndex];
return ListView.separated(
padding: EdgeInsets.zero,
itemBuilder: (context, index) => GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => DetailPage(
menu[index],
),
),
);
},
child: FoodItem(menu[index])),
separatorBuilder: (_, index) => const SizedBox(height: 15),
itemCount: menu.length,
);
},
));
}
}
Remove selected where you call FoodListView
Related
my ImagePaths function is supposed to return a list and I want to access that list in my Carousel but I can't seem to figure out how to do so.. The ".lenght" and the [index] are not working and I'm not sur how to "call" them in flutter. Can someone help me please :)
here is my code for the ImagePaths function :
Future<List<String>> getImagePaths() async { final Map<String, dynamic> assets = jsonDecode(await rootBundle.loadString('AssetManifest.json')); return assets.keys .where((String key) => key.contains('photos/')) .where((String key) => key.contains('.JPG')) .toList(); }
And here is my code for my carousel :
class MyWidget extends StatefulWidget {
const MyWidget({super.key});
#override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
int activeIndex = 0;
final controller = CarouselController();
final imgList = ImagePaths();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("carousel try"),
centerTitle: true,
),
body: Center(
child: Column(
children: [
const SizedBox(
height: 32,
),
CarouselSlider.builder(
carouselController: controller,
options: CarouselOptions(
height: 500,
enlargeCenterPage: true,
onPageChanged: (index, reason) {
setState(() {
activeIndex = index;
});
}),
itemCount: imgList.length,
itemBuilder: (context, index, realIndex) {
final urlImage = imgList[index];
return buildImage(urlImage, index);
},
),
const SizedBox(
height: 32,
),
buildButtons()
],
),
),
);
}
Widget buildImage(String urlImage, int index) {
return Container(
margin: const EdgeInsets.symmetric(horizontal: 12),
color: Colors.grey,
child: Image.network(
urlImage,
fit: BoxFit.cover,
),
);
}
Widget buildButtons({bool stretch = false}) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12),
),
onPressed: () {
controller.previousPage(
duration: const Duration(milliseconds: 500));
},
child: const Icon(Icons.arrow_back, size: 32),
),
stretch
? const Spacer()
: const SizedBox(
width: 32,
),
ElevatedButton(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12),
),
onPressed: () {
controller.nextPage(duration: const Duration(milliseconds: 500));
},
child: const Icon(Icons.arrow_forward, size: 32),
),
stretch
? const Spacer()
: const SizedBox(
width: 32,
),
],
);
}
}
In my page I have to open dialog and in that dialog we have to show listview of data. Once the user click any item in listview he have to show the item data to listview. I am using callback here. Can any one tell me how to pass the data to page (Text widget) .
code:
class PosSettingsPage extends StatefulWidget {
const PosSettingsPage({Key? key}) : super(key: key);
#override
State<StatefulWidget> createState() => _PosSettingPageState();
}
class _PosSettingPageState extends State<PosSettingsPage> {
#override
Widget build(BuildContext context) {
printerTerminalType = _documentService.hardware.paymentTerminalType.name;
return Scaffold(
........
........
InkWell(
onTap: () {
**openAppDialog(
context,
_buildContentDialog(
context, PaymentTerminalTypeName));**
},
child: Container(
margin: const EdgeInsets.only(left: 25),
width: 300,
decoration: BoxDecoration(
border: Border.all(color: Colors.white),
borderRadius: const BorderRadius.all(
Radius.circular(5),
),
),
child: Padding(
padding: const EdgeInsets.all(10.0),
/// This Text widget
child: Text(
printerTerminalType,
style: Theme.of(context)
.textTheme
.headline1
?.copyWith(color: Colors.white),
),
),
),
),
}
AppDialog _buildContentDialog(BuildContext context, List<String> data) {
return AppDialog(
dataList: data,
onValueChanged: (text) {
/// I want to append this "text" to text widget
},
);
}
}
class AppDialog extends StatefulWidget {
List<String> dataList = [];
final ValueChanged<String> onValueChanged;
AppDialog({
Key? key,
required this.dataList,
required this.onValueChanged,
}) : super(key: key);
#override
State<StatefulWidget> createState() => _AppDialogState();
}
class _AppDialogState extends State<AppDialog> {
TextEditingController editingController = TextEditingController();
final List<String>? items = [];
#override
void initState() {
items?.addAll(widget.dataList);
super.initState();
}
void filterSearchResults(String query) {
List<String> dummySearchList = <String>[];
dummySearchList.addAll(widget.dataList);
if (query.isNotEmpty) {
List<String> dummyListData = <String>[];
for (var item in dummySearchList) {
if (item.contains(query)) {
dummyListData.add(item);
}
}
setState(() {
items?.clear();
items?.addAll(dummyListData);
});
return;
} else {
setState(() {
items?.clear();
items?.addAll(widget.dataList);
});
}
}
#override
Widget build(BuildContext context) {
return Dialog(
child: SizedBox(
width: 500,
height: 400,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
onChanged: (value) {
filterSearchResults(value);
},
controller: editingController,
decoration: const InputDecoration(
hintText: "Search list",
hintStyle: TextStyle(fontSize: 12.0, color: Colors.white24),
),
),
),
Expanded(
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: ListView.builder(
shrinkWrap: true,
itemCount: items?.length,
itemBuilder: (context, index) {
return ListTile(
onTap: (){
widget.onValueChanged.call(items![index].toString());
Navigator.pop(context);
},
title: Text(items![index],style: Theme.of(context).textTheme.headline5,),
);
},
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
margin: const EdgeInsets.all(10.0),
width: double.infinity,
child: Center(
child: Text(
'Cancel',
style: Theme.of(context).textTheme.subtitle1,
),
),
),
)
],
),
),
);
}
}
Future<void> openAppDialog(BuildContext context, Widget appDialog,) async {
return showDialog<dynamic>(
context: context,
builder: (BuildContext context) {
return appDialog;
},
);
}
Whenever I try to scroll, it auto scrolls back, behaving like it is the end of the list.
Here is the screen:
import 'package:flutter/material.dart';
import 'package:move_me_delivery/components/search_field.dart';
import 'package:move_me_delivery/data/styles.dart';
class SearchScreen extends StatefulWidget {
const SearchScreen({Key? key}) : super(key: key);
#override
_SearchScreenState createState() => _SearchScreenState();
}
class _SearchScreenState extends State<SearchScreen> {
final _focusNode = FocusNode();
#override
void initState() {
super.initState();
_focusNode.requestFocus();
}
#override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: SafeArea(
child: Scaffold(
backgroundColor: Colors.white,
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 32),
child: ListView(
children: [
SearchTextField(
focus: _focusNode,
onCancel: (){
FocusScope.of(context).unfocus();
Navigator.pop(context);
}),
SizedBox(height: 15,),
ListView(
shrinkWrap: true,
children: [
Text("Recent requests", style: AppTextStyles.header1,),
SizedBox(height: 15,),
ListView.separated(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
itemBuilder: (BuildContext context, int index){
return Padding(
padding: const EdgeInsets.symmetric(vertical: 5),
child: Text("BBQ", style: AppTextStyles.body1,),
);
}, separatorBuilder: (BuildContext context, int index){
return Divider();
}, itemCount: 5),
SizedBox(height: 15,),
Text("Restaurants nearby", style: AppTextStyles.header1,),
ListView.separated(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
itemBuilder: (BuildContext context, int index){
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: Text("BBQ", style: AppTextStyles.body1,),
);
}, separatorBuilder: (BuildContext context, int index){
return Divider();
}, itemCount: 16),
],
),
],
),
),
),
),
);
}
}
I need to get the id from quizCatId in the category() class to QuizTile() can someone tell me how to solve the issue...
my need is to call subcategory data from firestore which has an quizid and quizcatid and there I have my quizdata so I need to pass both the id to the quizdata to get data from the firestore
class Category extends StatefulWidget {
String quizCatId;
Category(this.quizCatId);
#override
_CategoryState createState() => _CategoryState();
}
class _CategoryState extends State<Category> {
Stream quizStream;
DatabaseService databaseService = new DatabaseService();
Widget quizList() {
return Container(
child: Column(
children: [
StreamBuilder(
stream: quizStream,
builder: (context, snapshot) {
return snapshot.data == null
? Container()
: ListView.builder(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
return QuizTile(
noOfQuestions: snapshot.data.documents.length,
imageUrl:
snapshot.data.documents[index].data['quizImgUrl'],
title:
snapshot.data.documents[index].data['quizTitle'],
desc: snapshot.data.documents[index].data['quizDesc'],
quizid: snapshot.data.documents[index].data["quizId"],
);
});
},
),
],
),
);
}
#override
void initState() {
databaseService.getCatData(widget.quizCatId).then((value) {
quizStream = value;
setState(() {});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
centerTitle: true,
title: appBar(context),
brightness: Brightness.light,
elevation: 0.0,
backgroundColor: Colors.transparent,
//brightness: Brightness.li,
),
body: SingleChildScrollView(child: quizList()),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => CreateCategoryQuiz()));
},
),
);
}
}
class QuizTile extends StatelessWidget {
final String imageUrl, title, quizid, desc, quizcatId;
final int noOfQuestions;
QuizTile({
#required this.title,
#required this.imageUrl,
#required this.desc,
#required this.quizid,
#required this.noOfQuestions,
#required this.quizcatId,
});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PlayQuiz(quizid, quizcatId)));
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 14),
height: 150,
margin: EdgeInsets.only(bottom: 8),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Stack(
children: [
Image.network(
imageUrl,
fit: BoxFit.cover,
width: MediaQuery.of(context).size.width,
),
Container(
color: Colors.black26,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
title,
style: TextStyle(
fontSize: 18,
color: Colors.white,
fontWeight: FontWeight.w500),
),
SizedBox(
height: 4,
),
Text(
desc,
style: TextStyle(
fontSize: 13,
color: Colors.white,
fontWeight: FontWeight.w500),
)
],
),
),
)
],
),
),
),
);
}
}
Hey you have acces to statefulWidget properties form state class by windget property.
All you have to do is ad new parameter in QuizTile constructor and call them
QuizTile(
noOfQuestions: snapshot.data.documents.length,
imageUrl:
snapshot.data.documents[index].data['quizImgUrl'],
title:
snapshot.data.documents[index].data['quizTitle'],
desc: snapshot.data.documents[index].data['quizDesc'],
quizid: snapshot.data.documents[index].data["quizId"],
quizCatId: widget.quizCatId
);
I am trying to build a GridView list. This all works when I create a simple list of 'players', but now I am trying to persist data using sqflite and I am getting an error:
Error: The argument type 'Future' can't be assigned to the parameter type 'int'
This is my list builder widget:
class PlayerList extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Consumer<PlayerData>(
builder: (context, playerData, child) {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 20,
crossAxisSpacing: 20,
),
itemCount: playerData.playerCount,
itemBuilder: (BuildContext context, int index) {
final player = playerData.players[index];
return RawMaterialButton(
fillColor: Color(0x991c5597),
elevation: 20,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
CircleAvatar(
backgroundColor: Colors.tealAccent,
radius: 30,
child: Icon(
Icons.star,
color: Color(0xFF16377a),
size: 30,
),
),
Text(player.name, style: smallTitleText),
],
),
),
onPressed: () {
playerData.makeActive(player.name);
playerData.printList();
Navigator.pushNamed(context, PlayScreen.id);
});
});
},
);
}
}
This is how I get the list count:
Future<int> get playerCount async {
final Database db = await getDBConnector();
final List<Map<String, dynamic>> maps = await db.query('players');
if (maps.length != null) {
return maps.length;
} else { return 0;}
}
Wrap your GridView with FutureBuilder
Something like this
return FutureBuilder(
future: playerData.playerCount,
builder : (context,snapshot){
if(!(snapshot.hasData)){
return Container();
}
else{
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 20,
crossAxisSpacing: 20,
),
itemCount: snapshot.data,
itemBuilder: (BuildContext context, int index) {
final player = playerData.players[index];
return RawMaterialButton(
fillColor: Color(0x991c5597),
elevation: 20,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
CircleAvatar(
backgroundColor: Colors.tealAccent,
radius: 30,
child: Icon(
Icons.star,
color: Color(0xFF16377a),
size: 30,
),
),
Text(player.name, style: smallTitleText),
],
),
),
onPressed: () {
playerData.makeActive(player.name);
playerData.printList();
Navigator.pushNamed(context, PlayScreen.id);
});
});
},
);
}
}
);
The error is appearing because playerCount isn't returning int its returning a Future. First, you have to change your class to a stateful widget and load your data as shown below
class PlayerList extends StatefulWidget {
#override
_PlayerListState createState() => _PlayerListState();
}
class _PlayerListState extends State<PlayerList> {
int count;
#override
void initState() {
super.initState();
loadPlayerCount();
}
#override
Widget build(BuildContext context) {
return Consumer<PlayerData>(
builder: (context, playerData, child) {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 20,
crossAxisSpacing: 20,
),
itemCount: count??0,
itemBuilder: (BuildContext context, int index) {
final player = playerData.players[index];
return RawMaterialButton(
fillColor: Color(0x991c5597),
elevation: 20,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
CircleAvatar(
backgroundColor: Colors.tealAccent,
radius: 30,
child: Icon(
Icons.star,
color: Color(0xFF16377a),
size: 30,
),
),
Text(player.name, style: smallTitleText),
],
),
),
onPressed: () {
playerData.makeActive(player.name);
playerData.printList();
Navigator.pushNamed(context, PlayScreen.id);
});
});
},
);
}
void loadPlayerCount() async{
final Database db = await getDBConnector();
final List<Map<String, dynamic>> maps = await db.query('players');
if (maps.length != null) {
setState(() {
this.count = maps.length;
});
} else {
setState(() {
this.count = 0;
});
}
}
}