ListView with favorite items - flutter

I have a ListView.builder with Items and we can click on a heart to add to favorite. I want to put all Items which were add to Favorite in an other ListView.builder in an other screen. I want too the Favorite items can be supressed of the Favorite ListView by click on the heart. How I can do that? This is my code :
Home_screen.dart
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import '../recyclerview/data.dart';
import 'package:chrolix/constants.dart';
import 'package:flutter_countdown_timer/flutter_countdown_timer.dart';
int itemCount = item.length;
List<bool> selected = new List<bool>();
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
initState() {
for (var i = 0; i < itemCount; i++) {
selected.add(false);
}
super.initState();
}
Icon notFavorite = Icon(Icons.favorite_border, size: 32,);
Icon inFavorite = Icon(Icons.favorite, size: 32,);
#override
Widget build(BuildContext context) {
return new Scaffold(
body: ListView.builder(
scrollDirection: Axis.vertical,
physics: BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
itemCount: itemCount,
itemBuilder: (BuildContext context, int index) {
return Container(
child: new Row(
children: <Widget>[
//Image
new Container(
margin: new EdgeInsets.only(top: 5.0, left: 0.0),
child: new CachedNetworkImage(
imageUrl: item[index].imageURL,
height: MediaQuery.of(context).size.width / 3,
width: MediaQuery.of(context).size.width / 2,
fit: BoxFit.cover,
),
),
new Container(
height: MediaQuery.of(context).size.width / 3,
width: MediaQuery.of(context).size.width / 2,
child : new Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
//Text
new Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Spacer(),
//Titre
Container(
padding: const EdgeInsets.only(top: 15.0 ),
child: Text(
item[index].title,
style: kItemTitle,
),
),
//Decription
Container(
padding: const EdgeInsets.only(left: 10.0, top: 15.0),
child:Text(
item[index].description,
style: kItemDescription,
),
),
Spacer(),
],
),
Container(
padding: const EdgeInsets.only(top: 10.0),
child: CountdownTimer(
daysSymbol: new Text("j "),
hoursSymbol: new Text(" : "),
minSymbol: new Text(" : "),
secSymbol: new Text(""),
endTime: item[index].countdown,
textStyle: TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
onEnd: () {
print('onEnd');
},
),
),
Container(
padding: const EdgeInsets.only(left: 8.0, top: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
GestureDetector(
child: selected.elementAt(index) ? inFavorite : notFavorite,
onTap: () {
setState(() {
selected[index] = !selected.elementAt(index);
});
},
),
],),
),
],),
),
],
),
);
}
)
);
}
}
Favorite_screen.dart
import 'package:flutter/material.dart';
import 'package:chrolix/constants.dart';
import 'package:chrolix/nav.dart';
import 'package:get/get.dart';
class Favoris extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: //Put here the LisView.builder with the favorite items
)
}
}
I have don't seen other questions that can answer to mine. Thanks !
Update : I have used provider's package

The recommanded way to do this is to use provider. This is used to share variables to multiple widget down the tree.
This takes more than a StackOverflow answer to write so I will link you to a relevant article from flutter which basically explain everything you want to do:
Here is is.
If the link is broken you can find it by searching "Simple app state management flutter"

Related

Flutter : Horizontally and Vertically Scrolling Time Table with two sided header

In my flutter application I want to create a timetable widget as below which will scroll horizontally and vertically with corresponding heading. The timetable should have 'Day' as horizontal heading and 'Period' as vertical heading. During horizontal scrolling the 'Period' header should freeze and horizontal 'Day' header should scroll with data. Similarly, during vertical scrolling the 'Day' header should freeze and vertical 'Period' header should scroll with data. How can I achieve a widget like that.Please help..
In Android we can obtain the above type of scrolling by extending HorizontalScrollView & VerticalScrollView.
You can archive this using nested listView widgets.
You can try this approach:
class TimeTableView extends StatefulWidget {
const TimeTableView({super.key});
#override
State<TimeTableView> createState() => _TimeTableViewState();
}
class _TimeTableViewState extends State<TimeTableView> {
final periodsSlots = 15;
final double containerHeight = 55.0;
final double containerWidth = 80;
final days = [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
];
final subjects = [
"Maths",
"Hindi",
"English",
"Chemistry",
"History",
"Geography",
];
late ScrollController mainController;
late ScrollController secondController;
#override
void initState() {
super.initState();
secondController = ScrollController();
mainController = ScrollController()
..addListener(() {
if (mainController.hasClients && secondController.hasClients) {
secondController.jumpTo(mainController.offset);
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Time Table"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: PageView(
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
// Top header View
SizedBox(
height: containerHeight,
width: containerWidth,
child: CustomPaint(
painter: RectanglePainter(),
child: Stack(
children: const [
Align(
alignment: Alignment.topRight,
child: Padding(
padding: EdgeInsets.all(4.0),
child: Text("Day"),
),
),
Align(
alignment: Alignment.bottomLeft,
child: Padding(
padding: EdgeInsets.all(4.0),
child: Text("Period"),
),
),
],
),
),
),
Expanded(
child: SizedBox(
height: containerHeight,
child: SingleChildScrollView(
physics: const ClampingScrollPhysics(),
padding: EdgeInsets.zero,
scrollDirection: Axis.horizontal,
controller: mainController,
child: Row(
children: List<Widget>.generate(
days.length,
(index) => Container(
height: containerHeight,
width: containerWidth,
color: bgColorHeader(index),
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 8),
child: Center(child: Text(days[index])),
),
),
),
),
),
),
)
],
),
SizedBox(
// Added fixed size to scroll listView horizontal
height: 500,
child: ListView.builder(
physics: const ClampingScrollPhysics(),
padding:
EdgeInsets.zero, // remove listview default padding.
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: periodsSlots,
itemBuilder: (context, index) => Container(
height: containerHeight,
width: containerWidth,
color: bgColorHeader(index),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
// period header
Padding(
padding: EdgeInsets.zero,
child: SizedBox(
width: containerWidth,
height: containerHeight,
child: Center(child: Text("period ${index + 1}")),
),
),
// period subjects
Expanded(
child: SizedBox(
height: containerHeight,
child: SingleChildScrollView(
physics: const ClampingScrollPhysics(),
padding: EdgeInsets.zero,
scrollDirection: Axis.horizontal,
controller: secondController,
child: Row(
children: List<Widget>.generate(
subjects.length,
(index) => Container(
color: Colors.white,
child: Container(
height: containerHeight,
width: containerWidth,
color: bgColorSubject(index),
child: Center(
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 4),
child: Text(subjects[index]),
)),
),
),
),
),
),
),
)
],
),
),
),
)
],
),
],
),
),
);
}
// Alternate background colors
Color bgColorHeader(int index) =>
index % 2 == 0 ? Colors.cyan.withOpacity(0.5) : Colors.cyanAccent;
Color bgColorSubject(int index) =>
index % 2 == 0 ? Colors.grey.withOpacity(0.5) : Colors.grey;
}
// Draw cross line from top left container
class RectanglePainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
final backgroundPaint = Paint()
..color = Colors.cyanAccent
..strokeWidth = 2.0
..strokeCap = StrokeCap.round;
final crossLine = Paint()
..color = Colors.white
..strokeWidth = 2.0
..strokeCap = StrokeCap.round;
// Draw the rectangle
canvas.drawRect(Offset.zero & size, backgroundPaint);
// Draw the cross line
canvas.drawLine(Offset.zero, Offset(size.width, size.height), crossLine);
//canvas.drawLine(Offset(0, size.height), Offset(size.width, 0), crossLine);
}
#override
bool shouldRepaint(RectanglePainter oldDelegate) => false;
}
Scrolling widgets will create a default scroll controller (ScrollController class) if none is provided. A scroll controller creates a ScrollPosition to manage the state specific to an individual Scrollable widget.
To link our scroll controllers we’ll use linked_scroll_controller, a scroll controller that allows two or more scroll views to be in sync.
import 'package:flutter/material.dart';
import 'package:linked_scroll_controller/linked_scroll_controller.dart';
class ScrollDemo extends StatefulWidget {
#override
_ScrollDemoState createState() => _ScrollDemoState();
}
class _ScrollDemoState extends State<ScrollDemo> {
final List<String> colEntries = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split('');
final List<String> rowEntries =
Iterable<int>.generate(15).map((e) => e.toString()).toList();
late LinkedScrollControllerGroup _horizontalControllersGroup;
late ScrollController _horizontalController1;
late ScrollController _horizontalController2;
late LinkedScrollControllerGroup _verticalControllersGroup;
late ScrollController _verticalController1;
late ScrollController _verticalController2;
#override
void initState() {
super.initState();
_horizontalControllersGroup = LinkedScrollControllerGroup();
_horizontalController1 = _horizontalControllersGroup.addAndGet();
_horizontalController2 = _horizontalControllersGroup.addAndGet();
_verticalControllersGroup = LinkedScrollControllerGroup();
_verticalController1 = _verticalControllersGroup.addAndGet();
_verticalController2 = _verticalControllersGroup.addAndGet();
}
#override
void dispose() {
_horizontalController1.dispose();
_horizontalController2.dispose();
_verticalController1.dispose();
_verticalController2.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('sync scroll demo'),
),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Container(
width: 75,
height: 75,
color: Colors.grey[200],
),
const SizedBox(width: 10),
Container(
height: 75,
width: 400,
color: Colors.blue[100],
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
controller: _horizontalController2,
child: HeaderContainer(rowEntries: rowEntries),
),
)
],
),
const SizedBox(height: 10),
Row(
children: <Widget>[
Container(
width: 75,
height: 400,
color: Colors.blue[100],
child: SingleChildScrollView(
controller: _verticalController2,
child: ColumnContainer(
colEntries: colEntries,
),
),
),
const SizedBox(width: 10),
SizedBox(
width: 400,
height: 400,
child: SingleChildScrollView(
controller: _verticalController1,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
controller: _horizontalController1,
child: BodyContainer(
rowEntries: rowEntries,
colEntries: colEntries,
),
),
),
)
],
),
],
),
),
),
);
}
}
class ColumnContainer extends StatelessWidget {
final List<String> colEntries;
const ColumnContainer({
Key? key,
required this.colEntries,
}) : super(key: key);
#override
Widget build(BuildContext context) {
int numberOfRows = colEntries.length;
return Column(
children: List.generate(
numberOfRows,
(i) {
return Container(
height: 75,
width: 75,
decoration: BoxDecoration(border: Border.all(color: Colors.white)),
child: Center(child: Text(colEntries[i])),
);
},
),
);
}
}
class HeaderContainer extends StatelessWidget {
final List<String> rowEntries;
const HeaderContainer({
Key? key,
required this.rowEntries,
}) : super(key: key);
#override
Widget build(BuildContext context) {
int _numberOfColumns = rowEntries.length;
return Row(
children: List.generate(
_numberOfColumns,
(i) {
return Container(
height: 75,
width: 75,
decoration: BoxDecoration(border: Border.all(color: Colors.white)),
child: Center(child: Text(rowEntries[i])),
);
},
),
);
}
}
class BodyContainer extends StatelessWidget {
final List<String> colEntries;
final List<String> rowEntries;
const BodyContainer({
Key? key,
required this.colEntries,
required this.rowEntries,
}) : super(key: key);
#override
Widget build(BuildContext context) {
int _numberOfColumns = rowEntries.length;
int _numberOfLines = colEntries.length;
return Column(
children: List.generate(_numberOfLines, (y) {
return Row(
children: List.generate(_numberOfColumns, (x) {
return TableCell(item: "${colEntries[y]}${rowEntries[x]}");
}),
);
}),
);
}
}
class TableCell extends StatelessWidget {
final String item;
const TableCell({
Key? key,
required this.item,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
height: 75,
width: 75,
decoration: BoxDecoration(border: Border.all(color: Colors.grey)),
child: Center(child: Text(item)),
);
}
}
I found these solutions from these 2 links.
Flutter: How to create linked scroll widgets
Flutter: Creating a two-direction scrolling table with a fixed head and column

Error show during compile time: The method '[]' was called on null. Receiver: null

I am getting an error with a single listing page or detailed page.
It shows the method [] was called on null.
But is as defined some itemData in main dart file it also showa same error. please help me to solve this error.
this is my DetailPage.dart file
import 'package:flutter/material.dart';
import 'package:uidesign/custom/BorderIcon.dart';
import 'package:uidesign/custom/OptionButton.dart';
import 'package:uidesign/utils/constants.dart';
import 'package:uidesign/utils/custom_functions.dart';
import 'package:uidesign/utils/widget_functions.dart';
class DetailPage extends StatelessWidget {
final dynamic itemData;
const DetailPage({super.key, #required this.itemData});
//DetailPage({Key? key,#required this.itemData}) : super(key: key);
#override
Widget build(BuildContext context){
final Size size = MediaQuery.of(context).size;
final ThemeData themeData = Theme.of(context);
final double padding = 25;
final sidePadding = EdgeInsets.symmetric(horizontal: padding);
return SafeArea(
child: Scaffold(
backgroundColor: COLOR_WHITE,
body: Container(
width: size.width,
height: size.height,
child: Stack(
children: [
SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Stack(
children: [
Image.asset(itemData["image"]),
Positioned(
width: size.width,
top: padding,
child: Padding(
padding: sidePadding,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: (){
Navigator.pop(context);
},
child: BorderIcon(
padding: new EdgeInsets.all(0.0),
height: 50,
width: 50,
child: Icon(
Icons.keyboard_backspace, color:COLOR_BLACK,
),
),
),
BorderIcon(
padding: new EdgeInsets.all(0.0),
width: 50,
height: 50,
child: Icon(Icons.favorite_border, color: COLOR_BLACK),
),
],
),
),
),
],
),
addVerticalSpace(padding),
Padding(
padding: sidePadding,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("${formatCurrency(itemData["amount"])}",style: themeData.textTheme.headline1,),
addVerticalSpace(5),
Text("\$${itemData["address"]}",style: themeData.textTheme.subtitle2,),
]
),
BorderIcon(
width: 0,
height: 0,
child: Text("20 Hours ago",style: themeData.textTheme.headline5,),padding: const EdgeInsets.symmetric(vertical: 15,horizontal: 15),
)
],
),
),
addVerticalSpace(padding),
Padding(
padding: sidePadding,
child: Text("House Information",style: themeData.textTheme.headline4,),
),
addVerticalSpace(padding),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
physics: BouncingScrollPhysics(),
child: Row(
children: [
InformationTile(content: "${itemData["area"]}",name: "Square Foot",),
InformationTile(content: "${itemData["bedrooms"]}",name: "Bedrooms",),
InformationTile(content: "${itemData["bathrooms"]}",name: "Bathrooms",),
InformationTile(content: "${itemData["garage"]}",name: "Garage",)
],
),
),
addVerticalSpace(padding),
Padding(
padding: sidePadding,
child: Text(
itemData["description"],
textAlign: TextAlign.justify,
style: themeData.textTheme.bodyText2,
),
),
addVerticalSpace(200),
],
),
),
Positioned(
bottom: 20,
width: size.width,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
OptionButton(text: "Message",icon: Icons.message,width: size.width*0.35,),
addHorizontalSpace(10),
OptionButton(text: "Call",icon: Icons.call,width: size.width*0.35,),
],
),
),
],
),
),
),
);
}
}
class InformationTile extends StatelessWidget{
final String content;
final String name;
const InformationTile({super.key, required this.content, required this.name});
#override
Widget build(BuildContext context) {
final ThemeData themeData = Theme.of(context);
final Size size = MediaQuery.of(context).size;
final double tileSize = size.width*0.20;
return Container(
margin: const EdgeInsets.only(left: 25),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
BorderIcon(
padding: new EdgeInsets.all(0.0),
width: tileSize,
height: tileSize,
child: Text(content,style: themeData.textTheme.headline3,)),
addVerticalSpace(15),
Text(name,style: themeData.textTheme.headline6,)
],
),
);
}
}
this is my Sample_data.dart file
in this file i add some sample data in json format
and this is how i define my DetailPage file in main.dart file
import 'package:flutter/material.dart';
import 'package:uidesign/screens/LandingPage.dart';
import 'package:uidesign/screens/DetailPage.dart';
import 'package:uidesign/utils/constants.dart';
import 'dart:ui';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
double screenWidth = window.physicalSize.width;
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Design 1',
theme: ThemeData(primaryColor: COLOR_WHITE, accentColor: COLOR_DARK_BLUE, textTheme: screenWidth < 500 ? TEXT_THEME_SMALL : TEXT_THEME_DEFAULT, fontFamily: "Montserrat"),
//home: LandingPage(),
//home: DetailPage(itemData: 1),
home: const DetailPage(),
);
}
}
error in terminal: the line i select on terminal is the error
Please help me out how it get the data with the key
Pass your RE_DATA list here in MainScreen
home: DetailPage(itemData: RE_DATA)
And Change List<dynamic> itemData to List<Map<String,dynamic>> itemData in DetailPage.
You are getting list so access itemData like this itemData[index]['image']
If possible use model for your RE_DATA instead of passing List of Maps.

Scrollable column in flutter

I want to make my screen scrollable but that is not happening. I am making an app where i want to show an image,title and description. I have succesfully shown the data but now want to make screen scrollable. I also want to add an app bar but then two app bar appears one below the other.
Here is my code:
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:http/http.dart' as http;
import 'package:kmitra/app_screens/fragment_topheadlines.dart';
import 'News.dart';
class Newsdetail extends StatefulWidget {
final String value_image, value_description, value_title;
/*String value_image,value_description;
int index;*/
Newsdetail(
{Key key,
#required this.value_image,
this.value_description,
this.value_title})
: super(key: key);
#override
_newsdetail createState() => _newsdetail();
}
class _newsdetail extends State<Newsdetail> {
_newsdetail();
// List<News> dataList = List();
bool _isLoading = false;
BuildContext context1;
Future loadyourData() async {
setState(() {
_isLoading = true;
});
#override
void initState() {
super.initState();
loadyourData();
}
}
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
body: SingleChildScrollView(
child: Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Expanded(
child: Image.network(
widget.value_image, //image
)),
Padding(
padding: const EdgeInsets.fromLTRB(6.0, 8.0, 0, 8.0),
child: Text(
widget.value_title, //title
style: TextStyle(fontSize: 25.0),
),
),
Expanded(
child: Text(
widget.value_description, //descrpition
style: TextStyle(fontSize: 18.0),
)),
],
),
))),
);
}
}
Use SingleChildScrollView
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Expanded(
child: Image.network(
widget.value_image, //image
)),
Padding(
padding: const EdgeInsets.fromLTRB(6.0, 8.0, 0, 8.0),
child: Text(
widget.value_title, //title
style: TextStyle(fontSize: 25.0),
),
),
Expanded(
child: Text(
widget.value_description, //descrpition
style: TextStyle(fontSize: 18.0),
)),
],
),
))),
);
}
}
As in comments instead of scroll body use
SingleChildScrollView(
child: Text(
widget.value_description, //descrpition
style: TextStyle(fontSize: 18.0),
)),
OR
Flexible(
child: Text(
widget.value_description, //descrpition
style: TextStyle(fontSize: 18.0),
)),
I found the solution by using rows inside the column widget and then using SinglechildScrollView.
You can use Listview or SingleChildScrollView For Scrollable View in
body
ListView(
shrinkWrap: true,
padding: EdgeInsets.all(15.0),
children: <Widget>[
//Your Column Childrens
]
)
Use SingleChildScrollView in Container widget like this
Container(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
_showChild1(),
other child widgets
...
]
)
)
);

How to add text along with carousel images in flutter?

I tried to add carousel along with text. But As far I can only add image carousel, Have no idea on how to add text. Please help me. Totally new.
I expect the output to be like image on above and text on below, but both need to swipe at same time.
I have no idea where to add the text field. I made this carousel with a example in youtube. But no example for carousel images with text. I tried something manually, But it all doesn't ended much well.
Please help me fix it. Thank-you
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(title: 'Slider'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
PageController pageController;
//Images List
List<String> images = [
'',
];
#override
void initState() {
super.initState();
pageController = PageController(initialPage: 1, viewportFraction: 0.6);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: PageView.builder(
controller: pageController,
itemCount: images.length,
itemBuilder: (context, position) {
return imageSlider(position);
}
)
);
}
imageSlider(int index) {
return AnimatedBuilder(
animation: pageController,
builder: (context, widget) {
double value = 1;
if(pageController.position.haveDimensions){
value = pageController.page - index;
value = (1 - (value.abs() * 0.3.clamp(0.0, 1.0)));
}
return Center(
child: SizedBox(
height: Curves.easeInOut.transform(value) * 400.0,
width: Curves.easeInOut.transform(value) * 350.0,
child: widget,
),
);
},
child: Container(
margin: EdgeInsets.all(10.0),
child: Image.asset(images[index],fit: BoxFit.cover),
),
);
}
}
Use column instead of container, so just replace this:
child: Container(
margin: EdgeInsets.all(10.0),
child: Image.asset(images[index],fit: BoxFit.cover),
),
with this:
child: Column(
// To centralize the children.
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
// First child
Container(
margin: EdgeInsets.all(10.0),
child: Image.asset(images[index],fit: BoxFit.cover),
),
// Second child
Text(
'foo',
style: TextStyle(
// Add text's style here
),
),
]
),
OR instead of building your own carousal, you can use a ready to use one, e.g: carousel_slider or flutter_swiper
try this
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
heading,
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
sub_heading,
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
),
//textAlign: TextAlign.center,
),
),
],
),
PageView with Next and Previous Functionality
Step 1:- Add PageView widget
class _WalkThroughState extends State<WalkThrough> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
var height = 0.0;
var width = 0.0;
int mCurrentIndex = -1;
List<Widget> pages=[PageOne(message: "Beauty Trends",),PageTwo(message: "Exclusive Offers",),PageThree(message: "Make your Kit",)];
PageController _controller = new PageController();
static const _kDuration = const Duration(milliseconds: 300);
static const _kCurve = Curves.ease;
#override
void initState() {
super.initState();
_controller = PageController();
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
height = MediaQuery.of(context).size.height;
width = MediaQuery.of(context).size.width;
return Scaffold(
extendBodyBehindAppBar: true,
body: Stack(
children: [
Container(
height: height,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [startColorBackground, endColorBackground])),
),
Column(
children: <Widget>[
Flexible(
child: Container(
child: PageIndicatorContainer(
key: _scaffoldKey,
child: PageView.builder(
controller: _controller,
onPageChanged: _onPageViewChange,
itemBuilder: (context, position) {
mCurrentIndex = position;
return pages[position];
},
itemCount: 3,
),
align: IndicatorAlign.bottom,
length: 3,
indicatorSpace: 10.0,
indicatorColor: Colors.white,
indicatorSelectorColor: Colors.black,
)),
),
Container(
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
// ignore: invalid_use_of_protected_member
mCurrentIndex != 0 ?Padding(
padding: const EdgeInsets.only(left: 30.0, bottom: 30.0),
child: GestureDetector(
onTap: () {
_controller.previousPage(
duration: _kDuration, curve: _kCurve);
},
child: Text('Prev', style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500),)),
) : Container(),
mCurrentIndex != 2 ? Padding(
padding: const EdgeInsets.only(right: 30.0, bottom: 30.0),
child: GestureDetector(
onTap: () {
_controller.nextPage(
duration: _kDuration, curve: _kCurve);
},
child: Text('Next', style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500),)),
) : Container(),
],
),
),
],
),
],
),
);
}
_onPageViewChange(int page) {
/*print("Current Page: " + page.toString());
int previousPage = page;
if(page != 0) previousPage--;
else previousPage = 2;
print("Previous page: $previousPage");*/
setState(() {
mCurrentIndex = page;
print(mCurrentIndex);
});
}
}
Step 2:- Add Pages with data
Page 1
class PageOne extends StatelessWidget {
final String message;
var height = 0.0;
var width = 0.0;
PageOne({Key key, #required this.message}) : super(key: key);
#override
Widget build(BuildContext context) {
height = MediaQuery.of(context).size.height;
width = MediaQuery.of(context).size.width;
return Container(
height: height - 50,
child: Align(alignment: Alignment.center, child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Container(
margin: EdgeInsets.only(top: 16.0),
child: Image(image: AssetImage("assets/images/banner_one.png"),)),
Container(
margin: EdgeInsets.only(bottom: 16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(message, style: TextStyle(fontSize: 40, fontFamily: 'Playfair', fontWeight: FontWeight.bold),),
SizedBox(height: 30,),
Text("Lorem Ipsum is simply dummy text of the \n printing and typesetting industry.", textAlign: TextAlign.center, style: TextStyle(fontSize: 18),),
],
),
),
],
),),
);
}
}
Page 2
class PageTwo extends StatelessWidget {
final String message;
var height = 0.0;
var width = 0.0;
PageTwo({Key key, #required this.message}) : super(key: key);
#override
Widget build(BuildContext context) {
height = MediaQuery.of(context).size.height;
width = MediaQuery.of(context).size.width;
return Container(
child: Column(
children: [
Expanded(
flex: 2,
child: Container(
width: width,
child: Image(
width: double.infinity,
image: AssetImage("assets/images/banner_two.png"),
fit: BoxFit.cover,)),
),
Expanded(
flex: 1,
child: Container(
margin: EdgeInsets.only(top: 16),
child: Column(
children: [
SizedBox(
height: 40,
),
Text(message, style: TextStyle(fontSize: 40, fontFamily: 'Playfair', fontWeight: FontWeight.bold),),
SizedBox(height: 30,),
Text("Lorem Ipsum is simply dummy text of the \n printing and typesetting industry.", textAlign: TextAlign.center, style: TextStyle(fontSize: 18),),
],
),
),
),
],
),
);
}
}
Page 3
class PageThree extends StatelessWidget {
final String message;
var height = 0.0;
var width = 0.0;
PageThree({Key key, #required this.message}) : super(key: key);
#override
Widget build(BuildContext context) {
height = MediaQuery.of(context).size.height;
width = MediaQuery.of(context).size.width;
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 3,
child: Container(
width: width,
child: Image( width: double.infinity,
image: AssetImage("assets/images/banner_three.png"), fit: BoxFit.fill,)),
),
Expanded(
flex: 1,
child: Container(
child: Column(
children: [
Text(message, style: TextStyle(fontSize: 40, fontFamily: 'Playfair', fontWeight: FontWeight.bold),),
SizedBox(height: 30,),
Text("Lorem Ipsum is simply dummy text of the \n printing and typesetting industry.", textAlign: TextAlign.center, style: TextStyle(fontSize: 18),),
],
),
),
),
],
),
);
}
}
You can add N number of pages. Right now am adding 3 pages with data
Colors.dart
import 'package:flutter/material.dart';
const viewColor = Color(0xFFF5D9CE);
const textPinkColor = Color(0xFFF51678);
const buttonPinkColor = Color(0xFFF5147C);
const pinkColor = Color(0xFFF51479);
const pinkBackground = Color(0xFFF5C3C7);
const startColorBackground = Color(0xFFF5F4F2);
const endColorBackground = Color(0xFFF5EAE6);
This is complete working code with Image on top with text and dots. For this you need to use these two libraries:- " carousel_slider: ^4.1.1 ", "smooth_page_indicator: ^1.0.0+2", update them to the latest.
class MyItem {
String itemName;
String path;
MyItem(this.itemName, this.path);
}
class craouselImage extends StatefulWidget {
#override
_craouselImage createState() => _craouselImage();
}
class _craouselImage extends State<craouselImage> {
int activeIndex = 0;
List<MyItem> items = [
MyItem("item 1", 'assets/images/appiconlogo.png'),
MyItem("item 2", 'assets/images/Mockup4.png'),
];
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
CarouselSlider.builder(
itemCount: items.length,
options: CarouselOptions(
height: 400,
viewportFraction: 1,
autoPlay: true,
enlargeCenterPage: true,
enlargeStrategy: CenterPageEnlargeStrategy.height,
autoPlayInterval: const Duration(seconds: 1),
onPageChanged: (index, reason) {
setState(() {
activeIndex = index;
});
},
),
itemBuilder: (context, index, realIndex) {
final imgList = items[index];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Expanded(child: buildImage(imgList.path, index)),
const SizedBox(
height: 15,
),
buildText(imgList.itemName, index),
],
);
},
),
const SizedBox(
height: 22,
),
buildIndicator(),
const SizedBox(
height: 22,
),
//buildText(itemName, index),
// buildText(),
],
),
);
}
Widget buildImage(String imgList, int index) => Container(
margin: const EdgeInsets.symmetric(horizontal: 12),
color: Colors.transparent,
child: Align(
alignment: Alignment.center,
child: Image.asset(
imgList,
fit: BoxFit.cover,
),
),
);
buildIndicator() => AnimatedSmoothIndicator(
activeIndex: activeIndex,
count: items.length,
effect: const JumpingDotEffect(
dotColor: Colors.black,
dotHeight: 15,
dotWidth: 15,
activeDotColor: mRed),
);
buildText(String itemName, int index) => Align(
alignment: FractionalOffset.bottomCenter,
child: Text(
itemName,
style: const TextStyle(
fontWeight: FontWeight.w700, fontSize: 23, color: mRed),
));
}

Unable to get page scroll even adding the content inside a SingleChildScrollView or the ListView

I'm new to Flutter.
What I'm trying to achieve is a page that has a transparent AppBar with a widget behind it. That's how it looks now:
The problem is that, I can't make the page scroll when the content is bigger then the viewport height, even adding a SingleChildScrollView or adding the content inside a ListView, it just don't scrolls.
This is the page:
import 'package:cinemax_app/src/blocs/movie_bloc.dart';
import 'package:cinemax_app/src/components/movie/movie_header.dart';
import 'package:cinemax_app/src/models/movie.dart';
import 'package:flutter/material.dart';
import 'package:share/share.dart';
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
class MoviePage extends StatefulWidget {
final int movieId;
MoviePage({ this.movieId });
#override
_MoviePageState createState() => _MoviePageState();
}
class _MoviePageState extends State<MoviePage> {
#override
void initState() {
super.initState();
movieBloc.fetchMovie(widget.movieId);
}
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: movieBloc.movie,
builder: (context, snapshot) {
final _movie = snapshot.data as MovieModel;
return Scaffold(
body: SafeArea(
child: snapshot.hasData ?
Stack(
children: <Widget>[
ListView(
shrinkWrap: true,
children: <Widget>[
MovieHeader(movie: _movie),
Container(
padding: EdgeInsets.only(top: 45, bottom: 15, left: 15, right: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Sinopse:', style: Theme.of(context).textTheme.title),
HtmlWidget(
_movie.sinopsis,
bodyPadding: EdgeInsets.only(top: 15),
textStyle: TextStyle(color: Colors.grey),
)
],
),
)
]
),
AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
actions: <Widget>[
PopupMenuButton(
icon: Icon(Icons.more_vert),
itemBuilder: (BuildContext context) {
return <PopupMenuItem>[
PopupMenuItem(
child: Text('Partilhar'),
value: 'share'
),
PopupMenuItem(
child: Text('Comprar bilhete'),
value: 'share',
enabled: false,
),
];
},
onSelected: (selectedPopupValue) {
switch (selectedPopupValue) {
case 'share': {
final movieSlug = _movie.slug;
final movieAddress = 'https://cinemax.co.ao/movie/$movieSlug';
Share.share(movieAddress);
}
}
},
)
],
),
]
) :
Center(
child: CircularProgressIndicator(),
)
),
);
}
);
}
}
The MovieHeader widget:
import 'dart:ui' as prefix0;
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cinemax_app/src/models/movie.dart';
import 'package:flutter/material.dart';
import 'movie_cover.dart';
class MovieHeader extends StatelessWidget {
const MovieHeader({Key key, #required MovieModel movie}) : _movie = movie, super(key: key);
final MovieModel _movie;
#override
Widget build(BuildContext context) {
return Container(
height: 250,
color: Colors.black,
child: Column(
children: <Widget>[
Expanded(
child: Stack(
fit: StackFit.expand,
overflow: Overflow.visible,
children: <Widget>[
new MovieBanner(movie: _movie),
Positioned(
bottom: -15.0,
left: 15.0,
right: 15.0,
child: Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Container(
width: 125.0,
child: MovieCover(imageUrl: _movie.coverUrl)
),
Padding(padding: EdgeInsets.only(right: 15.0),),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
children: <Widget>[
Expanded(
child: Text(
_movie.name,
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.bold,
)
),
),
],
),
Padding(padding: EdgeInsets.only(bottom: 10.0),),
Text(
_movie.genresList,
style: TextStyle(
fontSize: 10.0,
color: Colors.white.withOpacity(0.6)
),
),
Padding(padding: EdgeInsets.only(bottom: 35.0),)
],
),
)
],
)
),
)
],
)
),
],
),
);
}
}
class MovieBanner extends StatelessWidget {
const MovieBanner({
Key key,
#required MovieModel movie,
}) : _movie = movie, super(key: key);
final MovieModel _movie;
#override
Widget build(BuildContext context) {
return Stack(
fit: StackFit.expand,
children: <Widget>[
Opacity(
child: CachedNetworkImage(
imageUrl: _movie.bannerUrl,
fit: BoxFit.cover,
),
opacity: 0.5,
),
Positioned(
child: ClipRect(
child: BackdropFilter(
child: Container(color: Colors.black.withOpacity(0)),
filter: prefix0.ImageFilter.blur(sigmaX: 5, sigmaY: 5),
),
),
)
],
);
}
}
Why is it happening? What I'm doing wrong?
An Example of Scrolling ListView using ListView Builder
class ScrollingList extends StatelessWidget{
List<String> snapshot= ["A","B","C","D","E","F","G"]
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder( //<----------- Using ListViewBuilder
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return Card( //<--------- Using Card as per my requirement as a wrapper on List tile, you can use any other UI Element
child: ListTile( // populating list tile with tap functionality
title: Text(
'${snapshot.data[index]}',
maxLines: 1,
),
onTap: () {
print('TAPPED = ${snapshot.data[index]}') //<---- do anything on item clicked eg: open a new page or option etc.
}),
);
},
);
)
}
for any reference of single child scroll view here is a link