Navigating to different screens from listTile (flutter, dart) - list

I am new to Flutter & would greatly appreciate some help! Apologies in advance for the messy code- I'm trying my best to understand flutter!
I am creating a simple quiz app.
The first page begins with a listTile with the titles of each subsequent page.
From clicking each listTile, I hope to navigate to a different screen. The screens are all in separate dart files.
Ideally, I would like to have the ontap function within the following code, so that each individually titled listTile could lead to a different screen:
Lesson(title: "Hosea", scoreString: "1 / 10", score: 0.1),
However, my ontap function can only be built within listTile, and so i can't make it individual for each Card!
Please help!!
**
class WelcomeScreen extends StatelessWidget {
static const String id = 'welcome_screen';
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Minor Prophets',
theme: new ThemeData(
primaryColor: Color.fromRGBO(58, 66, 86, 1.0), fontFamily: 'Raleway'),
home: new ListPage(title: 'Lessons'),
// home: DetailPage(),
);
}
}
class ListPage extends StatefulWidget {
ListPage({Key key, this.title}) : super(key: key);
final String title;
#override
_ListPageState createState() => _ListPageState();
}
class _ListPageState extends State<ListPage> {
List lessons;
#override
void initState() {
lessons = getLessons();
super.initState();
}
#override
Widget build(BuildContext context) {
ListTile makeListTile(Lesson lesson) => ListTile(
contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 1.0),
leading: Container(
padding: EdgeInsets.only(right: 12.0),
decoration: new BoxDecoration(
border: new Border(
right: new BorderSide(width: 1.0, color: Colors.white24))),
child: Icon(Icons.face, color: Colors.white),
),
title: Text(
lesson.title,
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
//
subtitle: Row(
children: <Widget>[
Expanded(
flex: 1,
child: Container(
// tag: 'hero',
child: LinearProgressIndicator(
backgroundColor: Color.fromRGBO(209, 224, 224, 0.2),
value: lesson.indicatorValue,
valueColor: AlwaysStoppedAnimation(Colors.green)),
)),
Expanded(
flex: 4,
child: Padding(
padding: EdgeInsets.only(left: 10.0),
child: Text(lesson.level,
style: TextStyle(color: Colors.white))),
)
],
),
trailing:
Icon(Icons.keyboard_arrow_right, color: Colors.white, size: 30.0),
onTap: () {
},
);
Card makeCard(Lesson lesson) => Card(
elevation: 8.0,
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
child: Container(
decoration: BoxDecoration(color: Color.fromRGBO(64, 75, 96, .9)),
child: makeListTile(lesson),
),
);
final makeBody = Container(
// decoration: BoxDecoration(color: Color.fromRGBO(58, 66, 86, 1.0)),
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: lessons.length,
itemBuilder: (BuildContext context, int index) {
return makeCard(lessons[index]);
},
),
);
**
`enter code here`List getLessons() {
return [
Lesson(title: "Hosea", scoreString: "1 / 10", score: 0.1),
Lesson(title: "Joel", scoreString: "1 / 10", score: 0.1),
Lesson(title: "Amos", scoreString: "1 / 10", score: 0.1),
Lesson(title: "Obadiah", scoreString: "1 / 10"),
Lesson(title: "Jonah", scoreString: "1 / 10"),
Lesson(title: "Micah", scoreString: "1 / 10"),
Lesson(title: "Nahum", scoreString: "1 / 10"),
Lesson(title: "Habakkuk", scoreString: "1 / 10"),
Lesson(title: "Zephaniah", scoreString: "1 / 10"),
Lesson(title: "Haggai", scoreString: "1 / 10"),
Lesson(title: "Zechariah", scoreString: "1 / 10"),
Lesson(title: "Malachi", scoreString: "1 / 10"),
];
}
**
class Lesson {
String title;
String scoreString;
double score;
Lesson({this.title, this.scoreString, this.score});
}

try to pass in makeListTile(lesson,index) and based on this index you can navigate to different screen
onTap(){
if(index==0)
// do something
else if(index==1)
// do something different
}

Related

This is the latest dialogflow flutter... I dont get response from Dialogflow. I get this Error " The method '[]' was called on null."

import 'package:bubble/bubble.dart';
import 'package:dialogflow_flutter/dialogflowFlutter.dart';
import 'package:dialogflow_flutter/googleAuth.dart';
import 'package:dialogflow_flutter/language.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class ChatBotScreen extends StatefulWidget {
const ChatBotScreen({Key? key}) : super(key: key);
#override
_ChatBotScreenState createState() => _ChatBotScreenState();
}
class _ChatBotScreenState extends State<ChatBotScreen> {
///Dialogflow
void response(query) async {
AuthGoogle authGoogle = await AuthGoogle(fileJson: "assets/services.json").build();
DialogFlow dialogflow = DialogFlow(authGoogle: authGoogle, language: Language.english);
AIResponse aiResponse = await dialogflow.detectIntent(query);
setState(() {
messages.insert(0, {"data": 0, "message":
aiResponse.getListMessage()![0]["text"]["text"][0].toString()
}
);
}
);
}
final messageInsert = TextEditingController();
///list where needed fixing i guess
List<Map> messages = [];
#override
Widget build(BuildContext context) {
return Scaffold(backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Colors.black87,
centerTitle: false,
toolbarHeight: 100,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(30),
bottomRight: Radius.circular(30),
),
),
elevation: 10,
title: const Text("LAIRA",
style: TextStyle(
fontWeight: FontWeight.bold,
fontFamily: 'Lato',
fontSize: 24,
),
),
),
body: Column(
children: <Widget>[
Flexible(
///listview builder
child: ListView.builder(
reverse: true,
itemCount: messages.length,
itemBuilder: (context, index) => chat(
messages[index]["message"].toString(),
messages[index]["data"]
)
)
),
///divider
const Divider(
color: Colors.white,
height: 6.0,
),
Container(
padding: const EdgeInsets.only(left: 15.0, right: 15.0, bottom: 10, top: 10),
///Textfield
margin: const EdgeInsets.symmetric(horizontal: 8.0),
child: Row(
children: [
Flexible(
child: TextField(
controller: messageInsert,
decoration: InputDecoration(
fillColor: Colors.grey[200],
contentPadding:
const EdgeInsets.symmetric(horizontal: 25, vertical: 20),
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
borderSide: const BorderSide(
width: 0,
style: BorderStyle.none,
),
),
hintText: "Type your message...",
hintStyle: const TextStyle(
fontFamily: 'Lato',
fontSize: 18.0)),
)
),
///onpressed send
Container(
margin: const EdgeInsets.symmetric(horizontal: 4.0),
child: IconButton(
icon: const Icon(
Icons.send,
size: 30.0,
),
onPressed: () {
if (messageInsert.text.isEmpty) {
if (kDebugMode) {
print("empty message");
}
} else {
setState(() {
messages.insert(0, {"data": 1, "message": messageInsert.text});
});
response(messageInsert.text);
messageInsert.clear();
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
}
}
),
)
],
),
),
const SizedBox(
height: 15.0,
)
],
),
);
}
///chat system
Widget chat(String message, int data) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: Bubble(
radius: const Radius.circular(10.0),
color: data == 0 ? Colors.blue : Colors.black87,
elevation: 5,
alignment: data == 0 ? Alignment.topLeft : Alignment.topRight,
nip: data == 0 ? BubbleNip.leftBottom : BubbleNip.rightTop,
child: Padding(
padding: const EdgeInsets.all(7.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
// CircleAvatar(
// backgroundImage: AssetImage(
// data == 0 ? "assets/bot.png" : "assets/user.png"),
// ),
const SizedBox(
width: 10.0,
),
Flexible(
child: Text(
message,
style: const TextStyle(
color: Colors.white,
fontSize: 19,
fontFamily: 'Lato'
),
)
)
],
),
)
),
);
}
}

flutter The argument type 'List<dynamic>' can't be assigned

Hey guys I ran into a problem that I don't know how to resolve.
I have a Character class:
import 'package:flutter/material.dart';
class Character {
final String name;
final String imagePath;
final String description;
final List<Color> colors;
Character({
required this.name,
required this.imagePath,
required this.description,
required this.colors,
});
}
List characters = [
Character(
name: 'Kevin',
imagePath: 'assets/images/Kevin_minions.png',
description:
'Sir Kevin KBE (formerly known as Kevin) is one of the Minions and the protagonist in the film Minions. Kevin is a tall, two-eyed minion with sprout cut hair and is usually seen wearing his golf apparel. Kevin loves to make fun of and tease people or Minions, shown when he made fun of Jerry and teases him for being a coward. He loves playing golf and cricket. In the film Minions he is the leader of the trio in search of a new master. He truly cares about the well-being of the Minion tribe (which is dependent on them having a proper master).',
colors: [Colors.orange.shade200, Colors.deepOrange.shade400]),
Character(
name: "Agnes",
imagePath: "assets/images/Agnes_gru.png",
description:
"Agnes Gru it is one of Gru and Lucy's three adopted daughters, alongside her sisters Margo and Edith. She is the youngest child of the three sisters. She greatly adores unicorns, as shown on various occasions. Agnes is a little girl with dark brown eyes. Her long black hair is tied in an upwards ponytail with a red scrunchie. Most of the time, Agnes wears blue overalls over a yellow and brown striped t-shirt, and white sneakers with yellow socks. She also wears a white ballet outfit like Edith and Margo (at the ballet recital). For pajamas, Agnes wears a long blue nightshirt covered with teddy bears and polar bear slippers; her hair stays the same. On her birthday, Agnes is wearing a dress that resembles a princess riding a unicorn. The colors are similar to her regular outfit. She also wears a blue princess hat on her head.",
colors: [Colors.pink.shade200, Colors.redAccent.shade400]),
];
Also a Character info or detail page:
import 'package:flutter/material.dart';
import 'package:mimir_minions/models/character.dart';
import 'package:mimir_minions/styleguide.dart';
class CharacterDetailPage extends StatefulWidget {
final Character character;
const CharacterDetailPage({
Key? key,
required this.character,
}) : super(key: key);
#override
_CharacterDetailPageState createState() => _CharacterDetailPageState();
}
class _CharacterDetailPageState extends State<CharacterDetailPage> {
#override
Widget build(BuildContext context) {
final screenHeight = MediaQuery.of(context).size.height;
return Scaffold(
body: Stack(
fit: StackFit.expand,
children: [
Hero(
tag: "background_${widget.character.name}",
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(35),
topRight: Radius.circular(35),
),
gradient: LinearGradient(
colors: widget.character.colors,
begin: Alignment.topRight,
end: Alignment.bottomLeft,
),
),
),
),
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(16.0, 56.0, 0, 0),
child: IconButton(
icon: Icon(
Icons.close,
),
iconSize: 48,
color: Colors.white.withOpacity(0.8),
onPressed: () {
Navigator.pop(context);
},
),
),
Align(
alignment: Alignment.topRight,
child: Hero(
tag: "image_${widget.character.name}",
child: Image.asset(
widget.character.imagePath,
height: screenHeight * 0.45,
),
),
),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 32.0, vertical: 8),
child: Hero(
tag: "name_${widget.character.name}",
child: Material(
color: Colors.transparent,
child: Container(
child: Text(widget.character.name,
style: AppTheme.heading)))),
),
Padding(
padding: const EdgeInsets.fromLTRB(16.0, 0, 32.0, 24.0),
child: Text(widget.character.description,
style: AppTheme.subHeading),
),
],
),
),
],
),
);
}
}
and a character widget page:
import 'package:flutter/material.dart';
import 'package:mimir_minions/models/character.dart';
import 'package:mimir_minions/pages/character_detail_page.dart';
import 'package:mimir_minions/styleguide.dart';
class CharacterWidget extends StatelessWidget {
const CharacterWidget({Key? key, required this.character}) : super(key: key);
final Character character;
#override
Widget build(BuildContext context) {
final screenHeight = MediaQuery.of(context).size.height;
final screenWidth = MediaQuery.of(context).size.width;
return InkWell(
onTap: () {
Navigator.push(
context,
PageRouteBuilder(
transitionDuration: Duration(milliseconds: 350),
pageBuilder: (context, _, __) => CharacterDetailPage(
character: characters,
),
),
);
},
child: Stack(
children: [
Align(
alignment: Alignment.bottomCenter,
child: Hero(
tag: "background_${characters[0].name}",
child: ClipPath(
clipper: CharacterCardBackgroundClipper(),
child: Container(
height: screenHeight * 0.6,
width: screenWidth * 0.9,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: characters[0].colors,
begin: Alignment.topRight,
end: Alignment.bottomLeft,
),
),
),
),
),
),
Align(
alignment: Alignment(0, -0.6),
child: Hero(
tag: "image_${characters[0].name}",
child: Image.asset(
characters[0].imagePath,
height: screenHeight * 0.55,
),
),
),
Padding(
padding: const EdgeInsets.only(left: 32, right: 8, bottom: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Hero(
tag: "name_${characters[0].name}",
child: Material(
color: Colors.transparent,
child: Container(
child: Text(characters[0].name,
style: AppTheme.heading)))),
Text('Tap to read more', style: AppTheme.subHeading),
],
),
)
],
),
);
}
}
class CharacterCardBackgroundClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
Path clippedPath = Path();
double curveDistance = 40;
clippedPath.moveTo(0, size.height * 0.4);
clippedPath.lineTo(0, size.height - curveDistance);
clippedPath.quadraticBezierTo(
1, size.height - 1, 0 + curveDistance, size.height);
clippedPath.lineTo(size.width - curveDistance, size.height);
clippedPath.quadraticBezierTo(size.width + 1, size.height - 1, size.width,
size.height - curveDistance);
clippedPath.lineTo(size.width, 0 + curveDistance);
clippedPath.quadraticBezierTo(size.width - 1, 0,
size.width - curveDistance - 5, 0 + curveDistance / 3);
clippedPath.lineTo(curveDistance, size.height * 0.29);
clippedPath.quadraticBezierTo(
1, (size.height * 0.30) + 10, 0, size.height * 0.4);
return clippedPath;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) {
return true;
}
}
When I use the character as a list like character[0].name I have no problem. However, when I want to change it to the character so I have several character widgets on my first page it gives me an error that says
The argument type 'List' can't be assigned to the parameter
type 'Character'.dart(argument_type_not_assignable)
This is the link to my repo on Github
The error is pretty clear you are trying to use a List when Dart is expecting a single instance of Character.
I think what you are trying to achieve is a master/detail view.
You should have one CharacterList widget
class CharacterList extends StatelessWidget {
final List<Character> characters;
const CharacterList({Key? key, required this.characters}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: characters.length, itemBuilder: (context, index) => CharacterWidget(character: characters[index])),
);
}
}
This ListView will be your master view and on any of the CharacterWidget they should take you to the detail view, but you should start using the character attribute instead of the characters list in your CharacterWidget
return InkWell(
onTap: () {
Navigator.push(
context,
PageRouteBuilder(
transitionDuration: Duration(milliseconds: 350),
pageBuilder: (context, _, __) => CharacterDetailPage(
character: character,
),
),
);
},
child: Stack(
children: [
Align(
alignment: Alignment.bottomCenter,
child: Hero(
tag: "background_${character.name}",// instead of "background_${characters[0].name}"
child: ClipPath(

Flutter Firebase where query arrayContains in List [duplicate]

This question already has answers here:
Firestore search array contains for multiple values
(6 answers)
Closed 1 year ago.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class SearchPage extends StatefulWidget {
#override
_SearchPageState createState() => _SearchPageState();
}
class _SearchPageState extends State<SearchPage> with TickerProviderStateMixin {
final searchController = TextEditingController();
final _firestore = FirebaseFirestore.instance;
static const defaultSearch = "";
String search = defaultSearch ;
void dispose() {
searchController.dispose();
super.dispose();
}
#override
void initState() {
super.initState();
searchController.addListener(searchChanged);
}
searchChanged() {
setState(() {
search = searchController.text;
});
}
#override
Widget build(BuildContext context) {
var tarifRef = _firestore
.collection("vehicles")
.where("models", arrayContains: search);
return Scaffold(
body: Container(
child: ListView(
children: <Widget>[
Expanded(
child: Container(
height: MediaQuery.of(context).size.height * 0.08,
margin: EdgeInsets.only(top: 25),
child: Text(
"Vehicles",
style: TextStyle(
fontSize: 20, fontFamily: "Quando", color: Colors.indigo),
),
),
),
Expanded(
child: Container(
margin: EdgeInsets.only(
top: 10.0, bottom: 10.0, right: 30, left: 30),
child: TextField(
keyboardType: TextInputType.text,
decoration: InputDecoration(
prefixIcon: Icon(Icons.search),
),
controller: searchController,
),
),
),
Expanded(
child: Container(
height: MediaQuery.of(context).size.height * 0.50,
child: StreamBuilder<QuerySnapshot>(
stream: tarifRef.snapshots(),
builder: (BuildContext context, AsyncSnapshot asyncsnapshot) {
if (asyncsnapshot.hasError) {
return Center(
child: Text("Error"),
);
} else {
if (asyncsnapshot.hasData) {
List<DocumentSnapshot> listOfDocumentSnapshot =
asyncsnapshot.data.docs;
return Flexible(
child: ListView.builder(
itemCount: listOfDocumentSnapshot.length,
itemBuilder: (context, index) {
return Card(
color: Colors.indigo,
child: ListTile(
title: Text(
"${listOfDocumentSnapshot[index]["name"]}",
style: TextStyle(
fontSize: 20,
color: Colors.white,
),
),
subtitle: Text(
"${listOfDocumentSnapshot[index]["models"]}",
style: TextStyle(
fontSize: 15,
color: Colors.white,
),
),
trailing: IconButton(
icon: Icon(
Icons.delete,
color: Colors.white,
),
onPressed: () async {
await listOfDocumentSnapshot[index]
.reference
.delete();
},
),
),
);
},
),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
}
},
),
),
),
],
),
),
);
}
}
This my all code and also I have database in Firebase like this;
vehicles: [
{
"name": "Vehicle1",
"models": ["bus", "plane", "motorcycle"]
},
{
"name": "Vehicle2",
"models": ["motorcycle", "sporcar", "plane"]
},
{
"name": "Vehicle3",
"models": ["motorcycle", "plane", "bus"]
}
]
In this example I can take one input from user, I can query and display which list includes this data but I want to query more than one data is in lists or not.
For example in this code if user input bus, program display Vehicle1 list but I want user can input more than one data such as plane and motorcycle. And so when the user input the plane and motorcycle, I want it to be displayed the list of Vehicle 2 and Vehicle 3.
I try a lot of different ways but I can't found proparly solution to this problem.
I think you're looking for arrayContainsAny here:
var tarifRef = _firestore
.collection("vehicles")
.where("models", arrayContainsAny: ["bus", "plane"]);
This query will return documents whose models array contains either "bus", "plane" or both.
Also see the FlutterFire documentation for Query.where.

How to not lose a data from the list when going from one screen to another screen in flutter?

I have a class ViewTotalItemProvider which extends the ChangeNotifier. Inside the class, there is a list like this.
class ViewTotalItemProvider extends ChangeNotifier{
List<CartPlantLists> cartPlantList3 = [];
}
Additionally, there are 3 screens including class like, PlantFeatureScreen1, ParticularPlant2, CartDetais3. All are stateful widget and I am adding some items in second screen i.e. ParticularPlant2 class.
When I try to show the items from list in the second screen and the third screen it works.
But the value is not updated in the firstScreen i.e. PlantFeatureScreen1. However, when I reload the app, it shows the updated value.
why is this happening? How can I solve it?
Code
ViewTotalItemProvider
List<CartPlantLists> cartPlantList3 = [];
class ViewTotalItemProvider extends ChangeNotifier{
addQuantity(index){
cartPlantList3[index].qu++;
notifyListeners();
}
subtrachQuantity(index){
cartPlantList3[index].qu--;
notifyListeners();
}
}
firstScreen PlantFeatureScreen1 (Here I want to update the value in the very last widget)
class PlantFeatureScreen1 extends StatefulWidget {
#override
_PlantFeatureScreen1State createState() => _PlantFeatureScreen1State();
}
class _PlantFeatureScreen1State extends State<PlantFeatureScreen1> {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<ViewTotalItemProvider>(
create: (context) => ViewTotalItemProvider(),
child:Builder(builder: (context) {
return Column(
children: <Widget>[
TopAppBar(),
Expanded(
flex: 1,
child: Align(
alignment: Alignment(-1, 0),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
),
child: Text(
"Plants",
style: TextStyle(fontSize: 30, fontWeight: FontWeight.w700),
),
),
),
),
Expanded(
flex: 5,
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.blue,
),
child: DefaultTabController(
length: 5,
child: Column(
children: [
Container(
height: 50,
width: double.infinity,
child: TabBar(
isScrollable: true,
tabs: ourAllLists.tabMaker(),
),
),
Container(
height: 317,
width: double.infinity,
decoration: BoxDecoration(color: Colors.white),
child: TabBarView(
children: ourAllLists.tabViewerMaker(context),),),
],
),
),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 20),
child: Container(
alignment: Alignment.bottomRight,
height: 120,
width: double.infinity,
child: Stack(
overflow: Overflow.visible,
children: [
Container(
height: 70,
width: 105,
decoration: BoxDecoration(
color: Color(0xFF96CA2D),
borderRadius: BorderRadiusDirectional.horizontal(
end: Radius.circular(32),
start: Radius.circular(32))),
child: Icon(FontAwesomeIcons.shoppingBag,color:Colors.white,size:30),
),
Positioned(
// top: 0,
bottom: 50,
right: 0,
child: Consumer<ViewTotalItemProvider>(
builder: (context, value, child){
return Container(
height: 35,
width: 35,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(50),
border: Border.all(color: Color(0xFF96CA2D),width: 4)
),
child: Center(child: Text(ourAllLists.totalquantity().toString(),style:TextStyle(fontSize: 20,color: Color(0xFF96CA2D)))),
);
}),
),
],
),
),
)
],
);
})
);
}
}
secondScreen ParticularPlant2
class ParticularPlant2 extends StatefulWidget {
final indexNumber;
ParticularPlant2({#required this.indexNumber});
#override
_ParticularPlant2State createState() => _ParticularPlant2State();
}
class _ParticularPlant2State extends State<ParticularPlant2> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: SafeArea(
child: Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TopAppBar(),
Container(
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadiusDirectional.only(
bottomStart: Radius.circular(50),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
ourAllLists
.mainListAllPlantDetailsList1[widget.indexNumber].pN,
style: kPlantNameStyle,
),
Text(
ourAllLists
.mainListAllPlantDetailsList1[widget.indexNumber].ca
.toUpperCase(),
style: TextStyle(
fontSize: 15,
),
),
Text(
"\$" +
ourAllLists
.mainListAllPlantDetailsList1[widget.indexNumber]
.pr
.toString(),
style: kItemPrice,
),
SizedBox(height: 100),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
height: 80,
width: 80,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(50)),
child: Icon(
FontAwesomeIcons.flag,
color: Color(0xFF9DCD3C),
),
),
SizedBox(
height: 50,
),
FlatButton(
onPressed: () {
final tile = cartPlantList3.firstWhere(
(item) =>
item.pN ==
ourAllLists
.mainListAllPlantDetailsList1[
widget.indexNumber]
.pN,
orElse: () => null);
if (tile != null) {
} else {
cartPlantList3.add(
CartPlantLists(
quantity: 1,
plantName: ourAllLists
.mainListAllPlantDetailsList1[
widget.indexNumber]
.pN,
category: ourAllLists
.mainListAllPlantDetailsList1[
widget.indexNumber]
.ca,
price: ourAllLists
.mainListAllPlantDetailsList1[
widget.indexNumber]
.pr,
),
);
}
print(cartPlantList3.length);
},
child: Container(
height: 80,
width: 80,
decoration: BoxDecoration(
color: Color(0xFF9DCD3C),
borderRadius: BorderRadius.circular(50)),
child: Icon(FontAwesomeIcons.shoppingBag,
color: Colors.white),
),
)
],
),
Container(
height: 250,
child: Image(image: AssetImage("assets/tulip.png")),
)
],
)
],
),
)
],
),
),
),
);
}
}
It seems like you are using Provider the wrong way. The best way to do this in your scenario is to wrap MaterialApp inside MyApp() in your main.dart file with MultiProvider. Try something like this: https://pub.dev/packages/provider#multiprovider You can place a ChangeNotifierProvider inside it.
return MultiProvider(
providers: [
ChangeNotifierProvider<ViewTotalItemProvider>(
create: (context) => ViewTotalItemProvider()),
],
child: MaterialApp(...)
);
Also, you have to place a getter and setter in your Model. Here is an example:
class ImageModel extends ChangeNotifier {
String _base64Image;
get base64Image => _base64Image;
set base64Image(String base64Image) {
_base64Image = base64Image;
notifyListeners();
}
}
I would also recommend using Selector instead of Consumer (Ideally, you should use Selector instead of Consumer so that the widget only rebuilds if the value its listening to changes) Here is an example based on the model above:
#override
Widget build(BuildContext context) {
//other widgets
Selector<ImageModel, String>(
selector: (_, model) => model.base64Image,
builder: (_, image, __) {
return Text(image);
},
);
}
)
}
Here is how you can get and set it using a RaisedButton:
class _PlantFeatureScreen1State extends State<PlantFeatureScreen1> {
final itemModel;
List<CartPlantLists> myList=[];
#override
Widget build(BuildContext context) {
itemModel = Provider.of<ViewTotalItemProvider>(context,listen:false);
print(itemModel.yourVariable); //getting the value
return Container(
child: RaisedButton(
child:Text("Set Item");
onPressed:(){
itemModel.yourVariable=myList; //setting the value
},
),
);
}
}
Hope this helps! Good Luck!
Step 1:
add the dependency for the provider pattern in the pubspec.yaml file
dependencies:
flutter:
sdk: flutter
provider: ^4.1.2
Step 2:
create provider in seperate file :
class ViewTotalItemProvider with ChangeNotifier{
List<CartPlantLists> _cartPlantList1 = [];
get cartPlantList1 => _cartPlantList1 ;
set cartPlantList1 (List<CartPlantLists> selected){
_cartPlantList1 = selected;
notifyListeners();
}
}
step 3:
Use MultiProvider to wrap the MaterialApp widget in main.dart.
void main() => runApp(
MultiProvider (providers: [
ChangeNotifierProvider<ViewTotalItemProvider>.value(value:
ViewTotalItemProvider()),
],
child: MyApp()
)
);
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
Step 4:
use provider in your screen PlantFeatureScreen1 :
class PlantFeatureScreen1 extends StatefulWidget {
#override
_PlantFeatureScreen1State createState() => _PlantFeatureScreen1State();
}
class _PlantFeatureScreen1State extends State<PlantFeatureScreen1> {
var viewTotalItemProvider;
#override
Widget build(BuildContext context) {
viewTotalItemProvider = Provider.of<ViewTotalItemProvider>(context);
return Scaffold(
.......
);
}
}
step 5:
get cartPlantList1.
List<CartPlantLists> list = viewTotalItemProvider.cartPlantList1;
step 6 : set cartPlantList1.
List<CartPlantLists> list = [];
...
viewTotalItemProvider.cartPlantList1 = list;
similarly u can use for other two classes.

Flutter Horizontal List View Dot Indicator

I have multiple images each with their own redirect link. Currently this works fine at displaying using a list view build to display the images inside a gesture detector.
However, I’d like to add a dot indicator to show which image is being viewed. How can I get the index of the image being displayed? Or increase / decrease a counter when swiping left or right.
I’ve looked into carousels but they don’t seem to allow each image to redirect to somewhere else.
As per example pointed to by #chunhunghan above in the comments, you need to replace map<Widget> ( (image, url) {..}
with
imgList.map((image) {int index = imgList.indexOf(image); ..}
I was able to get it to work with the above change. Revised code snippet for the build method:
#override
Widget build(BuildContext context) {
return Column(children: [
CarouselSlider(
items: child,
autoPlay: false,
enlargeCenterPage: true,
aspectRatio: 2.0,
onPageChanged: (index) {
setState(() {
_current = index;
print("${_current}");
});
},
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: imgList.map((image) { //these two lines
int index=imgList.indexOf(image); //are changed
return Container(
width: 8.0,
height: 8.0,
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 2.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _current == index
? Color.fromRGBO(0, 0, 0, 0.9)
: Color.fromRGBO(0, 0, 0, 0.4)),
);
},
),
),
]);
}
If I understand you clear. with package https://pub.dev/packages/carousel_slider
swipe image to left or right can get current page from onPageChanged event
and use InkWell wrap image, you can navigate to other page. In my demo just print click message
code snippet
final List child = map<Widget>(
imgList,
(index, i) {
return Container(
margin: EdgeInsets.all(5.0),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
child: Stack(children: <Widget>[
InkWell(
onTap: () { print("you click ${index} "); },
child: Image.network(i, fit: BoxFit.cover, width: 1000.0)),
Positioned(
bottom: 0.0,
left: 0.0,
right: 0.0,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color.fromARGB(200, 0, 0, 0), Color.fromARGB(0, 0, 0, 0)],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
),
),
padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
child: Text(
'No. $index image',
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
),
),
]),
),
);
},
).toList();
...
class _CarouselWithIndicatorState extends State<CarouselWithIndicator> {
int _current = 0;
#override
Widget build(BuildContext context) {
return Column(children: [
CarouselSlider(
items: child,
autoPlay: false,
enlargeCenterPage: true,
aspectRatio: 2.0,
onPageChanged: (index) {
setState(() {
_current = index;
print("${_current}");
});
},
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: map<Widget>(
imgList,
(index, url) {
return Container(
width: 8.0,
height: 8.0,
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 2.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _current == index
? Color.fromRGBO(0, 0, 0, 0.9)
: Color.fromRGBO(0, 0, 0, 0.4)),
);
},
),
),
]);
}
}
The solution I found, besides change map to use imgList, was to put .toList() at the imgList.map function return as follows:
#override
Widget build(BuildContext context) {
return Column(children: [
CarouselSlider(
items: child,
autoPlay: false,
enlargeCenterPage: true,
aspectRatio: 2.0,
onPageChanged: (index) {
setState(() {
_current = index;
print("${_current}");
});
},
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: imgList.map((image) {
int index=imgList.indexOf(image);
return Container(
width: 8.0,
height: 8.0,
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 2.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _current == index
? Color.fromRGBO(0, 0, 0, 0.9)
: Color.fromRGBO(0, 0, 0, 0.4)
),
);
},
).toList(), // this was the part the I had to add
),
]);
}
Vertical Indicators On Slider or Flutter Carousel
class VerticalSlider extends StatefulWidget {
#override
_VerticalSliderState createState() => _VerticalSliderState();
}
class _VerticalSliderState extends State<VerticalSlider> {
List imageSliders=[
//add your items here
];
int _current = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Vertical sliding carousel ')),
body: Stack(
children: [
Container(
child: CarouselSlider(
options: CarouselOptions(
viewportFraction: .6,
aspectRatio: 1.2,
enlargeCenterPage: true,
scrollDirection: Axis.vertical,
autoPlay: true,
onPageChanged: (index, reason) {
setState(() {
_current = index;
});
}
),
items: imageSliders,
)
),
Positioned(
top: 50,
right: 10,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: imgList.map((url) {
int index = imgList.indexOf(url);
return Container(
width: 8.0,
height: 8.0,
margin: EdgeInsets.symmetric(vertical: 4.0, horizontal: 2.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _current == index
? Colors.white60
: Color.fromRGBO(0, 0, 0, 0.4),
),
);
}).toList(),
),
),
],
),
);
}
}
And you may add custom indicators too.
The easiest way is to use CarouselSlider with the AnimatedSmoothIndicator widget
int _current = 0;
#override
Widget build(BuildContext context) {
Column(children: [
CarouselSlider(
options: CarouselOptions(
height: MediaQuery.of(context).size.height / 2,
onPageChanged: (i, r) {
setState(() {
_current = i;
});
}),
items: imageList.map((e) => Container(
child: Image.network(e, fit: BoxFit.cover),
))
.toList(),
),
Container(
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 2.0),
child: AnimatedSmoothIndicator(
activeIndex: _current,
count: imageList.length,
effect: ExpandingDotsEffect(
activeDotColor: Color.fromRGBO(0, 0, 0, 0.9),
dotWidth: 8,
dotHeight: 8),
),
)
]);
add auto slider code for flutter like this....
output screen shorts is here
class _ProductDetailsState extends State<ProductDetails> {
List imageSliders = [
'assets/images/man_1.png',
'assets/images/man_2.png',
'assets/images/man_3.png',
'assets/images/woman_1.png',
'assets/images/woman_2.png',
'assets/images/woman_3.png',
'assets/images/woman_4.png',
'assets/images/woman_5.png',
'assets/images/woman_6.png',
'assets/images/woman_7.png',
];
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
systemNavigationBarColor: Color(0xFF000000),
systemNavigationBarIconBrightness: Brightness.dark,
systemNavigationBarDividerColor: null,
statusBarColor: Color(0xFFFFFFFF),
statusBarIconBrightness: Brightness.dark,
statusBarBrightness: Brightness.dark,
));
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
elevation: 0,
automaticallyImplyLeading: false,
backgroundColor: Colors.white,
leading: Padding(
padding: const EdgeInsets.only(
left: 20,
top: 10,
),
child: IconButton(
icon: Icon(
Icons.keyboard_backspace_sharp,
size: 35,
color: Colors.grey[600],
),
onPressed: () => Navigator.of(context).pop(),
),
),
actions: [
Padding(
padding: const EdgeInsets.only(
left: 0,
top: 10,
),
child: IconButton(
icon: const Icon(
Icons.search_outlined,
color: Colors.black,
size: 30,
),
onPressed: () {},
),
),
Padding(
padding: const EdgeInsets.only(
left: 0,
top: 10,
right: 20,
),
child: IconButton(
icon: Stack(
children: [
if (_newNotification)
Positioned(
right: 1,
top: 1,
child: Container(
decoration: BoxDecoration(
shape: BoxShape.circle, color: Colors.red),
width: 20.0 / 2.5,
height: 20.0 / 2.5,
),
),
Icon(
Icons.notifications_none_outlined,
color: Colors.black,
size: 30,
)
],
),
onPressed: () {},
),
),
],
),
body: Column(
children: [
Container(
child: CarouselSlider(
options: CarouselOptions(
height: 200,
viewportFraction: .6,
aspectRatio: 1.2,
enlargeCenterPage: true,
scrollDirection: Axis.horizontal,
autoPlay: true,
onPageChanged: (index, reason) {
setState(() {
activeIndex = index;
});
}
),
items: [
for(var item in imageSliders ) Image.asset(item)
],
)
),
Positioned(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: imageSliders.map((url) {
int index = imageSliders.indexOf(url);
return Container(
width: 8.0,
height: 8.0,
margin: EdgeInsets.symmetric(vertical: 4.0, horizontal: 2.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: activeIndex == index
? Colors.blue
: Color.fromRGBO(0, 0, 0, 0.4),
),
);
}).toList(),
),
),
],
),
);
}
}