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
Please look at this image Home Page
Now when I scroll the ListView it becomes like this -
Home Page
Now I know the reason why this is happening, it is because I used ListView as a parent to this entire view and added ListView.builder() and other widgets as its child.
What I want is to scroll the ListView.builder() without scrolling the entire page.
For this I first tried to use Column as parent but that ended up giving the overflow pixels error.
And then I set the physics: const NeverScrollableScrollPhysics() inside the parent ListView but after that it made my ListView.builder() to show all of its list items.
Here is my Code for Home Screen
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
child: ListView(
padding: const EdgeInsets.only(top: 45, bottom: 24),
children: [
header(),
const SizedBox(height: 36),
const BalanceCard(),
const SizedBox(height: 36),
Recent()
],
),
),
Align(
alignment: Alignment.bottomCenter,
child: bottomNavigationBar(),
),
],
),
); }
Recent List Code
class RecentItems extends StatefulWidget {
final List<Transaction> transactions;
RecentItems({required this.transactions});
#override
State<RecentItems> createState() => _RecentItemsState();
}
class _RecentItemsState extends State<RecentItems> {
#override
Widget build(BuildContext context) {
return SizedBox(
height: 450,
child: Expanded(child: ListView.builder(
itemBuilder: (context, index) {
final item = widget.transactions[index].toString();
return Dismissible(
direction: DismissDirection.endToStart,
key: UniqueKey(),
onDismissed: (direction) {
setState(() {
widget.transactions.removeAt(index);
});
// Then show a snackbar.
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(content: Text('Transaction Deleted')));
},
background: Container(
color: Colors.red,
alignment: AlignmentDirectional.centerEnd,
child: const Padding(
padding: EdgeInsets.fromLTRB(0.0, 0.0, 15.0, 0.0),
child: Icon(
EvaIcons.trash2,
color: Colors.white,
),
),
),
child: Card(
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
child: ListTile(
leading: CircleAvatar(
radius: 30,
foregroundImage: widget.transactions[index].Image,
backgroundColor: primaryColor,
),
title: Text(
widget.transactions[index].title,
style: const TextStyle(color: secondaryColor),
),
subtitle: Text(
DateFormat.yMMMd().format(widget.transactions[index].date),
),
trailing: Text(
'\$${widget.transactions[index].amount}',
style: const TextStyle(color: secondaryColor),
),
),
),
);
},
itemCount: widget.transactions.length,
),)
);
}
}
Recent Widget -
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Recent Transactions',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: secondaryColor),
),
const SizedBox(height: 5),
RecentItems(transactions: _userTransactions),
],
),
)
The entire screen scrolls because Recent() is included in the same ListView as header() and balanceCard().
Try something like this:
Scaffold(
body: Column(
children: [
Expanded(
child: ListView(
padding: const EdgeInsets.only(top: 45, bottom: 24),
children: [
header(),
const SizedBox(height: 36),
const BalanceCard(),
const SizedBox(height: 36),
],
),
),
// Recent items removed from ListView
Recent(),
Align(
alignment: Alignment.bottomCenter,
child: bottomNavigationBar(),
),
],
),
)
I hope this helps.
By simplifying your code, this is an example of a layout where you have a single Column in the Scaffold. The Column contains some sized, unsized and aligned children.
One child, Recent is a ListView, without explicit height, but wrapped into an Expanded widget. This way it will occupy all the remaining area left by the other children, and it will be scrollable.
(You will run into trouble with this if the children without Recent occupy all the available area.)
Please have a look at this code, you can copy-paste it into a DartPad fiddle:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) => Scaffold(
body: Column(
children: [
const Text('header()'),
const SizedBox(height: 36),
const Text('BalanceCard()'),
const SizedBox(height: 36),
Expanded(child: Recent()),
const Align(
alignment: Alignment.bottomCenter,
child: Text('bottomNavigationBar()'),
),
],
),
);
}
class Recent extends StatelessWidget {
#override
Widget build(BuildContext context) => ListView.builder(
itemCount: 100, itemBuilder: (context, index) => Text('Item $index'));
}
I am trying to create a news app using api provided by newsapi.org
but the content is appearing as follows.. I am using a free api key
The code for the displaying and retrieving the data from api is given below
import 'package:flutter/material.dart';
import 'package:news_api_flutter_package/model/article.dart';
import 'package:news_api_flutter_package/news_api_flutter_package.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
class NewsPage extends StatefulWidget {
const NewsPage({Key? key, required this.category}) : super(key: key);
final String category;
#override
State<NewsPage> createState() => _NewsPageState();
}
class _NewsPageState extends State<NewsPage> {
final NewsAPI _newsAPI = NewsAPI("MyAPIKEY");
final spinkit = const SpinKitSpinningLines(
color: Colors.yellow,
size: 150.0,
);
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<List<Article>>(
future:
_newsAPI.getTopHeadlines(country: "in", category: widget.category),
builder: (context, snapshot) {
if (snapshot.hasData) {
return PageView.builder(
itemCount: snapshot.data!.length,
scrollDirection: Axis.vertical,
itemBuilder: (context, index) {
return Column(
children: [
SizedBox(
height: 250,
width: MediaQuery.of(context).size.width,
child: FittedBox(
fit: BoxFit.fill,
child: Image.network(
snapshot.data![index].urlToImage.toString(),
fit: BoxFit.fill,
)),
),
Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(20),
child: Text(
snapshot.data![index].title.toString(),
style: const TextStyle(fontSize: 22),
),
)),
Padding(
padding: const EdgeInsets.only(left: 20, right: 20),
child: Text(
snapshot.data![index].content.toString(),
style: Theme.of(context).textTheme.subtitle1,
),
)
],
);
});
} else if (snapshot.hasError) {
return Text(snapshot.error.toString());
} else {
return Container(
child: spinkit,
);
}
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.pop(context);
},
backgroundColor: Colors.yellow,
child: const Icon(Icons.arrow_back),
),
);
}
}
Is there any possibility to get the whole content. The api key has been removed for obvious reason
#R3hankhan According to the newsApi docs
https://newsapi.org/docs/endpoints/top-headlines
The response object has a key called totalResults which is an int and shows the number of articles fetched. so in your PageView.builder() itemCount will be snapshot.data!.totalResults (see the docs). And the other property called articles can be used to map over and display the ui accordingly. See the docs for further reference.
I'm currently trying to make a Netflix-style UI in Flutter on my Android TV. I've been struggling with integrating focus navigation for the past few days and figured I'd ask here as there doesn't really seem to be any in-depth tutorials.
Right now I'd like to be able to navigate my ListView Builder using d-pad controls and add a special state to the widget to signify that it's currently selected (enlarged or with a border).
Here's my current code:
class Home extends StatefulWidget {
Home({Key key}) : super(key: key);
#override
HomeState createState() => new HomeState();
}
class HomeState extends State<Home> {
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(left: 8.0, right: 8.0),
child: FutureBuilder(
// an asset :bundle is just the resources used by a given application
future: DefaultAssetBundle.of(context)
.loadString('assets/json/featured.json'),
builder: (context, snapshot) {
// Loading indicator
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
if (snapshot.hasError) {
return Text(snapshot.error); // or whatever
}
var mediaData = json.decode(snapshot.data.toString());
List<Session> mediaDataSession =
(mediaData as List<dynamic>).cast<Session>();
// Pass our array data into the Session class' fromJson method and allow it to be iterable
var decodedData =
mediaData.map((data) => Session.fromJson(data)).toList();
BoxDecoration myBoxDecoration() {
return BoxDecoration(
border: Border.all(),
);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 30.0),
child: Align(
alignment: Alignment.bottomLeft,
child: Text('Featured',
style: TextStyle(
fontWeight: FontWeight.bold,
fontFamily: 'HelveticaNeue',
fontSize: 24.0)),
),
),
Expanded(
// Focus was here before
child: ListView.builder(
itemCount: mediaData.length,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return Align(
alignment: Alignment.topLeft,
child: Container(
margin:
EdgeInsets.only(right: 8.0, top: 4.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment
.start, // Workaround for aligning text
children: [
Container(
// Find a way to render based on focus being true
decoration: myBoxDecoration(),
child: InkWell(
// onTap: () => {},
borderRadius: BorderRadius.circular(4.0),
focusColor: Colors.black,
child: SizedBox(
height: 150.0,
child: ClipRRect(
child: Image.network(
mediaData[index]['image'])),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 6.0),
child: Text(mediaData[index]['name'],
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 17.0,
fontFamily: "HelveticaNeue",
fontWeight: FontWeight.normal)),
)
],
),
),
);
},
),
),
],
);
}),
);
}
}
For reference, I'd like to get behaviour like this video here: https://www.youtube.com/watch?v=l37VYXhRhPQ
Any help would be appreciated!
Here is the source code of the app in the video:
https://gitlab.com/ad-on-is/chillyflix/
I'm Beginner to coding. I have created a Image picker in flutter, I want to use the image picker in many different pages, so I have created a separate class, but when I call the method in other pages, it just open the gallery but,it is not picking the image from gallery and displaying the picked image.There is no any error.
Kindly, help to solve the issue.
Thanks in advance
My Code:
main.dart:
import 'package:flutter/material.dart';
import 'package:project1test/healthscreen_expat.dart';
import 'package:project1test/forms/parkings.dart';
class accomodationform extends StatefulWidget {
String text;
accomodationform(String name) {
text = name;
}
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return MyAppState(text);
}
}
class MyAppState extends State<accomodationform> {
Mod1 mod11 = new Mod1();
String labels;
MyAppState([String label]) {
labels = label;
}
Image1 im = Image1();
final scaffoldkey = new GlobalKey<ScaffoldState>();
final formkey = new GlobalKey<FormState>();
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
body: new Padding(
padding: EdgeInsets.only(left: 20.0, right: 20.0, top: 20),
child: new Form(
key: formkey,
child: ListView(children: <Widget>[
mod11.user(),
]))),
);
}
}
imagepick.dart
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class Mod1 {
var images1accom;
user() {
List<dynamic> img = List();
return Container(
margin: EdgeInsets.only(top: 20, right: 20, left: 20),
padding: EdgeInsets.only(top: 20.0),
width: double.infinity,
height: 150.0,
color: Colors.white70,
child: Center(
child: Row(
//mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
OutlineButton(
onPressed: () async {
images1accom =
await ImagePicker.pickImage(source: ImageSource.gallery);
img.add(images1accom);
},
child: Row(children: <Widget>[
Icon(Icons.camera_alt),
Text(
"Choose File",
style: TextStyle(fontSize: 12.0),
textAlign: TextAlign.end,
)
]),
borderSide: BorderSide(color: Colors.pink),
textColor: Colors.pinkAccent,
padding: EdgeInsets.all(10.0),
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(10.0),
)),
Expanded(
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: img.length,
itemBuilder: (BuildContext c, int position) {
return (Image.file(
img[position],
fit: BoxFit.cover,
repeat: ImageRepeat.noRepeat,
));
},
),
),
],
),
),
);
}
}
Well, I think maybe it would be good for you to study object-oriented programming, dart, and how Flutter works.
Initially, I need to tell you that you simply cannot do what you are trying to do, insert widgets within classes, with separate functions, and try to instantiate it within a Stateful.
Widgets must not be instantiated, and if you want to componentize something, you must do it using a stateful or stateless class, not an ordinary class.
Your Mod class should look like this:
class ChoosePic extends StatefulWidget {
ChoosePic({Key key}) : super(key: key);
#override
_ChoosePicState createState() => _ChoosePicState();
}
class _ChoosePicState extends State<ChoosePic> {
List<dynamic> img = List();
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(top: 20, right: 20, left: 20),
padding: EdgeInsets.only(top: 20.0),
width: double.infinity,
height: 150.0,
color: Colors.white70,
child: Center(
child: Row(
//mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
OutlineButton(
onPressed: () async {
File images1accom =
await ImagePicker.pickImage(source: ImageSource.gallery);
img.add(images1accom);
setState(() {});
},
child: Row(children: <Widget>[
Icon(Icons.camera_alt),
Text(
"Choose File",
style: TextStyle(fontSize: 12.0),
textAlign: TextAlign.end,
)
]),
borderSide: BorderSide(color: Colors.pink),
textColor: Colors.pinkAccent,
padding: EdgeInsets.all(10.0),
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(10.0),
)),
Expanded(
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: img.length,
itemBuilder: (BuildContext c, int position) {
return (Image.file(
img[position],
fit: BoxFit.cover,
repeat: ImageRepeat.noRepeat,
));
},
),
),
],
),
),
);
}
}
And you can to use it with
child: ChoosePic()
I have no idea why you are using a listview in your main class, but if it is really necessary, you would do this:
ListView(children: <Widget>[
ChoosePic(),
])
If you want the value of img, you will need a state manager for this:
Using Get (add this package to pubspec):
https://pub.dev/packages/get
Create class with shared state:
class Controller extends GetController {
static Controller get to => Get.find();
List<dynamic> img = List();
takeImage() {
File images1accom =
await ImagePicker.pickImage(source: ImageSource.gallery);
img.add(images1accom);
update(this);
}
}
// use it:
class ChoosePic extends StatefulWidget {
ChoosePic({Key key}) : super(key: key);
#override
_ChoosePicState createState() => _ChoosePicState();
}
class _ChoosePicState extends State<ChoosePic> {
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(top: 20, right: 20, left: 20),
padding: EdgeInsets.only(top: 20.0),
width: double.infinity,
height: 150.0,
color: Colors.white70,
child: Center(
child: Row(
//mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
OutlineButton(
onPressed: () async {
Controller.to.takeImage();
},
child: Row(children: <Widget>[
Icon(Icons.camera_alt),
Text(
"Choose File",
style: TextStyle(fontSize: 12.0),
textAlign: TextAlign.end,
)
]),
borderSide: BorderSide(color: Colors.pink),
textColor: Colors.pinkAccent,
padding: EdgeInsets.all(10.0),
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(10.0),
)),
Expanded(
child: GetBuilder<Controller>(
init: Controller(),
builder: (controller) {
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: controller.img.length,
itemBuilder: (BuildContext c, int position) {
return (Image.file(
controller.img[position],
fit: BoxFit.cover,
repeat: ImageRepeat.noRepeat,
));
},
);
}
),
),
],
),
),
);
}
}
Now you can get the image list from anywhere in your code with:
on widget three controller.img;
GetBuilder<Controller>(
init: Controller(),
builder: (controller) {
Example:
GetBuilder<Controller>(
init: Controller(),
builder: (controller) {
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: controller.img.length,
itemBuilder: (BuildContext c, int position) {
return (Image.file(
controller.img[position],
fit: BoxFit.cover,
repeat: ImageRepeat.noRepeat,
));
},
);
And take it out of the widget tree with:
Controller.to.img
Note: init: Controller() can only be used once, if you need GetBuilder elsewhere, don't use it. Use, for example:
GetBuilder<Controller>(
builder: (controller) {
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: controller.img.length,
itemBuilder: (BuildContext c, int position) {
return (Image.file(
controller.img[position],
fit: BoxFit.cover,
repeat: ImageRepeat.noRepeat,
));
},
);
Well, I shouldn't answer that, as it qualifies as a general question, but since you are a beginner, I answered to help you, in detail. I hope you understand the basics soon, and become a great developer someday.
Welcome to Flutter!
You need to create a separate widget for Mod1 class.
MyAppState
Widget build(BuildContext context) {
return Scaffold(
body: new Padding(
padding: EdgeInsets.only(left: 20.0, right: 20.0, top: 20),
child: new Form(key: formkey, child: Mod1())),
);
}
Mod1 widget
class Mod1 extends StatefulWidget {
#override
State<StatefulWidget> createState() => Mod1State();
}
class Mod1State extends State<Mod1> {
var images1accom;
List<dynamic> img = List();
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(top: 20, right: 20, left: 20),
padding: EdgeInsets.only(top: 20.0),
width: double.infinity,
height: 150.0,
color: Colors.white70,
child: Center(
child: Row(
//mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
OutlineButton(
onPressed: () async {
images1accom =
await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
img.add(images1accom);
});
},
child: Row(children: <Widget>[
Icon(Icons.camera_alt),
Text(
"Choose File",
style: TextStyle(fontSize: 12.0),
textAlign: TextAlign.end,
)
]),
borderSide: BorderSide(color: Colors.pink),
textColor: Colors.pinkAccent,
padding: EdgeInsets.all(10.0),
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(10.0),
)),
Expanded(
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: img.length,
itemBuilder: (BuildContext c, int position) {
return (Image.file(
img[position],
fit: BoxFit.cover,
repeat: ImageRepeat.noRepeat,
));
},
),
),
],
),
),
);
}
}
if you want to use a method in different pages you can use Providers