Related
So I'm tring to make an app to show a detail card view page when I click on the gif of the character, so i'm trying to implement the ListView.build() inside an expand that is inside a column. but it gives me this error FlutterError (BoxConstraints has NaN values in minHeight and maxHeight.
The offending constraints were:
BoxConstraints(w=Infinity, NaN<=h<=NaN; NOT NORMALIZED))
here it's my code:
import 'package:flutter/material.dart';
import 'package:vertical_card_pager/vertical_card_pager.dart';
import 'models/hero_model.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Valorant Agents',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
alert(String msg) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(msg),
action: SnackBarAction(
label: "FECHAR",
onPressed: () => ScaffoldMessenger.of(context).hideCurrentSnackBar(),
),
));
}
//ImagesController _imagesController = Get.find();
//List for agents and respective gif for each one.
final List<HeroModel> heros = [
HeroModel("JETT", "images/jett_valo.gif"),
HeroModel("KILLJOY", "images/killjoy_valo.gif"),
HeroModel("SAGE", "images/sage_valo.gif"),
HeroModel("SOVA", "images/sova_valo.gif"),
HeroModel("VIPER", "images/viper_valo.gif"),
HeroModel("RAZE", "images/raze_valo.gif"),
HeroModel("YORU", "images/yoru_valo.gif"),
HeroModel("BREACH", "images/breach_valo.gif"),
HeroModel("ASTRA", "images/astra_valo.gif"),
HeroModel("CYPHER", "images/cypher_valo.gif"),
HeroModel("OMEN", "images/omen_valo.gif"),
HeroModel("PHOENIX", "images/phoenix_valo.gif"),
HeroModel("SKYE", "images/skye_valo.gif"),
];
#override
//Head Logo
Widget build(BuildContext context) {
// ImagesController _imagesController = Get.find();
return Scaffold(
backgroundColor: Colors.black38,
body: SafeArea(
child: Column(
children: [
SizedBox(
width: double.infinity,
height: 70,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 5),
child: Center(
child: Image.asset(
"images/logo.png",
fit: BoxFit.cover,
),
),
),
),
// CardView
Expanded(
child: ListView.builder(
itemCount: heros.length,
itemBuilder: (context, index) {
return VerticalCardPager(
titles: [for (var hero in heros) hero.title],
images: [
for (var hero in heros)
Hero(
tag: hero.title,
child: ClipRRect(
borderRadius: BorderRadius.circular(20.0),
child: Image.asset(
hero.image,
fit: BoxFit.cover,
),
),
),
],
textStyle: const TextStyle(
color: Colors.white, fontWeight: FontWeight.bold),
initialPage: 2,
align: ALIGN.CENTER,
);
}),
)
],
)));
}
}
You don't needed to use VerticalCardPager inside listView, try this:
Expanded(
child: Container(
child: VerticalCardPager(
titles: [for (var hero in heros) hero.title],
images: [
for (var hero in heros)
Hero(
tag: hero.title,
child: ClipRRect(
borderRadius: BorderRadius.circular(20.0),
child: Image.asset(
hero.image,
fit: BoxFit.cover,
),
),
),
],
textStyle: const TextStyle(
color: Colors.white, fontWeight: FontWeight.bold),
initialPage: 2,
align: ALIGN.CENTER,
),
),
)
The issue is with the Expanded widget. You are using the Expanded widget inside the Column whose height is not fixed. You can resolve it by either wrapping column inside SizedBox and setting some height or using shrinkWrap inside ListView.builder and removing the Expanded widget.
Solution 1
SizedBox(
height: MediaQuery.of(context).size.height,
child: Column(
children: [
SizedBox(
width: double.infinity,
height: 70,
...
),
// CardView
Expanded(
child: ListView.builder(
itemCount: heros.length,
itemBuilder: (context, index) {
...
}),
)
],
)
Solution 2:
SingleChildScrollView(
child: Column(
children: [
SizedBox(
width: double.infinity,
height: 70,
...
),
// CardView
ListView.builder(
itemCount: heros.length,
shrinkWrap: true, // add this
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
...
})
],
),
)
P.S:- If you want to use 2nd solution you need to restrict ListView scrolling by setting physics to NeverScrollableScrollPhysics and wrapping Column with SingleChildScrollView
I Had Question For how create Scroll List Like this
Flutter Scroll List Over Header
According to the answers given, I used DraggableScrollableSheet for implementing this scroll view
but now i have new problem
The Result is here:
now I need to when im scrolling the top Child Stay On Top, like a header
how can do this?
Here is my Code
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
double height = MediaQuery.of(context).size.height;
AppController appController = Provider.of<AppController>(context);
HomeController homeController = Provider.of<HomeController>(context);
String selectedCategory = homeController.selectedCategory;
return SafeArea(
child: Container(
//height: 450,
width: double.infinity,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/home_header.png'),
alignment: Alignment.topCenter,
)),
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
flexibleSpace: Padding(
padding: const EdgeInsets.only(left: 20, right: 20),
child: ChiscoAppbar(
icon: MENU,
iconAlignment: Alignment.centerLeft,
title: 'خانه',
onClick: () {
Navigator.pushNamed(context, '/account');
},
),
),
),
backgroundColor: Colors.transparent,
body: Stack(
children: [
Positioned(
child: Container(
color: Colors.transparent,
height: 200,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Expanded(
flex: 3,
child: Align(
alignment: Alignment.center,
child: ChiscoText(
text: 'دستگاههای هوشمند چیسکو',
fontWeight: FontWeight.w500,
textColor: Colors.white,
fontSize: 16,
)),
),
Expanded(
flex: 1,
child: Padding(
padding: EdgeInsets.only(left: 20, right: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: const [
HeaderItem(
titleText: 'کنترلر',
icon: COOLER,
counterText: '2',
),
HeaderItem(
titleText: 'سه راهی',
icon: SOCKET,
counterText: '2',
)
],
),
)),
],
),
),
),
Positioned(
child: DraggableScrollableSheet(
expand: true,
minChildSize: 0.70,
maxChildSize: 0.95,
initialChildSize: 0.70,
builder: (context, scrollController) {
return SingleChildScrollView(
controller: scrollController,
child: Container(
decoration: BoxDecoration(
color: Colors.blue[100],
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(25),
topRight: Radius.circular(25))),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListHandlerView(),
Container(
margin: const EdgeInsets.fromLTRB(20, 8, 20, 10),
height: 30,
child: ListView.builder(
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
itemCount: appController
.listOfDevicesCategory.length,
scrollDirection: Axis.horizontal,
primary: true,
addSemanticIndexes: false,
itemBuilder: (context, index) {
String category = appController
.listOfDevicesCategory[index];
return CategoryListItem(
isSelected: selectedCategory == category,
category: category,
);
}),
),
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: 25,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text('Item $index'));
},
),
],
),
),
);
},
),
)
],
),
floatingActionButton: Container(
margin: const EdgeInsets.only(bottom: 16),
child: const ChiscoSpeedDial()),
floatingActionButtonLocation:
FloatingActionButtonLocation.startDocked,
),
),
);
}
}
I think it is better to use bottom from SliverAppBar. Run below widget to see the result
class DAX extends StatefulWidget {
DAX({Key? key}) : super(key: key);
#override
State<DAX> createState() => _DAXState();
}
class _DAXState extends State<DAX> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: CustomScrollView(
slivers: [
SliverAppBar(
expandedHeight: 200,
pinned: true,
backgroundColor: Colors.blue,
elevation: 0,
bottom: PreferredSize(
preferredSize: Size.fromHeight(60),
child: ColoredBox(
color: Colors.blue,
child: Container(
clipBehavior: Clip.hardEdge,
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12),
topRight: Radius.circular(12),
),
color: Colors.white,
),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: List.generate(
12,
(index) => Chip(
label: Text("chip $index"),
),
),
),
),
),
)),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => Container(
alignment: Alignment.center,
height: 100,
child: Text("$index"),
),
),
),
],
),
),
);
}
}
I need to implement the pull to refresh action, on a future builder using refresh indicator widget. First of all, i know there are multiple threads on this topic. But I still couldn't. Here are my codes on the subject:
final QuerySnapshot<Map<String, dynamic>> querySnapshot =
snapshot.data as QuerySnapshot<Map<String, dynamic>>;
return ListView(
physics: const BouncingScrollPhysics(),
children: <Widget>[
Container(
margin: const EdgeInsets.only(top: 28.8, bottom: 16.8),
height: 714.8,
child: FutureBuilder<List<FirabaseWeatherModel>>(
future: chnageList(querySnapshot),
builder: (BuildContext context,
AsyncSnapshot<dynamic> snapshot) {
if (snapshot.hasData) {
ListView.builder(
itemCount: firabseModelList.length,
padding:
const EdgeInsets.only(left: 28.8, right: 12),
scrollDirection: Axis.vertical,
physics: const BouncingScrollPhysics(),
itemBuilder: (context, index) {
return Container(
height: 214.8,
width: 188.4,
margin: const EdgeInsets.only(
right: 16.8, bottom: 50),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(9.6),
image: DecorationImage(
fit: BoxFit.cover,
image: CachedNetworkImageProvider(
querySnapshot.docs[index]
.data()['image'],
maxHeight: 200,
maxWidth: 200),
),),
child: Stack(
children: <Widget>[
GestureDetector(
onTap: () => gotoPage(querySnapshot
.docs[index]
.data()['title'])),
],),);},);
} else if (snapshot.connectionState ==
ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);}
return ListView.builder(
itemCount: firabseModelList.length,
padding: const EdgeInsets.only(left: 28.8, right: 12),
scrollDirection: Axis.vertical,
physics: const BouncingScrollPhysics(),
itemBuilder: (context, index) {
return Container(
height: 214.8,
width: 188.4,
margin: const EdgeInsets.only(
right: 16.8, bottom: 50),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(9.6),
image: DecorationImage(
fit: BoxFit.cover,
image: CachedNetworkImageProvider(
querySnapshot.docs[index].data()['image'],
maxHeight: 200,
maxWidth: 200),
),),
child: Stack(
children: <Widget>[
GestureDetector(
onTap: () => gotoPage(querySnapshot
.docs[index]
.data()['title'])),
Positioned(
child: ClipRRect(
child: Container(
height: 80,
alignment: Alignment.centerLeft,
child: Column(
children: [
Align(
child: Container(
alignment: Alignment.topCenter,
child: Text(
querySnapshot.docs[index]
.data()['tr'],
style: const TextStyle(
fontSize: 15,
),),),),
Row(
children: <Widget>[
Expanded(
child: getImage(
querySnapshot.docs[index]
.data()['zposition1']
.toString(),
150),
),],),],),),),),],),);},);}),),],);
I have uploaded all the code in case you want to try it yourself using all the codes. Where should i use these refresh indicator codes:
RefreshIndicator(
onRefresh: () {},),
add key
GlobalKey _key = GlobalKey();
Then assign the previous key to the top widget
return RefreshIndicator(
onRefresh: _refresh,
child: Container(
key: _key,
child: ListView(
physics: AlwaysScrollableScrollPhysics(),
children: [
// do your stuff
],
),
),
);
Then refresh function, as you should update the key
Future<void> _refresh() async {
if (mounted) {
_key = GlobalKey();
setState(() {});
}
Future.value(null);
}
I wanted to add a container widget in the GridView when a button is clicked. I was able to do this with the column widget but could not do it with GridView.
import 'package:flutter/material.dart';
List<Widget> gridChild = [
Container(
margin: EdgeInsets.all(8.0),
width: 30.0,
height: 50.0,
color: Colors.green,
),
Container(
margin: EdgeInsets.all(8.0),
width: 30.0,
height: 50.0,
color: Colors.green,
),
Container(
margin: EdgeInsets.all(8.0),
width: 30.0,
height: 50.0,
color: Colors.green,
),
Container(
margin: EdgeInsets.all(8.0),
width: 30.0,
height: 50.0,
color: Colors.green,
),
Container(
margin: EdgeInsets.all(8.0),
width: 30.0,
height: 50.0,
color: Colors.green,
),
];
class Grid extends StatefulWidget {
#override
_GridState createState() => _GridState();
}
class _GridState extends State<Grid> {
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.red,
child: Icon(Icons.add),
onPressed: () {
setState(() {
gridChild.add(Container(
margin: EdgeInsets.all(8.0),
width: 30.0,
height: 50.0,
color: Colors.green,
));
print(gridChild.length);
});
},
),
body: Container(
child: GridView.count(
crossAxisCount: 2,
children: gridChild,
),
),
);
}
}
What I did was that I added a container in the widget list. The length of the list increases as I click the botton but the container was not added on the screen. It didn't work even though I put the function inside the setState().
I would really appreciate your help.
This works...
class Grid extends StatefulWidget {
#override
_GridState createState() => _GridState();
}
class _GridState extends State<Grid> {
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.red,
child: Icon(Icons.add),
onPressed: () {
setState(() {
gridChild.add(Container(
margin: EdgeInsets.all(8.0),
width: 30.0,
height: 50.0,
color: Colors.green,
));
});
},
),
body: Container(
child: GridView.count(
crossAxisCount: 2,
children: List.generate(gridChild.length, (index) => gridChild[index]),
),
),
);
}
}
Output:
Use GridView.builder in the body. It should fix your problem. I don't really know why, but I know it works. Hopefully someone can update this answer and provide an explanation.
GridView.builder(
itemCount: gridChild.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemBuilder: (BuildContext context, int index){
return gridChild[index];
},
),
You can do it by calling the setstate method.
while clicking on the button just add a widget to the list and use the setstate after adding to the list. Basically setstate will rebuild the screen.
Can you help me with my problem? I can create data from a textfield in my flutter app and that data goes inside my firebase collection. What I want to happen now is how can I read and display that Data inside Card with a Container child in my flutter app?
What I want is that data to be OVERLAYED or ON-TOP of the image
my code for that is here:
import 'package:flutter/material.dart';
import 'package:vmembershipofficial/Screens/discount_clicked.dart';
class DiscountCarousel extends StatelessWidget {
const DiscountCarousel({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
height: 220.0,
child: ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: 5,
itemBuilder: (BuildContext context, int posiition) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 5.0),
child: InkWell(
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => DiscountClicked(),
),
);
},
child: Card(
child: Column(
children: <Widget>[
Container(
height: 190.0,
width: 300.0,
child: ClipRRect(
borderRadius: new BorderRadius.circular(10.0),
child: Image.network("https://images.pexels.com/photos/2529787/pexels-photo-2529787.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260", fit: BoxFit.cover)),
)
],
),),
),
);
},
)
);
}
}