show images with grid view in flutter - image

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,
),
),
]),
),
);
}));
}
}

Related

How to create a custom dialogue with image parameter in flutter

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()
],
),
),
],
);
}
}

Flutter tabBar how to change from top to buttom

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.

Flutter, Carousel Text change with Image change

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),
));
}

How do I make my gridView scroll take up the whole page in Flutter?

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
)
)
],
);
}
}

Flutter: Notifications UI

I can't distinguish new Firebase Cloud Messaging notifications from older ones in my Flutter UI. How can I fix this? Thanks.
EXAMPLE: 3 users comment on an author's post that already has 2 "seen" comments. The author's post gets a +3 red marble on it. When the author clicks on this post in the Notifications tab, the user is routed to its comments, that +3 reduces to 0, and the bottom tab marble reduces to 3 (6-3=3) as well.
Dummy UI Code and Pics below.
1. A blank "home page;"
2. a dummy notifications page with posts that have been replied to
3. On clicking a post, a comments page.
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
routes: <String, WidgetBuilder>{
"/comment": (BuildContext context) => new commentFoundation(),
},
home: MainScreen());
}
}
//The content of the notification tab.
class Notification extends StatefulWidget {
#override
_NotificationState createState() => new _NotificationState();
}
class _NotificationState extends State<Notification> {
#override
Widget build(BuildContext context) {
return _buildPostList();
}
Widget _buildPostList() {
return new Scaffold(
backgroundColor: Colors.blue,
body: new Scrollbar(
child: new ListView.builder(
itemBuilder: (BuildContext context, int index) {
return new Container(
child: new Stack(children: <Widget>[
new Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 0.0, left: 12.0),
child: DummyPost()),
],
),
replyNotification(),
]));
},
itemCount: 2,
)));
}
Widget replyNotification() {
return new Positioned(
left: 175,
top: 205.5,
child: new Container(
padding: EdgeInsets.only(left: 3.0, right: 3.0),
decoration: new BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(30),
),
constraints: BoxConstraints(
minWidth: 30,
minHeight: 30,
),
child: Row(
children: <Widget>[
Container(
padding: EdgeInsets.only(top: 0.0),
child: new Text(
'+',
style: new TextStyle(
color: Colors.white,
fontSize: 26,
),
textAlign: TextAlign.center,
)),
Container(
padding: EdgeInsets.only(right: 0.0),
child: new Text(
'3',
style: new TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
)),
],
)),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => new _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Center(
child: new Container(
child: Text("HomePageStuff"),
));
}
}
//A dummy post in notififications tab
class DummyPost extends StatefulWidget {
#override
_DummyPostState createState() => new _DummyPostState();
}
class _DummyPostState extends State<DummyPost> {
bool monVal = false;
bool reportPressed = false;
Widget commentButton() {
return RaisedButton(
child: Text("ReplyButton"),
onPressed: () => Navigator.push(context,
MaterialPageRoute(builder: (context) => commentFoundation())),
);
}
#override
Widget build(BuildContext context) {
return postList();
}
Widget postList() {
return Column(children: <Widget>[
new GestureDetector(
//this type works
onTap: () => Navigator.pushNamed(context, '/comment'),
child: new Stack(children: <Widget>[
Column(children: <Widget>[
SizedBox(
height: 10.0,
),
Container(
margin: EdgeInsets.only(top: 35.0),
width: 390.0,
child: Card(
shape: RoundedRectangleBorder(
//15?
borderRadius: BorderRadius.circular(5.0),
),
color: Colors.white,
elevation: 2.0,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Flexible(
child: ListTile(
// The main post content
subtitle: Container(
height: 130.0,
margin: EdgeInsets.only(
top: 15.0, left: 15.0, right: 15.0),
child: Container(
child: Center(
child: Text(
"This is a dummy post",
textAlign: TextAlign.center,
style: TextStyle(
wordSpacing: 3.0,
color: Colors.black,
fontSize: 18.0),
))),
),
)),
//button row
new Container(
width: 400.0,
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
margin: EdgeInsets.only(right: 0.0),
width: 190.0,
height: 40.0,
child: commentButton(),
),
// Text to indicate comment numbers
],
)),
],
))),
]),
]))
]);
}
}
//the entire comment page.
class commentFoundation extends StatefulWidget {
#override
_commentFoundationState createState() => new _commentFoundationState();
}
class _commentFoundationState extends State<commentFoundation> {
ScrollController _scrollController = new ScrollController();
#override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.green,
appBar: _buildAppBar(),
body: new Stack(children: <Widget>[
ListView.builder(
shrinkWrap: true,
controller: _scrollController,
itemCount: 5,
itemBuilder: (BuildContext context, int index) {
return new individualComment();
}),
]));
}
Widget _buildAppBar() {
return AppBar(
title: Text("REPLIES"),
automaticallyImplyLeading: true,
backgroundColor: Colors.white,
elevation: 0.0,
);
}
}
//Each individual comment you see when you click on a post
class individualComment extends StatefulWidget {
final String title;
const individualComment({Key key, this.title}) : super(key: key);
#override
_individualCommentState createState() => new _individualCommentState();
}
class _individualCommentState extends State<individualComment> {
#override
Widget build(BuildContext context) {
return new Stack(
children: <Widget>[
Column(children: <Widget>[
//this used to be an expanded
new Container(
child: Card(
elevation: 0.0,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new ListTile(
// The avatar
leading: Container(
child: Icon(
Icons.accessibility_new,
)),
// Title, location, and time
// The main post content
subtitle: Container(
margin: EdgeInsets.only(top: 10.0, bottom: 0.0),
child: Text(
"This is a reply",
style: TextStyle(
color: Colors.black,
fontSize: .0364609 *
MediaQuery.of(context).size.width),
),
),
),
],
))),
])
],
);
}
}
//*****This is just the tabbar.
class MainScreen extends StatefulWidget {
#override
_MainScreenstate createState() => new _MainScreenstate();
}
class _MainScreenstate extends State<MainScreen> with TickerProviderStateMixin {
String _lastSelected = '0';
final List<Widget> _bodyOptions = [
HomePage(),
Notification(),
];
int _selectedIndex = 0;
bool tab = true;
_selectedTab(int index) {
setState(() {
_lastSelected = '$index';
});
}
Widget __buildTabs() {
return Scaffold(
body: _bodyOptions.elementAt(int.parse(_lastSelected)),
//around the FAB
backgroundColor: const Color(0xFFF4F4F4),
bottomNavigationBar: new Stack(
children: <Widget>[
FABBottomAppBar(
height: 45.0,
centerItemText: '',
color: Colors.black,
selectedColor: Colors.blue,
notchedShape: CircularNotchedRectangle(),
onTabSelected: _selectedTab,
items: [
FABBottomAppBarItem(iconData: Icons.search, text: 'Home'),
FABBottomAppBarItem(
iconData: Icons.notifications, text: 'Notifications'),
],
),
//the red "notification" marble
new Positioned(
right: 20,
top: 0.5,
child: new Container(
padding: EdgeInsets.all(1),
decoration: new BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(12),
),
constraints: BoxConstraints(
minWidth: 20,
minHeight: 20,
),
child: new Text(
'6',
style: new TextStyle(
color: Colors.white,
fontSize: 14,
),
textAlign: TextAlign.center,
),
),
)
],
));
}
#override
Widget build(BuildContext context) {
return __buildTabs();
}
}
//Everything below is boiler plate tabbar code.
class FABBottomAppBarItem {
FABBottomAppBarItem({this.iconData, this.text});
IconData iconData;
String text;
}
class FABBottomAppBar extends StatefulWidget {
FABBottomAppBar({
this.items,
this.centerItemText,
this.height: 60.0,
this.iconSize: 24.0,
this.backgroundColor,
this.color,
this.selectedColor,
this.notchedShape,
this.onTabSelected,
}) {
assert(this.items.length == 2 || this.items.length == 4);
}
final List<FABBottomAppBarItem> items;
final String centerItemText;
final double height;
final double iconSize;
final Color backgroundColor;
final Color color;
final Color selectedColor;
final NotchedShape notchedShape;
final ValueChanged<int> onTabSelected;
#override
State<StatefulWidget> createState() => FABBottomAppBarState();
}
class FABBottomAppBarState extends State<FABBottomAppBar> {
int _selectedIndex = 0;
_updateIndex(int index) {
widget.onTabSelected(index);
setState(() {
_selectedIndex = index;
});
return _selectedIndex;
}
#override
Widget build(BuildContext context) {
List<Widget> items = List.generate(widget.items.length, (int index) {
return _buildTabItem(
item: widget.items[index],
index: index,
onPressed: _updateIndex,
);
});
items.insert(items.length >> 1, _buildMiddleTabItem());
return BottomAppBar(
elevation: 0.0,
notchMargin: 2.0,
shape: CircularNotchedRectangle(),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: items,
),
//color of bottom
color: Colors.white,
);
}
Widget _buildMiddleTabItem() {
return Expanded(
child: SizedBox(
height: widget.height,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(height: widget.iconSize),
Text(
widget.centerItemText ?? '',
style: TextStyle(color: widget.color),
),
],
),
),
);
}
Widget _buildTabItem({
FABBottomAppBarItem item,
int index,
ValueChanged<int> onPressed,
}) {
Color color = _selectedIndex == index ? widget.selectedColor : widget.color;
return Expanded(
child: SizedBox(
height: widget.height,
child: Material(
type: MaterialType.transparency,
child: InkWell(
onTap: () => onPressed(index),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(item.iconData, color: color, size: widget.iconSize),
Text(
item.text,
style: TextStyle(color: color),
)
],
),
),
),
),
);
}
}
This seems to be a broad question and I'm unsure if you're asking for suggestions on how you can implement tracking read and unread notifications, or troubleshooting help on your existing code. I suggest checking tips posted on this thread on how you can manage notification counters.

Resources