How to add network image in a List<ImageProvider> - flutter

I have a list of image.
final List<ImageProvider>_imageProviders_pro = [
new Image.asset(
"assets/page1.png",
fit: BoxFit.fitWidth,
).image,
new Image.asset(
"assets/page2.png",
fit: BoxFit.fitWidth,
).image,
...
];
#override
Widget build(BuildContext context) {
return Scaffold(
body:
ImageViewPager(imageProviders: _imageProviders_pro)
)
}
class ImageViewPager extends StatefulWidget {
final List<ImageProvider> imageProviders;
/// Create new instance, using the [imageProviders] to populate the [PageView]
const ImageViewPager({ Key? key, required this.imageProviders }) : super(key: key);
#override
_ImageViewPagerState createState() => _ImageViewPagerState();
}
class _ImageViewPagerState extends State<ImageViewPager> {
#override
Widget build(BuildContext context) {
return PageView(
children: <Widget>[
PageView.builder(
physics: _pagingEnabled ? const PageScrollPhysics() : const NeverScrollableScrollPhysics(),
itemCount: widget.imageProviders.length,
controller: _pageController,
itemBuilder: (context, index) {
final image = widget.imageProviders[index];
return ImageView(
imageProvider: image,
onScaleChanged: (scale) {
setState(() {
_pagingEnabled = scale <= 1.0;
});
},
);
},
)
}
}
Now, I try to use same list with Image.network. But I have this error
The element type 'Image' can't be assigned to the list type 'ImageProvider'.
So I try to do something like thtat
final List<ImageProvider>_imageProviders_pro = [
Image.network('url_page1')
Image.network('url_page2')
];

You can use .image to get image-provider from Image.network.
Image.networ("url").image
final List<ImageProvider> _imageProviders_pro = [
Image.network('url_page1').image,
Image.network('url_page2').image
];

Related

How to display received json data from previous screen in Flutter

I want to display the JSON data inside ListView.builder received from the previous screen. Below is the sample code till now that I have tried.
FirstPage.dart
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => MyOrderDetails(
storeItems: order.inDetail!.menuItems!
)));
This is the sample json i am passing to Next Screen
{
"item_name": "Test",
"quantity": 1,
"subtotal": "434.78"
}
MyOrderDetail.dart
class MyOrderDetails extends StatefulWidget {
final List storeItems;
const MyOrderDetails(
{Key? key,
required this.storeItems})
: super(key: key);
#override
State<MyOrderDetails> createState() => _MyOrderDetailsState();
}
class _MyOrderDetailsState extends State<MyOrderDetails> {
#override
Widget build(BuildContext context) {
var height = MediaQuery.of(context).size.height;
var width = MediaQuery.of(context).size.width;
var lang = translator.activeLanguageCode;
return Scaffold(
appBar: AppBar(
elevation: 0,
),
body: ListView(
children: [
ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: widget.storeItems.length,
itemBuilder: (BuildContext context, int index) {
return Text(widget.storeItems[index]['item_name']); // Getting error here
}),
],
),
);
}
}
Your variable should be like that. List is not enough by itself you should declare which class is for that list.
final List<YourDataClass> storeItems;
const MyOrderDetails(
{Key? key,
required this.storeItems})
: super(key: key);

Flutter: Jump to specific item by item data in ListView.builder

It's possible to jump to specific item by item data in ListView?
class Test extends StatelessWidget {
Test({Key? key}) : super(key: key);
final _list = <String>[
"INFWARS_CH01_EP01",
"INFWARS_CH01_EP02",
"INFWARS_CH01_EP03",
"INFWARS_CH01_EP04",
"INFWARS_CH01_EP05",
];
void _scrollToItem() {
final specificItem = "INFWARS_CH01_EP04";
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: _list.length,
itemBuilder: (context, index) {
final data = _list[index];
return Text(data);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () => _scrollToItem(),
),
);
}
}
as you can see, I want to jump to specific item in ListView by specific data "INFWARS_CH01_EP04" using _scrollToItem function, not by index or by position.
So the item ListView for INFWARS_CH01_EP04 will be in the top (scrolled). For now in the top is INFWARS_CH01_EP01.
It's possible to do it?
I fix it using this package: https://pub.dev/packages/scroll_to_index
So you can scroll / jump to specific item by index / by item data in ListView.
class Test extends StatelessWidget {
Test({Key? key}) : super(key: key);
AutoScrollController _scrollController = AutoScrollController();
final _list = <String>[
"INFWARS_CH01_EP01",
"INFWARS_CH01_EP02",
"INFWARS_CH01_EP03",
"INFWARS_CH01_EP04",
];
void _scrollToItem() async {
final specificItem = "INFWARS_CH01_EP04";
final index = _list.indexOf(specificItem);
await _scrollController.scrollToIndex(
index,
preferPosition: AutoScrollPosition.begin,
);
await _scrollController.highlight(index);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
controller: _scrollController,
itemCount: _list.length,
itemBuilder: (context, index) {
final data = _list[index];
return AutoScrollTag(
key: ValueKey(index),
controller: _scrollController,
index: index,
child: Text(data),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () => _scrollToItem(),
),
);
}
}
To scroll to a specific item you can:
Find the specific item using the indexOf() method:
Use the scrollable_positioned_list package to scroll to that item.
Here is a complete working example:
class Test extends StatelessWidget {
Test({Key? key}) : super(key: key);
ItemScrollController _scrollController = ItemScrollController();
final _list = <String>[
"INFWARS_CH01_EP01",
"INFWARS_CH01_EP02",
"INFWARS_CH01_EP03",
"INFWARS_CH01_EP04",
];
void _scrollToItem() {
final specificItem = "INFWARS_CH01_EP04";
_scrollController.jumpTo(index: _list.indexOf(specificItem));
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ScrollablePositionedList.builder(
itemScrollController: _scrollController,
itemCount: _list.length,
itemBuilder: (context, index) {
final data = _list[index];
return Text(data);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () => _scrollToItem(),
),
);
}
}
See also: flutter ListView scroll to index not available
You can use the flutter_scrollview_observer lib to implement your desired functionality without invasivity
Create and use instance of ScrollController normally.
ScrollController scrollController = ScrollController();
ListView _buildListView() {
return ListView.separated(
controller: scrollController,
...
);
}
Create an instance of ListObserverController pass it to ListViewObserver
ListObserverController observerController = ListObserverController(controller: scrollController);
ListViewObserver(
controller: observerController,
child: _buildListView(),
...
)
Now you can scroll to the specified index position
// Find the specific item index.
final targetIndex = _list.indexOf(specificItem);
// Jump to the specified index position without animation.
observerController.jumpTo(index: targetIndex)
// Jump to the specified index position with animation.
observerController.animateTo(
index: targetIndex,
duration: const Duration(milliseconds: 250),
curve: Curves.ease,
);

Implement setstat and bind variables

I'm trying to get and display 2 variable values from another dart file, ("int myId" and "String myMenu") , these variables are updated with every "onTap" widget, my code works, but only if i do a "hot reload", i think that i need to put a "setstate" somewhere, but i'm having difficulty to implement it.
I think the problem is there, my widget text returns "null" to me, but if I hit the menu button and do a "hot reload", it's ok.
displayText.dart
import 'package:flutter/material.dart';
import './menu.dart';
class display extends StatefulWidget {
int myId;
String myMenu;
display(this.myId, this.myMenu);
#override
_displayState createState() => _displayState();
}
class _displayState extends State<display> {
Future myVarUsed() async {
//Each press on the button return the value
setState(() {
print('myIdDsiplay: ${widget.myId}'); // null
print('myMenuDisplay : ${widget.myMenu}'); // null
});
}
#override
void initState() {
super.initState();
myVarUsed();
}
#override
Widget build(BuildContext context) {
return Container(
color: Colors.blue,
height: 250,
width: 250,
child: Row(
children: [
Text('My ID is : ${widget.myId}'),
Text('My menu is : ${widget.myMenu}'),
],
),
);
}
}
This file contains the menu inside a scrollbar, each button return the ID and the name (of the button) and store it in 2 variable ("int myId" and "String myMenu") that i want to pass.
menu.dart
import 'package:flutter/material.dart';
import './mylist.dart';
import './displayText.dart';
class Menu extends StatefulWidget {
static int myId;
static String myMenu;
#override
_MenuState createState() => _MenuState();
}
class _MenuState extends State<Menu> {
Container scrollList() {
final PageController controller = PageController(initialPage: 1, keepPage: true, viewportFraction: 0.35);
return Container(
color: Colors.red,
height: 90,
child: PageView.builder(
scrollDirection: Axis.horizontal,
controller: controller,
itemCount: listdata.length,
physics: BouncingScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return Container(
child: gestureDetector_Ontap(index),
);
},
),
);
}
GestureDetector gestureDetector_Ontap(int index) {
return GestureDetector(
onTap: () {
Menu.myId = listdata[index].id;
Menu.myMenu = listdata[index].menuObj;
display(Menu.myId, Menu.myMenu);
print('myIDMenu ${Menu.myId}');
print('myMenuMenu ${Menu.myMenu}');
},
child: Container(
alignment: AlignmentDirectional.center,
child: Text(
'${listdata[index].menuObj}',
),
),
);
}
Widget build(BuildContext context) {
return Container(
child: scrollList(),
);
}
}
This file contains my list and his class
mylist.dart
class listModel {
int id;
String menuObj;
listModel(this.id, this.menuObj);
}
List listdata = [
listModel(0, 'Menu01'),
listModel(1, 'Menu02'),
listModel(2, 'Menu03'),
listModel(3, 'Menu04'),
listModel(4, 'Menu05')
];
And the container
main.dart
import 'package:flutter/material.dart';
import './menu.dart';
import './displayText.dart';
import './mylist.dart';
void main() {
runApp(MyHomePage());
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Container(
child: Column(
children: <Widget>[
Menu(),
display(Menu.myId, Menu.myMenu),
],
),
),
),
);
}
}
The problem
You're defining Menu this way:
class Menu extends StatefulWidget {
static int myId;
static String myMenu;
#override
_MenuState createState() => _MenuState();
}
When your app starts, myId and myMenu are uninitialized variables, therefore they're implicitely set to null.
Inside _MyHomePageState, you call
display(Menu.myId, Menu.myMenu)
Since you haven't initialized Menu.myId and Menu.myMenu yet, they're still null.
When you tap the GestureDetector, you initialize Menu.myId and Menu.myMenu this way:
Menu.myId = listdata[index].id;
Menu.myMenu = listdata[index].menuObj;
display(Menu.myId, Menu.myMenu);
print('myIDMenu ${Menu.myId}');
print('myMenuMenu ${Menu.myMenu}');
Now, Menu.myId and Menu.myMenu are defined to non-null values. However, this will not update the Container's display(Menu.myId, Menu.myMenu), so they'll still be null, you need to update it by yourself.
The solution
I've added comments through the code, pointing a better approach:
import 'package:flutter/material.dart';
// Avoid displaying the warning "Name types using UpperCamelCase."
class Display extends StatefulWidget {
// Make these fields final and the constructor const
final int myId;
final String myMenu;
const Display(this.myId, this.myMenu);
#override
_DisplayState createState() => _DisplayState();
}
// Avoid displaying the warning "Name types using UpperCamelCase."
class _DisplayState extends State<Display> {
// You don't need this Future nor this initState
//
// Future myVarUsed() async {
// setState(() {
// print('myIdDsiplay: ${widget.myId}'); // null
// print('myMenuDisplay : ${widget.myMenu}'); // null
// });
// }
//
// #override
// void initState() {
// super.initState();
// myVarUsed();
// }
#override
Widget build(BuildContext context) {
return Container(
color: Colors.blue,
height: 250,
width: 250,
child: Row(
children: [
Text('My ID is : ${widget.myId}'),
Text('My menu is : ${widget.myMenu}'),
],
),
);
}
}
class Menu extends StatefulWidget {
// Avoid using mutable static fields
// static int myId;
// static String myMenu;
// To simplify, you can add a onChanged callback to
// be triggered whenever you change `myId` and `myMenu`
final void Function(int myId, String myMenu) onChanged;
const Menu({this.onChanged});
#override
_MenuState createState() => _MenuState();
}
class _MenuState extends State<Menu> {
Container scrollList() {
final PageController controller = PageController(initialPage: 1, keepPage: true, viewportFraction: 0.35);
return Container(
color: Colors.red,
height: 90,
child: PageView.builder(
scrollDirection: Axis.horizontal,
controller: controller,
itemCount: listdata.length,
physics: BouncingScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return Container(
child: gestureDetectorOntap(index),
);
},
),
);
}
// Avoid displaying the warning "Name non-constant identifiers using lowerCamelCase."
GestureDetector gestureDetectorOntap(int index) {
return GestureDetector(
onTap: () {
// Make these local variables
int myId = listdata[index].id;
String myMenu = listdata[index].menuObj;
// Call the `onChanged` callback
widget.onChanged(myId, myMenu);
// This widget is being thrown away
// display(Menu.myId, Menu.myMenu);
print('myIDMenu $myId');
print('myMenuMenu $myMenu');
},
child: Container(
alignment: AlignmentDirectional.center,
child: Text(
'${listdata[index].menuObj}',
),
),
);
}
Widget build(BuildContext context) {
return Container(
child: scrollList(),
);
}
}
// Avoid the warning "Name types using UpperCamelCase."
class ListModel {
// You can make these fields final and the constructor const
final int id;
final String menuObj;
const ListModel(this.id, this.menuObj);
}
// You can make this list const to avoid modifying it unintentionally later
const List<ListModel> listdata = [
ListModel(0, 'Menu01'),
ListModel(1, 'Menu02'),
ListModel(2, 'Menu03'),
ListModel(3, 'Menu04'),
ListModel(4, 'Menu05')
];
void main() {
runApp(MyHomePage());
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// Create fields to store the current `myId` and current `myMenu`
int myId;
String myMenu;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Container(
child: Column(
children: <Widget>[
// Add the `onChanged` callback here, updating this widget state
Menu(
onChanged: (newMyId, newMyMenu) {
setState(() {
myId = newMyId;
myMenu = newMyMenu;
});
}
),
// Access the current values here
Display(myId, myMenu),
],
),
),
),
);
}
}

List into a class show it after a a clickable ListView.builder in flutter

I created these classes and this list to make it clickable in flutter with a ListView.builder. When I click on a name I take me to the clan page. How do I show the list of members in the clan class and make it tapable to the "Member profile page"? or is there a different way to do it?
These are the classes
class Clan{
String name;int member;DateTime born;
List<MemberClan> listMemberClan;
List<Videogame> listVieogame;
Clan ({this.born,this.member,this.name, this.listMemberClan, this.listVieogame});
}
class MemberClan{
String memberClanName, email; int age;
List<Videogame> memberVideogamelist;
MemberClan({this.age,this.email,this.memberClanName, this.memberVideogamelist});
}
class Videogame{
String videogameName, softwarehouse, type;
Videogame({this.softwarehouse,this.videogameName,this.type});
}
List<Clan> clanList =[
Clan(
name: "Wof",
member: 2,
listMemberClan: [
MemberClan(
memberClanName: "redwolf",
email: "redwolf#email.com",
memberVideogamelist: [
Videogame(
videogameName: "fifa20",
softwarehouse: "Ea",
type: "sport"
),
]
),
MemberClan(
memberClanName: "shaps",
email: "shaps#email.com",
memberVideogamelist: [
Videogame(
videogameName: "fifa21",
softwarehouse: "Ea",
type: "sport"
),
Videogame(
videogameName: "callofduty MW",
softwarehouse: "Activision",
type: "fps"
),
]
),
],
),
Clan(
name: "Ika",
member: 1,
listMemberClan: [
MemberClan(
memberClanName: "stinfo",
email: "stinfo#email.com",
memberVideogamelist: [
Videogame(
videogameName: "Call Of Duty: MW",
softwarehouse: "Activision",
type: "fps"
),
]
),
],
),
];
these are the the simply widget for the list and the clanpage are just a simply example there isn't UI
class ClanList extends StatelessWidget {
final Clan clan;
final MemberClan memberClan;
final Videogame videogame;
const ClanList({Key key, this.clan, this.memberClan, this.videogame})
: super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Expanded(
child: ListView.builder(
itemCount: clanList.length,
itemBuilder: (context, index) => InkWell(onTap: (){Navigator.push(context, MaterialPageRoute(builder: (context)=> ClanPage(clan: clanList[index],)));},
child: ListTile(
title: Text(clanList[index].name),
),
),
),
),
),
);
}
}
class ClanPage extends StatelessWidget {
final Clan clan;
final MemberClan memberClan;
final Videogame videogame;
const ClanPage({Key key, this.clan, this.memberClan, this.videogame})
: super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: [
Text(clan.name),
Text(clan.member.toString()),
//here i want show a clickable list of the member
//and tap or clik on name I want show the member profilepage
],
),
),
);
}
}
In your clan class add the following code:-
class ClanPage extends StatelessWidget {
final Clan clan;
final MemberClan memberClan;
final Videogame videogame;
const ClanPage({Key key, this.clan, this.memberClan, this.videogame})
: super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Expanded(
child: ListView.builder(
itemCount: clan.listMemberClan.length,
itemBuilder: (context, index) => ListTile(
onTap: (){Navigator.push(context, MaterialPageRoute(builder: (context)=> MemberPage(memberClan: clan.listMemberClan[index],)));},
title: Text(clan.listMemberClan[index]),
),
),
),
),
);
}
}
class MemberPage extends StatelessWidget {
final MemberClan memberClan;
const ClanPage({this.memberClan});
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
//show your details here like:-
child:Text(memberClan.email),
)
);
}
}

RangeError (index): Invalid value: Valid value range is empty: 0 returned while using Checkbox and a for loop

class HostAMealCard extends StatefulWidget {
HostAMealCard(this.combo);
final Combo combo;
#override
_HostAMealCardState createState() => _HostAMealCardState();
}
class _HostAMealCardState extends State<HostAMealCard> {
#override
Widget build(BuildContext context) {
return Container(
height: (50 * widget.combo.items.length + 75).toDouble(),
child: Card(
child: ListView.builder(
itemCount: widget.combo.items.length,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return OneMeal(widget.combo, index);
},
)),
);
}
}
class OneMeal extends StatefulWidget {
OneMeal(this.combo, this.index);
final Combo combo;
final int index;
//int count = combo.items.length;
#override
State<StatefulWidget> createState() => OneMealState();
}
class OneMealState extends State<OneMeal> {
List<bool> Vals = new List();
#override
void initState() {
super.initState();
int count = widget.combo.items.length;
for (int i = 0; i < count; i++) { //This for loop gives exception
Vals[i] = false;
}
}
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Align(
child: Text(widget.combo.items[widget.index].item.toString()),
alignment: Alignment(-1, 0),
),
Align(
child: Text(widget.combo.items[widget.index].price.toString()),
alignment: Alignment(0.2, 0)),
Align(
child: Checkbox( //This checkbox gives exception
value: Vals[widget.index],
onChanged: (bool value) {
setState(() {
Vals[widget.index] = value;
});
},
),
alignment: Alignment(0.6, 0.4)),
],
);
}
}
The class HostAMealCard is a card which contains a combination of food items. Each item has a Checkbox associated with it. The number of items in each card is dynamic.
The exceptions are thrown by a for loop and a Checkbox.
Also the class HostAMealCard is returned as the itemBuilder of a FutureBuilder.
Is there a simpler way to achieve what I'm trying to do here?
Vals has length 0, so accessing to any position of it will, of course, throw an exception.
you should do this:
Vals.add(false)
Or even better you could replace the for loop and initialize Vals in your initState this way:
Vals = List<bool>.generate(widget.combo.items.length, (_) => false);