I am pretty new in Dart Flutter.
I have this problem I follow the guide to creating a tab bar,
But is at the top, what I am trying to achieve is to have the tab
at the bottom instead of at the top.
I have already tried BottomNavigationBar and change all,
but didn't work and crash all the app.
Please help me thanks
child: Scaffold(
body: DefaultTabController(
length: 5,
initialIndex: 2,
child: Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: primaryColor,
automaticallyImplyLeading: false,
title: TabBar(
labelColor: Colors.white,
indicatorColor: Colors.white,
unselectedLabelColor: Colors.black,
isScrollable: false,
indicatorSize: TabBarIndicatorSize.label,
tabs: [
Tab(
icon: Icon(
Icons.person,
size: 30,
),
),
Tab(
icon: Icon(
Icons.group,
),
),
Tab(
icon: Icon(
Icons.whatshot,
),
),
Tab(
icon: Icon(
Icons.notifications,
),
),
Tab(
icon: Icon(
Icons.message,
),
)
]),
),
body: TabBarView(
children: [
Center(child: Profile(currentUser)),
Center(child: Chanels()),
Center(child: CardPictures(currentUser, users)),
Center(child: Notifications(currentUser, notification)),
Center(child: HomeScreen(currentUser, matches)),
],
physics: NeverScrollableScrollPhysics(),
)),
),
),
You can use BottomNavigationBar() in this way.
You need to manage everything ( like listening to tab events and rendering page accordingly).
Prototype:
class _TabsScreenState extends State<TabsScreen> {
final var _pages = [Screen1(),Screen2()];
int page_index = 0;
void _pageSelect(int index) {
setState(() {
page_index = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(),
),
body: _pages[page_index],
bottomNavigationBar: BottomNavigationBar(
onTap: _pageSelect,
backgroundColor: '',
unselectedItemColor: '',
selectedItemColor: '',
currentIndex: page_index,
items: [
BottomNavigationBarItem(
backgroundColor: '',
icon: Icon(''),
title: Text(''),
),
BottomNavigationBarItem(
backgroundColor: '',
icon: Icon('),
title: Text(''),
),
],
),
);
}
}
To change the tab bar from the top to bottom we have to customize the default tab bar in flutter using TabController. Here is an example :
import "package:flutter/material.dart";
import 'package:hexcolor/hexcolor.dart';
import 'LineChart.dart';
import 'LineChart1.dart';
class PortfolioGraph extends StatefulWidget {
#override
_PortfolioGraphState createState() => _PortfolioGraphState();
}
class _PortfolioGraphState extends State<PortfolioGraph> with TickerProviderStateMixin {
int _currentindex = 0;
List<Widget> _tabList = [
Container(
alignment: Alignment.bottomCenter,
child:LineChartSample2()),
Container(
alignment: Alignment.bottomCenter,
child:LineChartSample2()),
Container(
alignment: Alignment.bottomCenter,
child:LineChartSample2()),
Container(
alignment: Alignment.bottomCenter,
child:LineChartSample2()),
Container(
alignment: Alignment.bottomCenter,
child:LineChartSample2()),
Container(
alignment: Alignment.bottomCenter,
child:LineChartSample2()),
Container(
alignment: Alignment.bottomCenter,
child:LineChartSample2()),
];
TabController _tabController;
#override
void initState(){
super.initState();
_tabController = TabController(vsync:this,length: 7);
}
#override
void dispose(){
_tabController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Container(
child:Column(
children: [
Container(
height: 270,
width:size.width,
child:TabBarView(
controller: _tabController,
children:_tabList
),
),
Container(
alignment: Alignment.topLeft,
child: Container(
height: 50,
width:size.width,
child: Container(
child: Scaffold(
appBar: AppBar(
toolbarHeight: 50,
// leadingWidth: 10,
backgroundColor: Colors.white,
elevation: 0,
titleSpacing: 0,
centerTitle: false,
bottom: PreferredSize(
preferredSize: Size.fromHeight(40),
child: Align(
alignment: Alignment.center,
child: TabBar(
controller: _tabController,
indicatorColor: HexColor("#199C78"),
indicatorWeight: 4,
unselectedLabelColor: HexColor("#8C8C8C"),
labelColor:HexColor("#3A3A3A"),
labelPadding: EdgeInsets.only(left: 0, right: 0),
labelStyle: TextStyle(fontSize: 14,fontWeight: FontWeight.bold),
unselectedLabelStyle: TextStyle(fontSize: 14),
isScrollable: false,
tabs: [
Tab(child:Container(
child: Text("1D"),
)),
Tab(child:Container(
child: Text("1W"),
)),
Tab(child:Container(
child: Text("1M"),
)),
Tab(child:Container(
child: Text("3M"),
)),
// SizedBox(width:10),
Tab(child:Container(
child: Text("6M"),
)),
Tab(child:Container(
child: Text("1YR"),)),
Tab(child:Container(
child: Text("All"),))
],
),
),
),
),
),
),
),
)
],
)
);
}
}
If you know how to use a tab bar then its simple for you. For your need you can use tab bar in any row column in any way it's up to you.You just need to provide controller to both tab bar and tabBarView and both these controller must be same irrespective of how you use tab bar.You can put tab-bar in almost any widget I have done it myself and put it in a row.
Related
I'm trying to create a custom dialogue box, where i'm passing title, text and image parameter, when i call the dialogue box, it is not display image, here is the code
this is the code of Dialogue box.
class LoginSucessDailog extends StatefulWidget {
final String title, text;
final Image img;
const LoginSucessDailog({ required this.title, required this.text,required this.img });
#override
_LoginSucessDailogState createState() => _LoginSucessDailogState();
}
class _LoginSucessDailogState extends State<LoginSucessDailog> {
#override
Widget build(BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(Constants.padding),
),
elevation: 0,
backgroundColor: Colors.transparent,
child: contentBox(context),
);
}
contentBox(context) {
return Stack(
children: <Widget>[
Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Image.asset(
widget.img.toString(),
width: 100,
),
Text(
widget.title,
style:GoogleFonts.montserrat(fontSize: 22, fontWeight: FontWeight.w600),
),
Padding(
padding: const EdgeInsets.only(left: 20, right: 20),
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: TextStyle(
color: Colors.black,
),
children: <TextSpan>[
TextSpan(
text:widget.text,
style: GoogleFonts.montserrat(fontSize: 16, color: Colors.grey)),
],
),
),
),
SizedBox50(),
okay()
],
),
),
],
);
}
}
and here i'm calling it as like this
showDialog(
context: context,
builder: (BuildContext context) {
return LoginSucessDailog( text: 'Phone number doesnt exists!',
title: 'Error',
img:Image.asset("assets/img/alert.png"));
});
but it send me this error
Unable to load asset: Image(image: AssetImage(bundle: null, name: "assets/img/alert.png"), frameBuilder: null, loadingBuilder: null, alignment: Alignment.center, this.excludeFromSemantics: false, filterQuality: low)
widget.img.toString(), if i'm not converting it into string then it gives me this error
The argument type 'Image' can't be assigned to the parameter type 'String'.
please help how to solve it .
I changed the passed value and adapt the constructor dialog.
showDialog(
context: context,
builder: (BuildContext context) {
return LoginSucessDailog( text: 'Phone number doesnt exists!',
title: 'Error',
img:'assets/img/alert.png');
});
class LoginSucessDailog extends StatefulWidget {
final String title, text, img;
const LoginSucessDailog({ required this.title, required this.text,required this.img });
#override
_LoginSucessDailogState createState() => _LoginSucessDailogState();
}
class _LoginSucessDailogState extends State<LoginSucessDailog> {
#override
Widget build(BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(Constants.padding),
),
elevation: 0,
backgroundColor: Colors.transparent,
child: contentBox(context),
);
}
contentBox(context) {
return Stack(
children: <Widget>[
Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Image.asset(
widget.img,
width: 100,
),
Text(
widget.title,
style:GoogleFonts.montserrat(fontSize: 22, fontWeight: FontWeight.w600),
),
Padding(
padding: const EdgeInsets.only(left: 20, right: 20),
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: TextStyle(
color: Colors.black,
),
children: <TextSpan>[
TextSpan(
text:widget.text,
style: GoogleFonts.montserrat(fontSize: 16, color: Colors.grey)),
],
),
),
),
SizedBox50(),
okay()
],
),
),
],
);
}
}
I'm new to Flutter. I've got 2 Containers with SizedBox. I'm trying to set horizontal scroll for 1st one: Slider1LocalPage().
I read about it and tried to use scrollDirection: Axis.horizontal but it causes errors. I tried to use the Column but with no success.
Help on my example will help me learn and understand flutter.
This is my widget body in main.dart
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Text(
'Horizontal - can\'t deal with',
style: TextStyle(fontSize: 18),
),
Container(
child: SizedBox(height: 260.0, child: Slider1LocalPage()),
),
Text(
'Vertical',
style: TextStyle(fontSize: 18),
),
Container(
child: SizedBox(height: 290, child: List1LocalPage()),
)
],
),
),
Slider1LocalPage()
class Slider1LocalPage extends StatelessWidget {
#override
Widget build(BuildContext context) => Scaffold(
body: FutureBuilder<List<Record>>(
future: List1Api.getList1Locally(context),
builder: (context, snapshot) {
final records = snapshot.data;
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
default:
if (snapshot.hasError) {
return Center(child: Text('Some error occurred!'));
} else {
return buildList1(records);
}
}
},
),
);
Widget buildList1(List<Record> records) => ListView.builder(
physics: BouncingScrollPhysics(),
itemCount: records.length,
itemBuilder: (context, index) {
final record = records[index];
return ListTile(
onTap: () => Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => ContentPage(record: record),
)),
leading: CircleAvatar(
backgroundImage: NetworkImage(record.urlAvatar),
),
title: Text(record.title1),
subtitle: Text(record.content1),
);
},
);
}
#Divyesh answer is Ok , here is demo to use Horizontal and vertical list together. i prefer using CustomScrollView and MultiSliver to handle sliver type.
just add sliverTools to use MultiSliver, else there will be little extra code to handle this situation.
#override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: [
MultiSliver(
children: [
Text(
'Horizontal - can deal with',
style: TextStyle(fontSize: 18),
),
MultiSliver(
children: [
// Slider1LocalPage(),
Container(
height: 140,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
physics: BouncingScrollPhysics(),
itemCount: 20,
itemBuilder: (context, index) {
// final record = records[index];
return Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
// onTap: () => Navigator.of(context).push(MaterialPageRoute(
// builder: (BuildContext context) => ContentPage(record: record),
// ),),
child: Column(
children: [
CircleAvatar(
radius: 40,
backgroundImage: NetworkImage(
"https://www.rd.com/wp-content/uploads/2017/09/01-shutterstock_476340928-Irina-Bg-1024x683.jpg",
),
),
Text("title here"),
Text("subtitle"),
],
),
),
);
},
),
),
],
),
Text(
'Vertical',
style: TextStyle(fontSize: 18),
),
MultiSliver(
children: List.generate(
23,
(index) => Container(
height: 50,
width: double.infinity,
color: index % 2 == 0 ? Colors.cyanAccent : Colors.pinkAccent,
),
),
),
// Container(
// color: COlors,
// // child: List1LocalPage(),
// ),
// )
],
),
],
);
}
You can check working demo here: https://flutter.dev/docs/cookbook/lists/horizontal-list
Widget buildList1(List<Record> records) => ListView.builder(
scrollDirection: Axis.horizontal,
physics: BouncingScrollPhysics(),
itemCount: records.length,
itemBuilder: (context, index) {
final record = records[index];
return ListTile(
onTap: () => Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => ContentPage(record: record),
)),
leading: CircleAvatar(
backgroundImage: NetworkImage(record.urlAvatar),
),
title: Text(record.title1),
subtitle: Text(record.content1),
);
},
);
The problem is caused by ListTile, because it takes the full width. ListTile doesn't seem appropriate for a horizontal listview. To add an on-tap action you could make use of a GestureDetector.
Thanks for MultiSliver and info about ListTile. Both will be useful in future. So, now horizontal ListView works. Almost good but now I have data loop in each Column. I know the reason is in Widget buildSlider1 ListView but can't find solution.Any hint?screnshot
Widget buildSlider1(List<Record> records) => ListView.builder(
physics: BouncingScrollPhysics(),
itemCount: records.length,
itemBuilder: (context, index) {
final record = records[index];
return Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
// onTap: () => Navigator.of(context).push(MaterialPageRoute(
// builder: (BuildContext context) => ContentPage(record: record),
// ),),
child: Column(
children: [
Text(record.title1),
Text(record.content1),
],
),
),
);
},
);
_
Widget build(BuildContext context) {
return CustomScrollView(
slivers: [
MultiSliver(
children: [
Text(
'Horizontal - can deal with',
style: TextStyle(fontSize: 18),
),
MultiSliver(
children: [
Container(
height: 210,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
physics: BouncingScrollPhysics(),
itemCount: 20,
itemBuilder: (context, index) {
// final record = records[index];
return Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
// onTap: () => Navigator.of(context).push(MaterialPageRoute(
// builder: (BuildContext context) => ContentPage(record: record),
// ),),
child: Column(
children: [
SizedBox(
width: 220,
height: 280,
child: Slider1LocalPage()),
],
),
),
);
},
),
),
],
),
Text(
'Vertical',
style: TextStyle(fontSize: 18),
),
MultiSliver(children: [
SizedBox(
height: 380, width: double.infinity, child: List1LocalPage()),
]),
],
),
],
);}
I tried to use StaggeredGridView but it wont load anything on my page, not even just text. I haven't put images URLs yet cuz I want to test it out.
So far this is my code below:
body: ListView(
children: [
Container(
width: deviceSize.width,
height: 650,
child: Stack(
alignment: AlignmentDirectional.center,
children: [
Image.asset(
'assets/Big Sur.jpg',
width: deviceSize.width,
fit: BoxFit.cover,
),
Stack(
children: [
Text(
"""\n\n\nA decentralized photography platform\nfor the devoted communities.""",
style: TextStyle(
color: Colors.white,
fontSize: 30,
),
),
Text(
'PhoBlock',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 80,
),
)
],
),
],
),
),
SizedBox(
height: 50,
),
StaggeredGridView.countBuilder(
crossAxisCount: 4,
itemBuilder: (BuildContext context, int index) {
return Container(
color: Colors.green,
child: new Center(
child: new CircleAvatar(
backgroundColor: Colors.white,
child: new Text('$index'),
),
),
);
},
staggeredTileBuilder: (int index) {
return StaggeredTile.count(2, index.isEven ? 2 : 1);
},
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
),
This was from the body of the Scaffold widget. Please help me as I'm trying to figure out how to use this new StaggeredGridView widget...
You can copy paste run full code below
You can use Column and Expanded to control size
code snippet
Column(mainAxisSize: MainAxisSize.min, children: [
Expanded(
child: Container(
width: deviceSize.width,
//height: 650,
child: Stack(
...
),
SizedBox(
height: 50,
),
Expanded(
flex: 1,
child: StaggeredGridView.countBuilder(
working demo
full code
import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
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
Widget build(BuildContext context) {
var deviceSize = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(mainAxisSize: MainAxisSize.min, children: [
Expanded(
child: Container(
width: deviceSize.width,
//height: 650,
child: Stack(
alignment: AlignmentDirectional.center,
children: [
Image.network(
'https://picsum.photos/250?image=9',
width: deviceSize.width,
fit: BoxFit.cover,
),
Stack(
children: [
Text(
"""\n\n\nA decentralized photography platform\nfor the devoted communities.""",
style: TextStyle(
color: Colors.white,
fontSize: 30,
),
),
Text(
'PhoBlock',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 80,
),
)
],
),
],
),
),
),
SizedBox(
height: 50,
),
Expanded(
flex: 1,
child: StaggeredGridView.countBuilder(
crossAxisCount: 4,
itemBuilder: (BuildContext context, int index) {
return Container(
color: Colors.green,
child: Center(
child: CircleAvatar(
backgroundColor: Colors.white,
child: Text('$index'),
),
),
);
},
staggeredTileBuilder: (int index) {
return StaggeredTile.count(2, index.isEven ? 2 : 1);
},
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
),
),
]));
}
}
working demo 2
full code 2
import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
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
Widget build(BuildContext context) {
var deviceSize = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: LayoutBuilder(builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: constraints.copyWith(
minHeight: constraints.maxHeight,
maxHeight: double.infinity,
),
child: Column(mainAxisSize: MainAxisSize.min, children: [
Container(
width: deviceSize.width,
height: 450,
child: Stack(
alignment: AlignmentDirectional.center,
children: [
Image.network(
'https://picsum.photos/250?image=9',
width: deviceSize.width,
fit: BoxFit.cover,
),
Stack(
children: [
Text(
"""\n\n\nA decentralized photography platform\nfor the devoted communities.""",
style: TextStyle(
color: Colors.white,
fontSize: 30,
),
),
Text(
'PhoBlock',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 80,
),
)
],
),
],
),
),
SizedBox(
height: 50,
),
Container(
height: 500,
child: StaggeredGridView.countBuilder(
crossAxisCount: 4,
itemBuilder: (BuildContext context, int index) {
return Container(
color: Colors.green,
child: Center(
child: CircleAvatar(
backgroundColor: Colors.white,
child: Text('$index'),
),
),
);
},
staggeredTileBuilder: (int index) {
return StaggeredTile.count(2, index.isEven ? 2 : 1);
},
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
),
),
]),
),
);
}));
}
}
Row(
children: <Widget>[
new Expanded(
child: SizedBox(
height: 150.0,
width: 300,
child: Carousel(
boxFit: BoxFit.cover,
autoplay: true,
animationCurve: Curves.fastOutSlowIn,
animationDuration: Duration(milliseconds: 1000),
dotSize: 6.0,
dotIncreasedColor: Colors.grey,
dotBgColor: Colors.transparent,
dotPosition: DotPosition.bottomCenter,
dotVerticalPadding: 10.0,
showIndicator: true,
indicatorBgPadding: 7.0,
images: [
AssetImage('assets/mountain.jpg'),
AssetImage('assets/mountain2.png')
],
),
),
),
// Other children below
]
)
Hi, I've managed to implement a carousel but I am wondering how you can add Text to it on the center. When the carousel moves to a new image I want the text to change to. I am using carousel_pro 1.0.0.
You can copy paste run full code below
image attribute actually can use widget , so you can use Card
code snippet
images: [
Card(
child:
Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
const ListTile(
leading: Icon(Icons.album),
title: Text('The Enchanted Nightingale'),
subtitle:
Text('Music by Julie Gable. Lyrics by Sidney Stein.'),
),
Image.network(
'https://cdn-images-1.medium.com/max/2000/1*GqdzzfB_BHorv7V2NV7Jgg.jpeg'),
])),
working demo
full code
import 'package:flutter/material.dart';
import 'package:carousel_pro/carousel_pro.dart';
class CarouselPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SizedBox(
height: 300.0,
width: 300.0,
child: Carousel(
boxFit: BoxFit.cover,
autoplay: false,
animationCurve: Curves.fastOutSlowIn,
animationDuration: Duration(milliseconds: 1000),
dotSize: 6.0,
dotIncreasedColor: Color(0xFFFF335C),
dotBgColor: Colors.transparent,
dotPosition: DotPosition.topRight,
dotVerticalPadding: 10.0,
showIndicator: true,
indicatorBgPadding: 7.0,
images: [
Card(
child:
Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
const ListTile(
leading: Icon(Icons.album),
title: Text('The Enchanted Nightingale'),
subtitle:
Text('Music by Julie Gable. Lyrics by Sidney Stein.'),
),
Image.network(
'https://cdn-images-1.medium.com/max/2000/1*GqdzzfB_BHorv7V2NV7Jgg.jpeg'),
])),
Card(
child:
Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
const ListTile(
leading: Icon(Icons.album),
title: Text('The Enchanted Nightingale'),
subtitle:
Text('Music by Julie Gable. Lyrics by Sidney Stein.'),
),
Image.network(
'https://cdn-images-1.medium.com/max/2000/1*wnIEgP1gNMrK5gZU7QS0-A.jpeg'),
])),
],
),
),
),
);
}
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: CarouselPage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
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),
));
}
I have a gridView which on scrolling must take up the whole page. It currently only scrolls in the bottom half of the page and looks like shown below.
When I scroll the Grid View containing the elements only the bottom part of the page is scrolling
#override
Widget build(BuildContext context) {
return Material(
child: Container(
color: DesignCourseAppTheme.nearlyWhite,
child: PageView(
scrollDirection: Axis.vertical,
children: [
Scaffold(
backgroundColor: DesignCourseAppTheme.nearlyWhite,
body: Container(
child: Column(
children: <Widget>[
SizedBox(
height: MediaQuery.of(context).padding.top,
),
getAppBarUI(),
Expanded(
child: Container(
height: MediaQuery.of(context).size.height,
child: Column(
children: <Widget>[
getCategoryUI(),
Flexible(
child: getPopularCourseUI(),
),
],
),
),
),
],
),
),
),
],
),
),
);
}
Here the gridView is called as:
Widget getPopularCourseUI() {
return Padding(
padding: const EdgeInsets.only(top: 8.0, left: 18, right: 16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Featured Games',
textAlign: TextAlign.left,
style: TextStyle(
fontFamily: "Netflix",
fontWeight: FontWeight.w800,
fontSize: 24,
letterSpacing: 0.27,
color: HexColor('FF8C3B'),
),
),
Flexible(
child: GamesGridView(
callBack: () {},
),
)
],
),
);
}
Thank you for your help!
You can wrap your widget which is inside Scaffold body with ListView.
Then you should remove all flex widgets from your Column.
Your GridView should include
shrinkWrap: truephysics: const ClampingScrollPhysics()
Refer this,
import "package:flutter/material.dart";
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
Widget build(BuildContext context) {
return Material(
color: Colors.white, //DesignCourseAppTheme.nearlyWhite,
child: PageView(
scrollDirection: Axis.vertical,
children: [
Scaffold(
body: SafeArea(
child: ListView(
padding: EdgeInsets.symmetric(horizontal: 30),
children: <Widget>[
getAppBarUI(),
getCategoryUI(),
getPopularCourseUI(),
],
),
),
),
],
),
);
}
Widget getCategoryUI(){
return SizedBox(
height: 300,
child: PageView(
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(vertical: 40.0,horizontal: 30.0),
child: Material(
color: Colors.blue,
elevation: 3.0,
borderRadius: BorderRadius.circular(20.0),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 40.0,horizontal: 30.0),
child: Material(
color: Colors.green,
elevation: 3.0,
borderRadius: BorderRadius.circular(20.0),
),
),
],
),
);
}
Widget getAppBarUI(){
return Text(
'Games for Fun!',
style: TextStyle(
fontFamily: "Netflix",
fontWeight: FontWeight.w800,
fontSize: 32.0,
letterSpacing: 0.27,
color: Colors.red, //HexColor('FF8C3B'),
),
);
}
Widget getPopularCourseUI() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Featured Games',
style: TextStyle(
fontFamily: "Netflix",
fontWeight: FontWeight.w800,
fontSize: 24.0,
letterSpacing: 0.27,
color: Colors.red, //HexColor('FF8C3B'),
),
),
const SizedBox(height: 8.0),
GamesGridView(
callBack: () {},
)
],
);
}
}
class GamesGridView extends StatelessWidget {
final VoidCallback callBack;
const GamesGridView({Key key, this.callBack}) : super(key: key);
#override
Widget build(BuildContext context) {
return GridView.count(
shrinkWrap: true, //TODO: must be included
physics: const ClampingScrollPhysics(), //TODO: must be included
crossAxisCount: 2,
mainAxisSpacing: 50.0,
crossAxisSpacing: 50.0,
children: <Widget>[
RaisedButton(child: Text("Button"), onPressed: () {}),
RaisedButton(child: Text("Button"), onPressed: () {}),
RaisedButton(child: Text("Button"), onPressed: () {}),
RaisedButton(child: Text("Button"), onPressed: () {}),
RaisedButton(child: Text("Button"), onPressed: () {}),
RaisedButton(child: Text("Button"), onPressed: () {}),
RaisedButton(child: Text("Button"), onPressed: () {}),
],
);
}
}
Here getCategoryUI can scroll horizontally too.
If I understood your issue correctly, using a CustomScrollView with SliverAppBar and a SliverGrid should do what you want:
class GridViewIssue extends StatelessWidget {
#override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: <Widget>[
SliverAppBar(
title: Center(child: Text('Banner')),
expandedHeight: 250.0,
),
SliverGrid(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
alignment: Alignment.center,
color: Colors.teal[100 * (index % 9)],
child: Text('grid item $index'),
);
},
childCount: 8
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2
)
)
],
);
}
}