I am making a flutter game where I have made a virtual keyboard using item builder and the keyboard contains some characters and these characters can be duplicate, when i select any character it is showed in containers above keyboard.
The problem is when I select any particular character, its duplicates are also selected but I want to treat duplicates as different. Refer image below
I think this is happening due to list.contains I used in my code, check the code below
import 'package:flutter/material.dart';
class PuzzlePage extends StatefulWidget {
int? id;
String? image1;
String? image2;
String? puzzleAnswer;
PuzzlePage(this.id, this.image1, this.image2, this.puzzleAnswer);
State<StatefulWidget> createState()
{
return _PuzzlePageState(this.id,this.image1,this.image2,this.puzzleAnswer);
}
//State<StatefulWidget> createState() {
// return _PuzzlePageState(this.id,this.image1,this.image2,this.puzzleAnswer);
}
class _PuzzlePageState extends State<PuzzlePage> {
int? id;
String? image1;
String? image2;
String? puzzleAnswer;
String? randomCharactersString="";
List selection=[];
_PuzzlePageState(this.id,this.image1,this.image2,this.puzzleAnswer);
void initState(){
super.initState();
}
#override
Widget build(BuildContext context) {
// deciding keyboard size
int? remainingLetters=26-(puzzleAnswer!.length);
int extraSize=(remainingLetters/2).ceil();
// print(extraSize);
// print(puzzleAnswer!.length);
int keyboardSize=puzzleAnswer!.length+extraSize;
if(randomCharactersString==""){
randomCharactersString = RandomString(extraSize, puzzleAnswer!);
}
String keyboardWords=randomCharactersString!+puzzleAnswer!;
// print(randomCharactersString);
print(selection);
// const answer= "cde";
//final id = ModalRoute.of(context)!.settings.arguments as Id ;
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title:Text("Guess the answer"),
centerTitle: true,
automaticallyImplyLeading: true,
leading: IconButton(icon:Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context);
},
),
),
body: Container(
color: Colors.white54,
child: Column(
children: [
SizedBox(
height: 60,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: 125,
width: 125,
child: Image(image: AssetImage("assets/images/$image1"))),
SizedBox(
width: 20,
),
Text("$randomCharactersString"),
Container(
height: 125,
width: 125,
child: Image(image: AssetImage("assets/images/$image2"))),
], ),
Column(
children: [
Container(
height: 250,
padding: EdgeInsets.all(10),
alignment: Alignment.center,
child: GridView.builder(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// childAspectRatio: 1,
crossAxisCount: 7,
crossAxisSpacing: 4,
mainAxisSpacing: 4,
),
itemCount: puzzleAnswer!.length,
shrinkWrap: true,
itemBuilder: (context , index){
print(index);
if(selection.length>index){
return InkWell(
onTap: () {
setState(() {
if (!selection.contains(keyboardWords[index])){
null;
}
else{
selection.remove(keyboardWords[index]);
}
});
},
child: Container(
padding: EdgeInsets.all(10),
alignment: Alignment.center,
decoration: BoxDecoration(
color:Colors.blue,
borderRadius: BorderRadius.circular(7)
),
child: Text(selection[index],
style: TextStyle(color: Colors.black)
),
),
);
}
else{
return Container(
padding: EdgeInsets.all(10),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(7)
),
child: Text("",
style: TextStyle(color: Colors.black)
),
);
}
}
)
),
],
),
Expanded(child:
Container(
// height: 300,
padding: EdgeInsets.all(10),
alignment: Alignment.center,
child: GridView.builder(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: 1,
crossAxisCount: 7,
crossAxisSpacing: 4,
mainAxisSpacing: 4,
),
itemCount: keyboardSize,
// shrinkWrap: true,
itemBuilder: (context , index)
{
return InkWell(
onTap:(){
setState(() {
if (!selection.contains(keyboardWords[index])){
selection.add(keyboardWords[index]);
}
else{
selection.remove(keyboardWords[index]);
}
}
);
},
child: Container(
padding:EdgeInsets.all(10),
alignment:Alignment.center,
decoration:BoxDecoration(
color:selection.contains(keyboardWords[index])?Colors.blueAccent:Colors.grey,
borderRadius:BorderRadius.circular(7)
),
child:Text(keyboardWords[index],
style:TextStyle(color:Colors.black)
),
),
);
// return ElevatedButton(
// style: ElevatedButton.styleFrom(
// primary: Colors.purple,
// // padding: EdgeInsets.symmetric(horizontal: 50, vertical: 20),
// textStyle: TextStyle(
// fontSize: 20,
// fontWeight: FontWeight.bold
// ),
// ),
// onPressed: null,
// child: Text("d"),
// );
}
)
),
),
],
),
),
),
);
}
}
RandomString(int strlen,String puzzleAnswer){
Random rnd = new Random();
String result = "";
const chars = "abcdefghijklmnopqrstuvwxyz";
for (var i = 0; i < strlen; i++) {
// if (!puzzleAnswer.contains(chars[i])) {
result += chars[rnd.nextInt(chars.length)];
// }
}
return result;
}
Here is the modified file, here it does not highlight the duplicates:
import 'dart:math';
import 'package:flutter/material.dart';
class PuzzlePage extends StatefulWidget {
int? id;
String? image1;
String? image2;
String? puzzleAnswer;
PuzzlePage(this.id, this.image1, this.image2, this.puzzleAnswer);
State<StatefulWidget> createState()
{
return _PuzzlePageState(this.id,this.image1,this.image2,this.puzzleAnswer);
}
//State<StatefulWidget> createState() {
// return _PuzzlePageState(this.id,this.image1,this.image2,this.puzzleAnswer);
}
class _PuzzlePageState extends State<PuzzlePage> {
int? id;
String? image1;
String? image2;
String? puzzleAnswer;
String? randomCharactersString="";
List<int> selection=[];
_PuzzlePageState(this.id,this.image1,this.image2,this.puzzleAnswer);
void initState(){
super.initState();
}
#override
Widget build(BuildContext context) {
// deciding keyboard size
int? remainingLetters=26-(puzzleAnswer!.length);
int extraSize=(remainingLetters/2).ceil();
// print(extraSize);
// print(puzzleAnswer!.length);
int keyboardSize=puzzleAnswer!.length+extraSize;
if(randomCharactersString==""){
randomCharactersString = RandomString(extraSize, puzzleAnswer!);
}
String keyboardWords=randomCharactersString!+puzzleAnswer!;
// print(randomCharactersString);
print(selection);
// const answer= "cde";
//final id = ModalRoute.of(context)!.settings.arguments as Id ;
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title:Text("Guess the answer"),
centerTitle: true,
automaticallyImplyLeading: true,
leading: IconButton(icon:Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context);
},
),
),
body: Container(
color: Colors.white54,
child: Column(
children: [
SizedBox(
height: 60,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: 125,
width: 125,
child: Image(image: AssetImage("assets/images/$image1"))),
SizedBox(
width: 20,
),
Text("$randomCharactersString"),
Container(
height: 125,
width: 125,
child: Image(image: AssetImage("assets/images/$image2"))),
], ),
Column(
children: [
Container(
height: 250,
padding: EdgeInsets.all(10),
alignment: Alignment.center,
child: GridView.builder(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// childAspectRatio: 1,
crossAxisCount: 7,
crossAxisSpacing: 4,
mainAxisSpacing: 4,
),
itemCount: puzzleAnswer!.length,
shrinkWrap: true,
itemBuilder: (context , index){
print(index);
if(selection.length>index){
return InkWell(
onTap: () {
setState(() {
if (!selection.contains(index)){
null;
}
else{
selection.remove(index);
}
});
},
child: Container(
padding: EdgeInsets.all(10),
alignment: Alignment.center,
decoration: BoxDecoration(
color:Colors.blue,
borderRadius: BorderRadius.circular(7)
),
child: Text("${selection[index]}",
style: TextStyle(color: Colors.black)
),
),
);
}
else{
return Container(
padding: EdgeInsets.all(10),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(7)
),
child: Text("",
style: TextStyle(color: Colors.black)
),
);
}
}
)
),
],
),
Expanded(child:
Container(
// height: 300,
padding: EdgeInsets.all(10),
alignment: Alignment.center,
child: GridView.builder(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: 1,
crossAxisCount: 7,
crossAxisSpacing: 4,
mainAxisSpacing: 4,
),
itemCount: keyboardSize,
// shrinkWrap: true,
itemBuilder: (context , index)
{
return InkWell(
onTap:(){
setState(() {
if (!selection.contains(index)){
selection.add(index);
}
else{
selection.remove(index);
}
}
);
},
child: Container(
padding:EdgeInsets.all(10),
alignment:Alignment.center,
decoration:BoxDecoration(
color:selection.contains(index)?Colors.blueAccent:Colors.grey,
borderRadius:BorderRadius.circular(7)
),
child: Text("${keyboardWords[selection[index]]}",
style:TextStyle(color:Colors.black)
),
),
);
// return ElevatedButton(
// style: ElevatedButton.styleFrom(
// primary: Colors.purple,
// // padding: EdgeInsets.symmetric(horizontal: 50, vertical: 20),
// textStyle: TextStyle(
// fontSize: 20,
// fontWeight: FontWeight.bold
// ),
// ),
// onPressed: null,
// child: Text("d"),
// );
}
)
),
),
],
),
),
),
);
}
}
RandomString(int strlen,String puzzleAnswer){
Random rnd = new Random();
String result = "";
const chars = "abcdefghijklmnopqrstuvwxyz";
for (var i = 0; i < strlen; i++) {
// if (!puzzleAnswer.contains(chars[i])) {
result += chars[rnd.nextInt(chars.length)];
// }
}
return result;
}
Related
class SearchBar extends SearchDelegate {
final TumUrunlerDeneme _tumUrunlerDeneme = TumUrunlerDeneme();
#override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(
onPressed: () {
query = '';
},
icon: const Icon(Icons.close))
];
}
#override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: const Icon(Icons.arrow_back_ios),
onPressed: () {
Navigator.pop(context);
},
);
}
#override
Widget buildResults(BuildContext context) {
return FutureBuilder<List<Products>>(
future: _tumUrunlerDeneme.getuserList(query: query),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(),
);
}
List<Products> ?data = snapshot.data;
return ListView.builder(
shrinkWrap: true,
//physics: const NeverScrollableScrollPhysics(),
itemCount: data!.length,
itemBuilder: (context, index) {
return Column(
children: [
Flex(
direction: Axis.vertical,
children:[ SingleChildScrollView(
scrollDirection: Axis.vertical,
child: GestureDetector(
onTap: () {
Get.toNamed(RouteHelper.getAllProduct(index));
},
child: Container(
margin: EdgeInsets.only(
left: Dimensions.width20,
right: Dimensions.width10,
bottom: Dimensions.height15),
child: Row(
children: [
//image section
Container(
width: Dimensions.listViewImgSize,
height: Dimensions.listViewImgSize,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
Dimensions.radius20),
color: Colors.white38,
image: DecorationImage(
fit: BoxFit.cover,
image: CachedNetworkImageProvider(
AppConstans.BASE_URL +
AppConstans.UPLOAD_URL +
data[index]
.img!))),
),
//text section
Expanded(
child: Container(
height: Dimensions.listViewTextContSize,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topRight: Radius.circular(
Dimensions.radius20),
bottomRight: Radius.circular(
Dimensions.radius20)),
color: Colors.white),
child: Padding(
padding: EdgeInsets.only(
left: Dimensions.width10,
right: Dimensions.width10),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
BigText(
text: data[index].name!,
),
SizedBox(
height: Dimensions.height10,
),
ExpandableProductText(
text: data[index]
.description!),
SizedBox(
height: Dimensions.height10,
),
],
),
),
),
)
],
)),
),
),
]),
],
);
});
});
}
#override
Widget buildSuggestions(BuildContext context) {
return const Center(
child: Text('Ürün Arama'),
);
}
}
Here is detail page :
class AllProductDetail extends StatelessWidget {
final int pageId;
const AllProductDetail({Key? key, required this.pageId}) : super(key: key);
#override
Widget build(BuildContext context) {
var product = Get.find<TumUrunlerController>().tumUrunlerList[pageId];
return Scaffold(
backgroundColor: Colors.white,
body: CustomScrollView(
slivers: [
SliverAppBar(
automaticallyImplyLeading: false,
toolbarHeight: 70,
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(onTap: (){
Navigator.of(context).pop(context);
}
,child: const AppIcon(icon: Icons.arrow_back_ios),
),
],
),
bottom: PreferredSize(
preferredSize: const Size.fromHeight(20),
child: Container(
child: Center(
child: BigText(
text: product.name!,
size: Dimensions.font20,
)),
width: double.maxFinite,
padding: const EdgeInsets.only(top: 0, bottom: 0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(Dimensions.radius20),
topRight: Radius.circular(Dimensions.radius20))),
),
),
backgroundColor: Colors.white,
pinned: true,
expandedHeight: Dimensions.imgsize,
flexibleSpace: FlexibleSpaceBar(
background: Image.network(
AppConstans.BASE_URL+AppConstans.UPLOAD_URL+product.img!,
width: double.maxFinite,
fit: BoxFit.fitWidth,
),
),
),
SliverToBoxAdapter(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
child: ExpandableText(
text: product.description!
),
margin: EdgeInsets.only(
left: Dimensions.width20, right: Dimensions.width20),
),
],
),
)
],
),
);
}
}
here is Controller page:
class TumUrunlerDeneme {
late var data = [];
List<Products> results= [];
String urlList = 'http://mzpdata.com/api/v1/products/allproduct';
Future<List<Products>> getuserList({String? query}) async {
var url = Uri.parse("http://mzpdata.com/api/v1/products/allproduct");
print("got TumUrunlerDeneme 1");
try {
http.Response response = await http.get(url);
if (response.statusCode == 200) {
print("got TumUrunlerDeneme 2");
data = json.decode(response.body)['products'];
print("got TumUrunlerDeneme 3");
results = data.map((e) => Products.fromJson(e)).toList();
print("got TumUrunlerDeneme 4");
if (query != null) {
results = results
.where((element) =>
element.name!.toLowerCase().contains((query.toLowerCase())))
.toList();
print("got TumUrunlerDeneme 5");
}
} else {
print("fetch error");
}
} on Exception catch (e) {
print('error: $e');
}
return results;
}
}
No matter what I search for, the detail opens according to the product order in the whole list.
When I click on the product I am looking for, I reach the details of another product.
How can I search for the product I want and find the details of the product I am looking for?
I appreciate your help.
currently I am fetching the videos from YouTube. The code below just lists out my videos vertically. I want the videos to be listed horizontally. I tried different approaches, but could not succeed. I tried a bunch of options, but was only left with a number of errors. So I am in need of help on what change should I implement.
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
Channel _channel;
bool _isLoading = false;
#override
void initState() {
super.initState();
_initChannel();
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
}
//UCtfK5Khr3psKzUP9HuYYgrw
_initChannel() async {
Channel channel = await APIService.instance
.fetchChannel(channelId: 'Random#');
setState(() {
_channel = channel;
});
}
_buildProfileInfo() {
return Container(
margin: EdgeInsets.all(20.0),
padding: EdgeInsets.all(20.0),
height: 100.0,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black12,
offset: Offset(0, 1),
blurRadius: 6.0,
),
],
),
child: Row(
children: <Widget>[
CircleAvatar(
backgroundColor: Colors.white,
radius: 30.0,
backgroundImage: NetworkImage(_channel.profilePictureUrl),
),
SizedBox(width: 12.0),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
_channel.title,
style: TextStyle(
color: Colors.black,
fontSize: 20.0,
fontWeight: FontWeight.w600,
),
overflow: TextOverflow.ellipsis,
),
// Text(
// '${_channel.subscriberCount} subscribers',
// style: TextStyle(
// color: Colors.grey[600],
// fontSize: 16.0,
// fontWeight: FontWeight.w600,
// ),
// overflow: TextOverflow.ellipsis,
// ),
],
),
)
],
),
);
}
_buildVideo(Video video) {
return GestureDetector(
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => VideoScreen(id: video.id),
),
),
child:
Container(
margin: EdgeInsets.symmetric(horizontal: 20.0, vertical: 5.0),
padding: EdgeInsets.all(10.0),
height: 140.0,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black12,
offset: Offset(0, 1),
blurRadius: 6.0,
),
],
),
child: Row(
children: <Widget>[
Image(
width: 150.0,
image: NetworkImage(video.thumbnailUrl),
),
SizedBox(width: 10.0),
Expanded(
child: Text(
video.title,
style: TextStyle(
color: Colors.black,
fontSize: 18.0,
),
),
),
],
),
),
);
}
_loadMoreVideos() async {
_isLoading = true;
List<Video> moreVideos = await APIService.instance
.fetchVideosFromPlaylist(playlistId: _channel.uploadPlaylistId);
List<Video> allVideos = _channel.videos..addAll(moreVideos);
setState(() {
_channel.videos = allVideos;
});
_isLoading = false;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
toolbarHeight: 30,
title: Text('Jiwdo Pani Audio Video'),
backgroundColor: Colors.indigo[900],
automaticallyImplyLeading: false,
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: Colors.black,
size: 20,
),
onPressed: () => Get.to(UserMenu()))),
body: _channel != null
? NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification scrollDetails) {
if (!_isLoading &&
_channel.videos.length != int.parse(_channel.videoCount) &&
scrollDetails.metrics.pixels ==
scrollDetails.metrics.maxScrollExtent) {
_loadMoreVideos();
}
return false;
},
child: ListView.builder(
shrinkWrap: true,
//scrollDirection: Axis.horizontal,
itemCount: 1 + _channel.videos.length,
itemBuilder: (BuildContext context, int index) {
if (index == 0) {
return _buildProfileInfo();
}
Video video = _channel.videos[index - 1];
return _buildVideo(video);
},
),
)
: Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(
Theme.of(context).primaryColor, // Red
),
),
),
);
}
}
Wrap your listView builder into the container and try to add width and height.
Container(
width : 500,
height : 500,
child:ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: 1 + _channel.videos.length,
itemBuilder: (BuildContext context, int index) {
if (index == 0) {
return _buildProfileInfo();
}
Video video = _channel.videos[index - 1];
return _buildVideo(video);
},
),
),
when i try to increase the quantity the total amount showing big numbers and when i exit the page and reenter it showing correct out put why this happenning...?this happens when i increase or decrease the quantity
this happens when i exit the page and reenter
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:appnew/src/hivedatabase/cart_model.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:appnew/src/widgets/totalprice.dart';
List<String> compnme = List();
List<String> compqnt = List();
class CartPage extends StatefulWidget {
#override
_CartPageState createState() => _CartPageState();
}
class _CartPageState extends State<CartPage> {
double sum = 0;
final cartBox = Hive.box('carts');
final totBox = Hive.box('tot');
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 1,
backgroundColor: Colors.lightGreen,
title: Text(
'Cart',
),
),
body: _buildListView(),
bottomNavigationBar: Container(
color: Colors.white,
child: Row(
children: <Widget>[
Expanded(
child: _buildtotal(),
),
Expanded(
child: new MaterialButton(
onPressed: () {
final cartBox = Hive.box('carts');
cartBox.clear();
compnme.clear();
compqnt.clear();
totBox.clear();
},
child: new Text(
"Check Out",
style: TextStyle(color: Colors.white),
),
color: Colors.red,
)),
],
),
),
);
}
Widget _buildListView() {
// ignore: deprecated_member_use
return WatchBoxBuilder(
box: Hive.box('carts'),
builder: (context, cartBox) {
return ListView.builder(
itemCount: cartBox.length,
itemBuilder: (BuildContext context, int index) {
final cartModel = cartBox.getAt(index) as CartModel;
double iprice = double.parse(cartModel.price);
double nprice = 0;
int iquant = int.parse(cartModel.quantitys);
return Card(
elevation: 5,
child: Container(
height: 130,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
height: 129,
width: 125,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(cartModel.img),
fit: BoxFit.fill,
),
),
),
Container(
height: 130,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 5),
child: Text(
cartModel.pname,
style: TextStyle(fontSize: 20),
),
),
Padding(
padding: EdgeInsets.fromLTRB(0, 4, 0, 3),
child: Container(
width: 160,
child: Text(cartModel.curquant,
style: TextStyle(fontSize: 17)),
),
),
Padding(
padding: EdgeInsets.fromLTRB(1, 25, 0, 0),
child: Text("Rs." + cartModel.price,
style: TextStyle(
fontSize: 19, color: Colors.black54)),
)
],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 77, 19, 2),
child: Container(
height: 90,
child: IconButton(
icon: Icon(Icons.add_circle,
size: 35, color: Colors.green[300]),
onPressed: () {
iquant++;
nprice = iprice + (iprice / (iquant - 1));
cartBox.putAt(
index,
CartModel(
cartModel.pname,
cartModel.curquant,
cartModel.img,
nprice.toString(),
iquant.toString()));
}),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 77, 0, 2),
child: Container(
height: 90,
child: CircleAvatar(
backgroundColor: Colors.grey[300],
maxRadius: 16,
child: Text(cartModel.quantitys),
),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(19, 77, 0, 2),
child: Container(
height: 90,
child: IconButton(
icon: Icon(Icons.remove_circle,
size: 35, color: Colors.redAccent),
onPressed: () {
if (iquant == 1) {
cartBox.deleteAt(index);
print(compnme[index]);
compnme.removeAt(index);
compqnt.removeAt(index);
} else {
iquant--;
nprice = iprice - (iprice / (iquant + 1));
cartBox.putAt(
index,
CartModel(
cartModel.pname,
cartModel.curquant,
cartModel.img,
nprice.toString(),
iquant.toString()));
}
}),
),
)
],
),
),
);
},
);
},
);
}
Widget _buildtotal() {
// ignore: deprecated_member_use
return WatchBoxBuilder(
box: Hive.box('carts'),
builder: (context, cartBox) {
for (int i = 0; i < cartBox.length; i++) {
final cartModel = cartBox.getAt(i) as CartModel;
double iprice = double.parse(cartModel.price);
sum += iprice;
print(sum);
}
return ListTile(
title: new Text("total:", style: TextStyle(color: Colors.black)),
subtitle: new Text(sum.toString(),
style: TextStyle(
color: Colors.black,
fontSize: 16,
)),
);
});
}
}
i tried adding setState() in buttons and functions but it didnt worked
Just assign zero each time in _buildtotal() method
Widget _buildtotal() {
sum=0;//This will reset sum value zero before re-calculating total
// ignore: deprecated_member_use
return WatchBoxBuilder(
box: Hive.box('carts'),
builder: (context, cartBox) {
for (int i = 0; i < cartBox.length; i++) {
final cartModel = cartBox.getAt(i) as CartModel;
double iprice = double.parse(cartModel.price);
sum += iprice;
print(sum);
}
return ListTile(
title: new Text("total:", style: TextStyle(color: Colors.black)),
subtitle: new Text(sum.toString(),
style: TextStyle(
color: Colors.black,
fontSize: 16,
)),
);
});
}
I have seen many same questions but they don't have answers yet, so I decided to put it again.
I am using rest API to load data in Gridview.count with ScrollController which is generally working fine but many times some images are not loading on the frame and i got this error:-
"Connection closed before full header was received, uri =IMAGE URL"
Here is my code
class CreateHome extends StatefulWidget {
_AppState state;
BuildContext context;
CreateHome(this.state, this.context);
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return new CreateHomeState(state, context);
}
}
class CreateHomeState extends State<CreateHome> {
_AppState state;
BuildContext context;
int _selectBuilder = 0;
List<ProductModel> productList = new List();
CreateHomeState(this.state, this.context);
ScrollController _controller;
String lasthit = "";
FutureBuilder<List<ProductModel>> _getFutureBuilder(int pos) {
switch (pos) {
case 0:
return new FutureBuilder(
future: Api.getProductList(context, '0'),
builder: (context, snapshot) {
if (snapshot.hasData) {
productList.addAll(snapshot.data);
return GridList(productList);
} else if (snapshot.hasError) {
Toast.show(snapshot.error, context,
duration: 3, backgroundColor: Colors.deepOrange);
}
return RoundProgress();
},
);
case 1:
return new FutureBuilder(
future: Api.getProductList(
context, productList[productList.length - 1].product_id),
builder: (context, snapshot) {
lasthit = productList[productList.length - 1].product_id;
if (snapshot.hasData) {
productList.addAll(snapshot.data);
//productList = productList.sublist(productList.length-7, productList.length-1);
var distinctIds = productList.toSet().toList();
return GridList(distinctIds);
} else if (snapshot.hasError) {
Toast.show(snapshot.error, context,
duration: 3, backgroundColor: Colors.deepOrange);
}
return RoundProgress();
},
);
}
}
#override
void initState() {
print('initstatecalled');
_controller = ScrollController();
_controller.addListener(_scrollListener);
super.initState();
}
_scrollListener() {
if (_controller.offset >= _controller.position.maxScrollExtent &&
!_controller.position.outOfRange) {
print(productList.length.toString());
String currentHit = productList[productList.length - 1].product_id;
if (currentHit != lasthit) {
setState(() {
_selectBuilder = 1;
});
}
}
}
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
controller: _controller,
child: Container(
color: Colors.black12,
//=========Main Container For Scrollview==============//
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 15, 0, 0),
child: Column(
children: <Widget>[
Container(
width: double.infinity,
//================Container for Categories==================//
color: Colors.white,
child: Container(
height: 130,
child: FutureBuilder<List<CategoryModel>>(
future: Api.getDataCategories(context),
builder: (context, snapshot) {
if (snapshot.hasData) {
List<CategoryModel> categoryListing = snapshot.data;
return ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: categoryListing.length,
itemBuilder: (BuildContext context, int index) {
return createList(
state,
categoryListing[index].url,
categoryListing[index].name,
1,
categoryListing[index].id);
},
);
} else if (snapshot.hasError) {
Toast.show("Error", context,
duration: 3,
gravity: Toast.BOTTOM,
backgroundColor: Colors.deepOrange);
}
return RoundProgress();
},
),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 20, 0, 20),
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 10),
child: SizedBox(
child: FutureBuilder<List<String>>(
future: Api.getBanners(context, "front"),
builder: (context, snapshot) {
if (snapshot.hasData) {
List<String> images = snapshot.data;
return CarouselWithIndicator(images);
} else if (snapshot.hasError) {
Toast.show("Error", context,
duration: 3,
gravity: Toast.BOTTOM,
backgroundColor: Colors.deepOrange);
}
return RoundProgress();
},
),
),
),
),
),
Container(
color: Colors.white, child: _getFutureBuilder(_selectBuilder))
],
),
),
),
);
}
}
This is my code for making GridView
class GridList extends StatelessWidget {
List<ProductModel> list;
GridList(this.list);
#override
Widget build(BuildContext context) {
print('length from grid..'+list.length.toString());
IconData icon;
Color color;
String price;
bool boolean;
return Padding(
padding: const EdgeInsets.fromLTRB(10, 10, 10, 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 10),
child: Text(
'Popular Products',
style: TextStyle(
fontSize: 16,
fontFamily: 'SFProRegular',
color: Colors.black),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 0),
child: GridView.count(
shrinkWrap: true,
primary: false,
childAspectRatio: 0.6,
//(itemWidth / itemHeight),
crossAxisCount: 2,
children: List.generate(list.length, (index) {
if (list[index].wishlist == "1") {
icon = Icons.favorite;
color = Colors.red;
} else {
icon = Icons.favorite_border;
color = Colors.black38;
}
if (list[index].discounted_price != "0") {
price = "Rs " + list[index].discounted_price;
boolean = true;
} else {
price = "Rs " + list[index].price;
boolean = false;
}
return Wrap(
children: <Widget>[
Card(
elevation: 5,
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Container(
constraints: new BoxConstraints.expand(
height: 150.0,
),
padding:
new EdgeInsets.only(top: 8.0, right: 8.0),
decoration: new BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(4),
topRight: Radius.circular(4)),
image: new DecorationImage(
image:
new NetworkImage(list[index].image_url),
fit: BoxFit.cover,
),
),
child: new Stack(
children: <Widget>[
new Positioned(
right: 0.0,
top: 0.0,
child: Material(
borderRadius: BorderRadius.all(
Radius.circular(50)),
child: Padding(
padding: const EdgeInsets.all(6.0),
child: Center(
child: new Icon(
icon,
color: color,
size: 16,
),
),
),
),
),
],
)),
Padding(
padding:
const EdgeInsets.fromLTRB(5.0, 10, 0, 10),
child: Text(
list[index].product_name,
style: TextStyle(
fontSize: 16,
fontFamily: 'SFProRegular',
color: Colors.black),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(5.0, 0, 0, 10),
child: Row(
children: <Widget>[
Icon(
Icons.person,
size: 23,
color: Colors.black38,
),
Padding(
padding:
const EdgeInsets.fromLTRB(5.0, 0, 0, 0),
child: Text(
list[index].designer,
style: TextStyle(
fontSize: 14,
fontFamily: 'SFProRegular',
color: Colors.black38,
decoration: TextDecoration.underline,
),
),
),
],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(5.0, 2, 0, 10),
child: Row(
children: <Widget>[
Text(
price,
style: TextStyle(
fontSize: 13,
fontFamily: 'SFProRegular',
color: Colors.green),
),
Padding(
padding:
const EdgeInsets.fromLTRB(10, 0, 0, 0),
child: Visibility(
visible: boolean,
maintainSize: true,
maintainAnimation: true,
maintainState: true,
child: Text(
"Rs " + list[index].price,
style: TextStyle(
fontSize: 13,
fontFamily: 'SFProRegular',
color: Colors.grey,
decoration:
TextDecoration.lineThrough),
),
),
),
],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(5.0, 0, 0, 5),
child: Visibility(
maintainSize: true,
maintainAnimation: true,
maintainState: true,
visible: boolean,
child: Text(
list[index].discount + '% OFF',
style: TextStyle(
fontSize: 13,
fontFamily: 'SFProRegular',
color: Colors.deepOrange),
),
),
),
],
),
),
),
],
);
}),
crossAxisSpacing: 3.0,
mainAxisSpacing: 5.0,
),
),
],
),
);
}
}
this issue will be solved by
Flutter Clean
run
I am building a food cart application and have a query on the menu item page.
My menu items page consists of a list view, which shows each item with description along with an option to specify the quantity of items( 1, 2, 3....)
Now I am able to increment or decrement item count for a single item, but not sure how to do that in a list view at a particular index where the user clicks.
Could some one please help me on this?
The code which I have done till now is as below :
FutureBuilder(
future: getItemList(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
var itemList = snapshot.data;
int itemlength = itemList.length;
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Container(
height: 100,
margin: EdgeInsets.only(left: 10, right: 10, top: 10),
decoration: BoxDecoration(
color: Colors.white70,
border: Border.all(width: 2.0, color: Colors.blueGrey),
borderRadius: BorderRadius.circular(6.0),
boxShadow: [
BoxShadow(
color: Color(0xFF6078ea).withOpacity(.3),
offset: Offset(0.0, 8.0),
blurRadius: 8.0),
],
),
child: Row(
children: < Widget > [
Container(
width: 75,
child: ClipRRect(
borderRadius: new BorderRadius.circular(10.0),
child: Image(
image: AssetImage(
'assets/images/loginbg3.jpg'),
fit: BoxFit.cover,
),
),
margin: EdgeInsets.only(left: 10),
),
Expanded(
child: Container(
child: Column(
children: < Widget > [
Row(
children: < Widget > [
Expanded(child: Container(margin: EdgeInsets.only(left: 10, top: 15, bottom: 5), child: Text(itemList[index]['itemname'], style: kClickableTextStyle, ))),
Container(color: Colors.white, width: 25, margin: EdgeInsets.only(left: 10, top: 15, bottom: 5), child: Image.asset(_itemtype)),
],
),
Row(
children: < Widget > [
Container(margin: EdgeInsets.only(left: 10, top: 15, bottom: 5), child: Text('Price : ', style: kListTitleTextStyle, )),
Container(margin: EdgeInsets.only(left: 10, top: 15, bottom: 5), child: Text(numberofitems.toString() + ' \u20B9 ', style: kListTitleTextStyle, )),
],
),
],
),
),
),
Container(
margin: EdgeInsets.only(left: 10),
child: Row(
children: < Widget > [
InkWell(
onTap: onClickDelete,
child: Container(
width: 30, child: Icon(
Icons.remove_circle_outline,
color: Colors.green,
size: 30,
), ),
),
Container(
width: 30,
child: Center(child: Text(_count.toString(), style: TextStyle(fontSize: 25), )),
),
InkWell(
onTap: onClickAdd,
child: Container(
margin: EdgeInsets.only(right: 5),
width: 30, child: Icon(
Icons.add_circle_outline,
color: Colors.green,
size: 30,
), ),
),
],
),
),
],
),
);
},
itemCount: itemList == null ? 0 : itemList.length,
);
})
You can copy paste run full code below
Step 1: create Item class
Step 2: change future builder call
Step 3: deal with Inkwell onTap
working demo
code snippet
Future callback;
#override
void initState() {
callback = _getItemList();
super.initState();
}
#override
Widget build(BuildContext context) {
var futureBuilder = FutureBuilder(
future: callback,
...
InkWell(
onTap: () {
if (itemList[index].numberofitems > 0) {
setState(() {
itemList[index].numberofitems =
itemList[index].numberofitems - 1;
});
}
},
...
InkWell(
onTap: () {
setState(() {
itemList[index].numberofitems =
itemList[index].numberofitems + 1;
print(
' ${itemList[index].itemname.toString()} ${itemList[index].numberofitems.toString()}');
});
},
full code
import 'dart:async';
import 'dart:collection';
import 'package:flutter/material.dart';
void main() => runApp( MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class Item {
String itemname;
String itemtype;
int numberofitems;
Item({this.itemname, this.itemtype, this.numberofitems});
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future callback;
#override
void initState() {
callback = _getItemList();
super.initState();
}
#override
Widget build(BuildContext context) {
var futureBuilder = FutureBuilder(
future: callback,
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
default:
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
else
return createListView(context, snapshot);
}
},
);
return Scaffold(
appBar: AppBar(
title: Text("Home Page"),
),
body: futureBuilder,
);
}
Future<List<Item>> _getItemList() async {
var values = List<Item>();
values.add(
Item(itemname: "A", itemtype: "assets/images/a.jpg", numberofitems: 0));
values.add(
Item(itemname: "B", itemtype: "assets/images/a.jpg", numberofitems: 1));
values.add(
Item(itemname: "C", itemtype: "assets/images/a.jpg", numberofitems: 2));
//throw Exception("Danger Will Robinson!!!");
await Future.delayed( Duration(seconds: 2));
return values;
}
Widget createListView(BuildContext context, AsyncSnapshot snapshot) {
List<Item> itemList = snapshot.data;
return ListView.builder(
itemCount: itemList.length,
itemBuilder: (BuildContext context, int index) {
{
return Container(
height: 100,
margin: EdgeInsets.only(left: 10, right: 10, top: 10),
decoration: BoxDecoration(
color: Colors.white70,
border: Border.all(width: 2.0, color: Colors.blueGrey),
borderRadius: BorderRadius.circular(6.0),
boxShadow: [
BoxShadow(
color: Color(0xFF6078ea).withOpacity(.3),
offset: Offset(0.0, 8.0),
blurRadius: 8.0),
],
),
child: Row(
children: <Widget>[
Container(
width: 75,
child: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Image(
image: AssetImage('assets/images/a.jpg'),
fit: BoxFit.cover,
),
),
margin: EdgeInsets.only(left: 10),
),
Expanded(
child: Container(
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
child: Container(
margin: EdgeInsets.only(
left: 10, top: 15, bottom: 5),
child: Text(
itemList[index].itemname,
))),
Container(
color: Colors.white,
width: 25,
margin: EdgeInsets.only(
left: 10, top: 15, bottom: 5),
child: Image.asset(itemList[index].itemtype)),
],
),
Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(
left: 10, top: 15, bottom: 5),
child: Text(
'Price : ',
)),
Container(
margin: EdgeInsets.only(
left: 10, top: 15, bottom: 5),
child: Text(
itemList[index].numberofitems.toString() +
' \u20B9 ',
)),
],
),
],
),
),
),
Container(
margin: EdgeInsets.only(left: 10),
child: Row(
children: <Widget>[
InkWell(
onTap: () {
if (itemList[index].numberofitems > 0) {
setState(() {
itemList[index].numberofitems =
itemList[index].numberofitems - 1;
});
}
},
child: Container(
width: 30,
child: Icon(
Icons.remove_circle_outline,
color: Colors.green,
size: 30,
),
),
),
Container(
width: 30,
child: Center(
child: Text(
itemList[index].numberofitems.toString(),
style: TextStyle(fontSize: 25),
)),
),
InkWell(
onTap: () {
setState(() {
itemList[index].numberofitems =
itemList[index].numberofitems + 1;
print(
' ${itemList[index].itemname.toString()} ${itemList[index].numberofitems.toString()}');
});
},
child: Container(
margin: EdgeInsets.only(right: 5),
width: 30,
child: Icon(
Icons.add_circle_outline,
color: Colors.green,
size: 30,
),
),
),
],
),
),
],
),
);
}
;
});
}
}
you need to create list of objects for your Item like.
class Item{
String name;
String description;
int quantity;
double price;
}
and on tap of item, get index of clicked item with new incremented/decremented value and update your list of objects inside setState().
You need to wrap your itemBuilder item, i.e the Container with a GestureDetector and then call the onTap() method inside that detector.
Before that, you'll have to convert your item into a stateful widget with a variable to maintain the count of quantity.