Related
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'
),
)
)
],
),
)
),
);
}
}
This question already has answers here:
how to assign future<> to widget in flutter?
(6 answers)
Closed 1 year ago.
I'm building a list of buttons, using Firebase to name each one, but my code presents this error when referencing "_getButtonBar" to the Widget: "The argument type 'Future<List>' can't be assigned to the parameter type 'List'". Should the widget be Future too? Does anyone know what's missing?
class ThemesList extends StatelessWidget {
Future<List<FlatButton>> _getButtonBar(context) async {
List<FlatButton> _list1 = [];
tot = await callReadTotal(); //Receives length to make the loop.
getListCauses(); //Calls Firebase to use arrCauses = List () for child: Text
for (int i = 1; i <= tot; i++) {
_list1.add(
FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
side: BorderSide(color: Color.fromRGBO(150, 1, 1, 1)),
),
splashColor: Color.fromRGBO(150, 1, 1, 1),
onPressed: () => {
setChoice(i),
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CausesList()),
),
},
child: Text(
arrCauses[i],
style: TextStyle(
color: Color.fromRGBO(150, 1, 1, 1),
fontSize: 20,
fontFamily: 'Balsamiq_Sans',
),
),
),
);
}
return _list1;
}
#override
Widget build(BuildContext context) {
return Platform.isIOS
? CupertinoPageScaffold(child: null)
: Scaffold(
appBar: AppBar(
title: Text(
'ICare',
style: TextStyle(
color: Color.fromRGBO(150, 1, 1, 1),
fontSize: 40,
fontFamily: 'Balsamiq_Sans',
fontWeight: FontWeight.w500,
),
),
flexibleSpace: Image(
image: AssetImage('assets/images/solidariedade.png'),
color: Color.fromRGBO(255, 200, 200, 0.45),
colorBlendMode: BlendMode.modulate,
fit: BoxFit.cover,
),
),
body: Stack(
children: <Widget>[
Container(
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: ButtonBar(
children: _getButtonBar(
context), //<-- Here it points out the error.
alignment: MainAxisAlignment.center,
),
),
),
],
),
);
}
}
Your problem can be solve via two options.
By using StatefulWidget
import 'package:flutter/material.dart';
class ThemesList extends StatefulWidget {
#override
_ThemesListState createState() => _ThemesListState();
}
class _ThemesListState extends State<ThemesList> {
List<FlatButton> _buttonBar = [];
#override
void initState() {
_getButtonBar();
super.initState();
}
_getButtonBar() async {
List<FlatButton> _list1 = [];
tot = await callReadTotal(); //Receives length to make the loop.
getListCauses(); //Calls Firebase to use arrCauses = List () for child: Text
for (int i = 1; i <= tot; i++) {
_list1.add(
FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
side: BorderSide(color: Color.fromRGBO(150, 1, 1, 1)),
),
splashColor: Color.fromRGBO(150, 1, 1, 1),
onPressed: () => {
setChoice(i),
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CausesList()),
),
},
child: Text(
arrCauses[i],
style: TextStyle(
color: Color.fromRGBO(150, 1, 1, 1),
fontSize: 20,
fontFamily: 'Balsamiq_Sans',
),
),
),
);
}
_buttonBar = _list1;
setState(() {});
}
#override
Widget build(BuildContext context) {
return Platform.isIOS
? CupertinoPageScaffold(child: null)
: Scaffold(
appBar: AppBar(
title: Text(
'ICare',
style: TextStyle(
color: Color.fromRGBO(150, 1, 1, 1),
fontSize: 40,
fontFamily: 'Balsamiq_Sans',
fontWeight: FontWeight.w500,
),
),
flexibleSpace: Image(
image: AssetImage('assets/images/solidariedade.png'),
color: Color.fromRGBO(255, 200, 200, 0.45),
colorBlendMode: BlendMode.modulate,
fit: BoxFit.cover,
),
),
body: Stack(
children: <Widget>[
Container(
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: ButtonBar(
children: _buttonBar,
alignment: MainAxisAlignment.center,
),
),
),
],
),
);
}
}
By using FutureBuilder
import 'package:flutter/material.dart';
class ThemesList extends StatelessWidget {
Future<List<FlatButton>> _getButtonBar(context) async {
List<FlatButton> _list1 = [];
tot = await callReadTotal(); //Receives length to make the loop.
getListCauses(); //Calls Firebase to use arrCauses = List () for child: Text
for (int i = 1; i <= tot; i++) {
_list1.add(
FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
side: BorderSide(color: Color.fromRGBO(150, 1, 1, 1)),
),
splashColor: Color.fromRGBO(150, 1, 1, 1),
onPressed: () => {
setChoice(i),
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CausesList()),
),
},
child: Text(
arrCauses[i],
style: TextStyle(
color: Color.fromRGBO(150, 1, 1, 1),
fontSize: 20,
fontFamily: 'Balsamiq_Sans',
),
),
),
);
}
return _list1;
}
#override
Widget build(BuildContext context) {
return Platform.isIOS
? CupertinoPageScaffold(child: null)
: Scaffold(
appBar: AppBar(
title: Text(
'ICare',
style: TextStyle(
color: Color.fromRGBO(150, 1, 1, 1),
fontSize: 40,
fontFamily: 'Balsamiq_Sans',
fontWeight: FontWeight.w500,
),
),
flexibleSpace: Image(
image: AssetImage('assets/images/solidariedade.png'),
color: Color.fromRGBO(255, 200, 200, 0.45),
colorBlendMode: BlendMode.modulate,
fit: BoxFit.cover,
),
),
body: Stack(
children: <Widget>[
Container(
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: FutureBuilder<List<FlatButton>>(
future: _getButtonBar(context),
builder: (context,
AsyncSnapshot<List<FlatButton>> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Text('Loading....');
break;
default:
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
else
return ButtonBar(
children: snapshot.data,
alignment: MainAxisAlignment.center,
);
}
}),
),
),
],
),
);
}
}
I have a program that uses a List, but I get this error, how to fix it?
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(children: [
CustomScrollView(physics: BouncingScrollPhysics(), slivers: [
_list(),
]),
]),
);
}
_list() {
return List.generate(
actions.length,
(i) => _card(actions[i]),
);
}
_card(
String phrase,
) {
return SliverToBoxAdapter(
child: Card(
shape: RoundedRectangleBorder(
side: BorderSide(color: Colors.black26, width: 0.1),
borderRadius: BorderRadius.circular(10),
),
margin: EdgeInsets.only(right: 50, left: 50, top: 20),
child: InkWell(
splashColor: Colors.black12,
borderRadius: BorderRadius.circular(10),
splashFactory: InkRipple.splashFactory,
onTap: () => _speak(phrase),
child: Column(children: <Widget>[
SizedBox(height: 15.0),
Padding(
padding: EdgeInsets.only(left: 15, right: 15),
child: Text(
phrase,
style: TextStyle(
fontFamily: 'Circular',
fontSize: 17.0,
color: Colors.grey[800]),
),
),
SizedBox(height: 15.0),
]),
),
),
);
}
Your method _list() returns a List<Widget>.
Therefore, you should remove the brackets in your CustomScrollView:
CustomScrollView(physics: BouncingScrollPhysics(), slivers: _list()),
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(),
),
),
],
),
);
}
}
I am trying to fetch a list from API that is two methods fetchImages and fetchCategories. the first time it is showing a red screen error and then after 2 seconds automatically it is loading the list. Can you please tell me what's the issue with my code and how to avoid showing that red screen error in my app?
Widget build(context) {
try{
if (isFirst == true) {
fetchImage();
fetchCategories(context);
isFirst = false;
}
}catch(Exception){
}
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
title: Text('Lets see images!'),
),
body: new Column(
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new InkResponse(
child: new Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: new Image.asset(
catimages[0],
width: 60.0,
height: 60.0,
),
),
new Text(
categoriesText[0],
style: TextStyle(color: Colors.white),
),
],
),
onTap: () {
debugPrint("on tv clikced");
widget.fetchApI.fetchSubCategories(context, 6);
}),
new InkResponse(
child: new Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: new Image.asset(
catimages[1],
width: 60.0,
height: 60.0,
),
),
new Text(
categoriesText[1],
style: TextStyle(color: Colors.white),
),
],
),
onTap: () {
debugPrint("on moview clicked");
widget. fetchApI.fetchSubCategories(context, 7);
},
),
new InkResponse(
child: new Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: new Image.asset(
catimages[2],
width: 60.0,
height: 60.0,
),
),
new Text(
categoriesText[2],
style: TextStyle(color: Colors.white),
),
],
),
onTap: () {
debugPrint("on news clicked");
widget.fetchApI.fetchSubCategories(context, 10);
},
),
new InkResponse(
child: new Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: new Image.asset(catimages[3],
width: 60.0, height: 60.0),
),
new Text(
categoriesText[3],
style: TextStyle(color: Colors.white),
),
],
),
onTap: () {
debugPrint('on shows clicked');
widget.fetchApI.fetchSubCategories(context, 8);
},
),
new InkResponse(
child: new Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: new Image.asset('assets/live_icon.png',
width: 60.0, height: 60.0),
),
new Text(
'Live',
style: TextStyle(color: Colors.white),
),
],
),
onTap: () {
debugPrint('on live clicked');
},
),
],
),
ImageList(images,widget.fetchApI),
],
),
),
);
}
Make sure specifying the length of the list of data. For example, if you're using ListView.builder give proper value to the attribute itemCount.
ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (ctx, index) {
return WidgetItem();
});
The problem can be that you are trying to access a variable/array that is not ready yet (maybe because the future/api call is not finished)
A quick workaround could be to check the length of the array or check for null, example:
Text( (myArray?.length > 0 ? myArray[0] : '') );
There are quick-and-dirty answer, and proper answer
Quick-and-dirty
Use list?.elementAt(<index>) ?? "" for safe access to element of a list
Widget build(context) {
try{
if (isFirst == true) {
fetchImage();
fetchCategories(context);
isFirst = false;
}
}catch(Exception){
}
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
title: Text('Lets see images!'),
),
body: new Column(
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new InkResponse(
child: new Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: new Image.asset(
catimages?.elementAt(0) ?? "",
width: 60.0,
height: 60.0,
),
),
new Text(
categoriesText?.elementAt(0) ?? "",
style: TextStyle(color: Colors.white),
),
],
),
onTap: () {
debugPrint("on tv clikced");
widget.fetchApI.fetchSubCategories(context, 6);
}),
new InkResponse(
child: new Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: new Image.asset(
catimages?.elementAt(1) ?? "",
width: 60.0,
height: 60.0,
),
),
new Text(
categoriesText?.elementAt(1) ?? "",
style: TextStyle(color: Colors.white),
),
],
),
onTap: () {
debugPrint("on moview clicked");
widget. fetchApI.fetchSubCategories(context, 7);
},
),
new InkResponse(
child: new Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: new Image.asset(
catimages?.elementAt(2) ?? "",
width: 60.0,
height: 60.0,
),
),
new Text(
categoriesText?.elementAt(2) ?? "",
style: TextStyle(color: Colors.white),
),
],
),
onTap: () {
debugPrint("on news clicked");
widget.fetchApI.fetchSubCategories(context, 10);
},
),
new InkResponse(
child: new Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: new Image.asset(catimages?.elementAt(3) ?? "",
width: 60.0, height: 60.0),
),
new Text(
categoriesText?.elementAt(3) ?? "",
style: TextStyle(color: Colors.white),
),
],
),
onTap: () {
debugPrint('on shows clicked');
widget.fetchApI.fetchSubCategories(context, 8);
},
),
new InkResponse(
child: new Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: new Image.asset('assets/live_icon.png',
width: 60.0, height: 60.0),
),
new Text(
'Live',
style: TextStyle(color: Colors.white),
),
],
),
onTap: () {
debugPrint('on live clicked');
},
),
],
),
ImageList(images,widget.fetchApI),
],
),
),
);
}
}
Proper answer
Frankly, if I were to review this code, even if it works seamlessly, I would reject this change, because of the structure/pattern this code is using is quite bad.
Please use FutureBuilder, StreamBuilder or ValueListenableBuilder instead, but you need to provide more code (especially fetchImage and fetchCategories) for us to help.
Null safe
Reason for error:
This error occurs on retrieving the value for an index that doesn't exist in the List. For example:
List<int> list = [];
list[0]; // <-- Error since there's no element at index 0 in the list.
Solution:
Check if the the List is not null and has the element at index:
var myList = nullableList;
var index = 0;
if (myList != null && myList.length > index) {
myList[index]; // You can safely access the element here.
}
You are not getting the data. The data folder from or data source is missing. The same happened for me. Later, I created the json file for data and pointed to that location. And it got fixed simply!
I got same issue when tried to access a array which was empty. This was as part of null safety.
my earlier code was
TextBox(response.customerDetails!.address![0].city),
which caused me error so I changed the code to
Text(
(response.cutomerDetails.address.isNotEmpty)
? response.customerDetails!.address![0].city
: "N/A",
),
add a check when accessing arrays. This helped me remove the error.
It happens when you are going to fetch some data but it is not available on that index/position
So, you have to check the index/position value where it is null or not
In my case Listview -> itemcount was perfect but showing this error And then solved it by following checking code
Text("${(widget.topSellItem.subjects.isEmpty) ? "" : widget.topSellItem!.subjects[0].subject.name}"),
I have solved this issue in flutter null safety version by following way.
Reason : It happened when value is not available for that index.
You can check itemCount item value is available or not at builder,
Solution with Null Safety would be like :
ListView.builder(
itemCount: snapshot.data!.items.length, //OR snapshot.data!.length
itemBuilder: (context, index) {
return (index > 0) ? YourWidget() : Container();
});
In case the other methods don't work, check if your database contains any conflicting data entries. If so, fix them.
First, declare the array of objects.
late Map<String, dynamic> product={};
the HTTP answer is:
{
"id": "1",
"codigo": "mw9wcsABvk",
"nombre": "Router TPLink Gaming 5G",
"portada": [
{
"url": "/php/assets/producto/mw9wcsABvk/2729233.png",
"name": "2729233.png"
}
]
}
In Widget build
body: Center(
child: Column(
children: [
if(producto.isNotEmpty)
Expanded(
child: Column(
children: [
ConstrainedBox(
constraints: BoxConstraints.tight(Size(double.infinity, 256)),
child: Stack(
alignment: AlignmentDirectional.center,
children: [
Positioned(
child: Image.network("${host}${producto["portada"][0]["url"]}"),
),
],
),
),
],
),
),
],
),
),
Had same problem when accessing empty arrays, and fix it this ways : data.allData[index].reviews!.isEmpty ? 0 : data.allData[index].reviews![0].rating
when there's data in it, it will access first index.
You must specify the length of the list of data. For example, if you're using ListView along with builder function then you must provide its item length count as itemCount.
ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return //your widget
});
This error comes because of these reasons.
Not using a builder in a screen.
While using a builder we have to provide a condition that checking the list was empty or not. If the list is empty we have to show a circular progress indicator and the list is not empty we can show the list.
If you are fetching data from the API consider using FutureBuilder.
To me, going to the project directory and running the command flutter clean fixed the error