I learned the use of sliver widget in flutter two days ago, and I was playing with it to grow my skills. I was building one kind of imaginary project and I faced a problem there.
let's think, there is 15 container in my body's container under x widget which allow them to scroll vertically.Now, My objective here, when I am scrolling, I want when the container number 5 reached the top,the container number 5 will stuck there like a appbar or like sliver appbar and others will scroll under it.
Here I am using sliver and SliverFixedExtentList under CustomScrollView widget to give an idea of my objective, if there is any other option without slivers please feel free to share with me. Thanks in advance :)
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
actions: <Widget>[
Icon(
Icons.camera_front,
size: 40,
)
],
title: Text("Sliver Example"),
leading: Icon(Icons.menu),
backgroundColor: Colors.green,
expandedHeight: 100.0,
floating: true,
pinned: true),
SliverFixedExtentList(
itemExtent: 75,
delegate: SliverChildListDelegate([
Container(
color: Colors.blue,
child: Text("1"),
),
Container(
color: Colors.pink,
child: Text("2"),
),
Container(
color: Colors.yellow,
child: Text("3"),
),
Container(
color: Colors.red,
child: Text("4"),
),
Container(
color: Colors.black,
child: Text(
"Desired Appbar Conainer number 5, which will stuck\n there instead of the sliverappbar sliver example when it reached to the top ",
style: TextStyle(color: Colors.white),
),
),
Container(
color: Colors.amber,
child: Text("6"),
),
Container(
color: Colors.blue,
child: Text("7"),
),
Container(
color: Colors.yellow,
child: Text("8"),
),
Container(
color: Colors.blue,
child: Text("9"),
),
Container(
color: Colors.pink,
child: Text("10"),
),
Container(
color: Colors.blue,
child: Text("11"),
),
Container(
color: Colors.yellow,
child: Text("12"),
),
Container(
color: Colors.blue,
child: Text("13"),
),
Container(
color: Colors.purpleAccent,
child: Text("14"),
),
Container(
color: Colors.white,
child: Text("15"),
),
]),
),
],
),
),
);
}
}
Seems I found a working solution of this problem.The answer is Based on => this post
Here is the code of mine to resolve the issue -
import 'package:flutter/material.dart';
import 'dart:math' as math;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
SliverPersistentHeader makeHeader(String headerText) {
return SliverPersistentHeader(
pinned: true,
delegate: _SliverAppBarDelegate(
minHeight: 75.0,
maxHeight: 75.0,
child: Container(
color: Colors.black,
child: Center(
child: Text(
headerText,
style: TextStyle(color: Colors.white),
),
),
),
),
);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverFixedExtentList(
itemExtent: 75,
delegate: SliverChildListDelegate([
Container(
color: Colors.blue,
child: Text("1"),
),
Container(
color: Colors.pink,
child: Text("2"),
),
Container(
color: Colors.yellow,
child: Text("3"),
),
Container(
color: Colors.red,
child: Text("4"),
),
]),
),
makeHeader("Container Number 5"),
SliverFixedExtentList(
itemExtent: 75,
delegate: SliverChildListDelegate([
Container(
color: Colors.amber,
child: Text("6"),
),
Container(
color: Colors.blue,
child: Text("7"),
),
Container(
color: Colors.yellow,
child: Text("8"),
),
Container(
color: Colors.blue,
child: Text("9"),
),
Container(
color: Colors.pink,
child: Text("10"),
),
Container(
color: Colors.blue,
child: Text("11"),
),
Container(
color: Colors.yellow,
child: Text("12"),
),
Container(
color: Colors.blue,
child: Text("13"),
),
Container(
color: Colors.purpleAccent,
child: Text("14"),
),
Container(
color: Colors.white,
child: Text("15"),
),
Container(
color: Colors.yellow,
child: Text("12"),
),
Container(
color: Colors.blue,
child: Text("13"),
),
Container(
color: Colors.purpleAccent,
child: Text("14"),
),
Container(
color: Colors.white,
child: Text("15"),
),
Container(
color: Colors.yellow,
child: Text("12"),
),
Container(
color: Colors.blue,
child: Text("13"),
),
Container(
color: Colors.purpleAccent,
child: Text("14"),
),
Container(
color: Colors.white,
child: Text("15"),
),
Container(
color: Colors.yellow,
child: Text("12"),
),
Container(
color: Colors.blue,
child: Text("13"),
),
Container(
color: Colors.purpleAccent,
child: Text("14"),
),
Container(
color: Colors.white,
child: Text("15"),
),
]),
),
],
),
),
);
}
}
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
_SliverAppBarDelegate({
#required this.minHeight,
#required this.maxHeight,
#required this.child,
});
final double minHeight;
final double maxHeight;
final Widget child;
#override
double get minExtent => minHeight;
#override
double get maxExtent => math.max(maxHeight, minHeight);
#override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return new SizedBox.expand(child: child);
}
#override
bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}
Hope this will help someone like me :)
your idea is still working, just need a little tweak, instead of using SliverFixedExtentList, you can use this, flutter_sticky_header, it provides sticky sliver list header, for your case, you can just set one header:
import 'package:flutter/material.dart';
import 'package:flutter_sticky_header/flutter_sticky_header.dart';
import '../common.dart';
class ListExample extends StatelessWidget {
const ListExample({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: [
//SliverAppBar(),
//SliverList(),
_StickyHeaderList(index: 2),
//SliverList(),
],
);
}
}
class _StickyHeaderList extends StatelessWidget {
const _StickyHeaderList({
Key key,
this.index,
}) : super(key: key);
final int index;
#override
Widget build(BuildContext context) {
return SliverStickyHeader(
header: Header(index: index),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
(context, i) => ListTile(
leading: CircleAvatar(
child: Text('$index'),
),
title: Text('List tile #$i'),
),
childCount: 6,
),
),
);
}
}
Related
I tried to acheive from NestedScrollView by creating a sample code. But its not exactly which I want. Please help me.
I want to achieve this ui. When scrolling appbar should dock at the top. Image top should start from status bar to the fixed height 300.
After Image there would be some dynamic content like description.
Then I have to add TabBar, which will dock just below the Appbar when scroll.
Body will scroll on top of Header Image, like a overlay.
Image Attachments
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class StickyTabbarExample extends StatefulWidget {
#override
_StickyTabbarExampleState createState() => _StickyTabbarExampleState();
}
class _StickyTabbarExampleState extends State<StickyTabbarExample>
with SingleTickerProviderStateMixin {
// TabController? _tabController;
final List<String> _tabs = <String>[
"Featured",
"Popular",
];
#override
void initState() {
super.initState();
// _tabController = TabController(vsync: this, length: _tabs.length);
}
#override
void dispose() {
// _tabController?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) => Scaffold(
body: DefaultTabController(
length: _tabs.length,
child: NestedScrollView(
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) => <Widget>[
SliverAppBar(
pinned: true,
// floating: true,
toolbarHeight: 70,
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Icon(
Icons.arrow_back_ios_new_sharp,
color: Colors.white,
size: 15,
),
Icon(
Icons.shop,
color: Colors.white,
size: 15,
)
]),
backgroundColor: Colors.green,
expandedHeight: 300,
flexibleSpace: FlexibleSpaceBar(
background: Image.network(
"https://images.unsplash.com/photo-1673942393203-fe61f45b4479?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=870&q=80%20870w",
fit: BoxFit.cover,
width: double.maxFinite,
),
),
),
SliverToBoxAdapter(
child: Positioned.fill(
child: Transform.translate(
offset: Offset(0, -10.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
height: 30,
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.only(
topRight: Radius.circular(100),
topLeft: Radius.circular(100),
),
),
),
Text("Challenge description"),
],
),
),
),
),
SliverPersistentHeader(
delegate: _SliverAppBarDelegate(
TabBar(
indicator: UnderlineTabIndicator(
borderSide: BorderSide(
width: 4,
color: Color(0xFF646464),
),
insets: EdgeInsets.only(left: 0, right: 8, bottom: 4)),
isScrollable: true,
labelPadding: EdgeInsets.only(left: 0, right: 0),
tabs: [
Tab(
child: Text(
"Tab 1",
style: TextStyle(color: Colors.black),
),
),
Tab(
child: Text(
"Tab 2",
style: TextStyle(color: Colors.black),
)),
],
),
),
pinned: true,
),
],
body: TabBarView(children: [TabA(), TabB()]),
),
),
);
}
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
_SliverAppBarDelegate(this._tabBar);
final TabBar _tabBar;
#override
double get minExtent => _tabBar.preferredSize.height;
#override
double get maxExtent => _tabBar.preferredSize.height;
#override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) =>
Container(
color: Colors.white,
child: _tabBar,
);
#override
bool shouldRebuild(_SliverAppBarDelegate oldDelegate) => false;
}
class TabA extends StatelessWidget {
const TabA({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) => CustomScrollView(
// primary: false,
key: PageStorageKey<String>("Tab1"),
slivers: [
SliverPadding(
padding: EdgeInsets.symmetric(vertical: 24, horizontal: 16),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) => Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: index % 2 == 0 ? Colors.green : Colors.greenAccent,
height: 80,
alignment: Alignment.center,
child: Text(
"Item $index",
style: const TextStyle(fontSize: 30),
),
),
),
// 40 list items
childCount: 40,
),
),
)
],
);
}
class TabB extends StatelessWidget {
const TabB({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) => CustomScrollView(
key: PageStorageKey<String>("Tab2"),
slivers: [
SliverPadding(
padding: EdgeInsets.symmetric(vertical: 24, horizontal: 16),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) => Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: index % 2 == 0 ? Colors.green : Colors.greenAccent,
height: 80,
alignment: Alignment.center,
child: Text(
"Item $index",
style: const TextStyle(fontSize: 30),
),
),
),
childCount: 40,
),
),
)
],
);
}
I have this piece of code inside a scaffold with SafeArea:
Column(
children: [Flexible(
fit: FlexFit.loose,
child: Container(
// width: 130,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [Icon(Icons.ac_unit), Text("Trending")],
),
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.grey[300]),
),
)]
)
Which gives the following result:
What I want to achieve is this:
How do I make the row warp around the text.
from the documentation
Wrap(
spacing: 8.0, // gap between adjacent chips
runSpacing: 4.0, // gap between lines
children: <Widget>[
Chip(
avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text('AH')),
label: Text('Hamilton'),
),
Chip(
avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text('ML')),
label: Text('Lafayette'),
),
Chip(
avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text('HM')),
label: Text('Mulligan'),
),
Chip(
avatar: CircleAvatar(backgroundColor: Colors.blue.shade900, child: Text('JL')),
label: Text('Laurens'),
),
],
)
if you want to use that row just do
Row(
mainAxisSize: MainAxisSize.min
children: [
...
])
replace that Chip() with the above row
Edit:
replace the Chip() with that _buildChip() custom widget something like this, It should give you a better control over the widget
import 'package:flutter/material.dart';
main() {
runApp(MaterialApp(
home: MyPage(),
));
}
class MyPage extends StatelessWidget {
Widget _buildChip() {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20), color: Colors.grey.withOpacity(.4) ),
child: InkWell(
highlightColor: Colors.blue.withOpacity(.4),
splashColor: Colors.green,
borderRadius: BorderRadius.circular(20),
onTap: () {
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 15, vertical: 7),
child: Row(
mainAxisSize: MainAxisSize.min,
children:[
Icon(Icons.ac_unit, size: 14),
SizedBox(width: 10),
Text("Trending")
]),
),
),
);
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Wrap(
spacing: 8.0, // gap between adjacent chips
runSpacing: 4.0, // gap between lines
children: <Widget>[
_buildChip(),
_buildChip(),
_buildChip(),
_buildChip(),
_buildChip(),
],
)
);
}
}
let me know if It is what you want, so that I edit that answer
Take a look at this example. You should be using Wrap and RichText to achieve this design. Not Flexible, because it will take all the available space.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
MyHomePage({Key? key, required this.title}) : super(key: key);
#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: Wrap(children: [
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20), color: Colors.grey[300]),
child: RichText(
text: TextSpan(
children: [
WidgetSpan(
child: Icon(Icons.ac_unit, size: 14),
),
TextSpan(
text: "Trending",
),
],
),
),
),
SizedBox(width: 5,),
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20), color: Colors.grey[300]),
child: RichText(
text: TextSpan(
children: [
WidgetSpan(
child: Icon(Icons.ac_unit, size: 14),
),
TextSpan(
text: "Trending",
),
],
),
),
)
]),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
I am currently developing an app which people can save their receipt in it, I shared home screen below,initial time It will be empty, as soon as user add new menu, it will get full with menu, After user added new menu, the should be able to click the menu container, and access to new screen for example, İn home screen I created container which called "CAKES", the cakes screen should be created, if I created another menu in my home screen It should also created too, I currently menu extanded screen as a statefull widget already, you can see below, but my question is How can I create this page for spesific menu's , How can I store them, in list, in map etc, Lastly, I dont want user information dissapear, I know I have to use database, but I want to use local database, How can I handle with that, Have a nice day...
import 'package:flutter/material.dart';
import 'package:lezzet_kitabi/add_menu_screen.dart';
import 'package:lezzet_kitabi/constants.dart';
import 'package:lezzet_kitabi/widgets.dart';
class HomeScreen extends StatefulWidget {
HomeScreen({this.newMenuName,this.imagePath});
final imagePath;
final newMenuName;
static String id="homeScreen";
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
Widget buildBottomSheet(BuildContext context)=>AddMenuScreen(buttonText: "Menü Ekle",route: HomeScreen,);
void initState(){
super.initState();
if (widget.newMenuName!=null && widget.imagePath!=null){
Widget newMenu=MenuCard(newMenuName: widget.newMenuName,imagePath: widget.imagePath);
menuCards.insert(0,newMenu);
}
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: kColorTheme1,
appBar: AppBar(
centerTitle: true,
automaticallyImplyLeading: false,
elevation: 5,
backgroundColor: Color(0xFFF2C3D4).withOpacity(1),
title:TitleBorderedText(title:"SEVIMLI YEMEKLER", textColor: Color(0xFFFFFB00)),
actions: [
CircleAvatar(
radius: 27,
backgroundColor: Colors.transparent,
backgroundImage: AssetImage(kCuttedLogoPath),
),
],
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(kBGWithLogoOpacity),
fit: BoxFit.cover,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: GridView.count(
crossAxisCount: 2,
children:menuCards,
),
),
Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: EdgeInsets.all(10),
child: Container(
decoration: BoxDecoration(
boxShadow:[
BoxShadow(
color: Colors.black.withOpacity(1),
spreadRadius: 2,
blurRadius: 7,
offset: Offset(0,4),
),
],
color: kColorTheme7,
borderRadius: BorderRadius.circular(40),
),
child: FlatButton(
onPressed: (){
showModalBottomSheet(
context: context,
builder: (BuildContext context)=> AddMenuScreen(buttonText: "Menü Ekle",route: "homeScreen",),
);
},
child: TitleBorderedText(title: "LEZZET GRUBU EKLE",textColor: Colors.white,)
),
),
),
],
)
],
),
),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:lezzet_kitabi/screens/home_screen.dart';
import 'package:lezzet_kitabi/widgets.dart';
import 'constants.dart';
import 'dart:math';
class AddMenuScreen extends StatefulWidget {
AddMenuScreen({#required this.buttonText, #required this.route});
final route;
final String buttonText;
static String id="addMenuScreen";
#override
_AddMenuScreenState createState() => _AddMenuScreenState();
}
class _AddMenuScreenState extends State<AddMenuScreen> {
int selectedIndex=-1;
Color _containerForStickersInactiveColor=Colors.white;
Color _containerForStickersActiveColor=Colors.black12;
final stickerList= List<String>.generate(23, (index) => "images/sticker$index");
String chosenImagePath;
String menuName;
int addScreenImageNum;
void initState(){
super.initState();
createAddScreenImageNum();
}
void createAddScreenImageNum(){
Random random =Random();
addScreenImageNum = random.nextInt(3)+1;
}
#override
Widget build(BuildContext context) {
return Material(
child: Container(
color: kColorTheme9,
child: Container(
height: 400,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(topRight: Radius.circular(40),topLeft: Radius.circular(40)),
),
child:Padding(
padding:EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
decoration: BoxDecoration(
color: kColorTheme2,
borderRadius: BorderRadius.circular(90)
),
child: TextField(
style: TextStyle(
color: Colors.black,
fontFamily:"Graduate",
fontSize: 20,
),
textAlign: TextAlign.center,
onChanged: (value){
menuName=value;
},
decoration: InputDecoration(
border:OutlineInputBorder(
borderRadius: BorderRadius.circular(90),
borderSide: BorderSide(
color: Colors.teal,
),
),
hintText: "Menü ismi belirleyin",
hintStyle: TextStyle(
color: Colors.black.withOpacity(0.2),
fontFamily: "Graduate",
),
),
),
),
SizedBox(height: 20,),
Text(" yana kadırarak menünüz icin bir resim secin",textAlign: TextAlign.center,
style: TextStyle(fontFamily: "Graduate", fontSize: 12),),
SizedBox(height: 20,),
Expanded(
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: stickerList.length,
itemBuilder: (context,index){
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: index == selectedIndex ?
_containerForStickersActiveColor :
_containerForStickersInactiveColor,
),
child:FlatButton(
child: Image(
image: AssetImage("images/sticker$index.png"),
),
onPressed: (){
setState(() {
selectedIndex = index;
});
},
),
);
}
),
),
SizedBox(height: 20,),
Container(
decoration: BoxDecoration(
border: Border.all(style: BorderStyle.solid),
color: kColorTheme7,
borderRadius: BorderRadius.circular(90),
),
child: FlatButton(
onPressed: (){
widget.route=="homeScreen"?Navigator.push(context, MaterialPageRoute(builder: (context)=>HomeScreen(newMenuName: menuName,imagePath: "images/sticker$selectedIndex.png")))
:Navigator.push(context, MaterialPageRoute(builder: (context)=>MenuExtension(menuExtensionName: menuName)),
);
},
child: Text(widget.buttonText, style: TextStyle(fontSize: 20, color: Colors.white,
fontFamily: "Graduate", fontWeight: FontWeight.bold),),
),
),
],
),
),
),
),
);
}
}
import 'package:flutter/material.dart';
import 'dart:math';
import 'add_menu_screen.dart';
import 'package:bordered_text/bordered_text.dart';
import 'package:lezzet_kitabi/screens/meal_screen.dart';
import 'constants.dart';
List<Widget> menuExtensionCards=[EmptyMenu()];
List<Widget> menuCards=[EmptyMenu()];
class MenuCard extends StatelessWidget {
MenuCard({this.newMenuName, this.imagePath});
final newMenuName;
final imagePath;
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(top:15.0),
child: FlatButton(
onPressed: (){
Navigator.push(context, MaterialPageRoute(builder: (context)=>MenuExtension(menuExtensionName: newMenuName,)));
},
child: Container(
height: 180,
width: 180,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Color((Random().nextDouble() * 0xFFFFFF).toInt()).withOpacity(0.5),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(height: 10,),
Container(
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.5),
borderRadius: BorderRadius.circular(90),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
newMenuName,
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontFamily: 'Graduate',
fontWeight: FontWeight.bold),
),
),
),
Expanded(
child: Padding(
padding:EdgeInsets.all(5),
child: Image(
image: AssetImage(
imagePath
),
),
),
),
],
),
),
),
);
}
}
class EmptyMenu extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(top:15.0),
child: FlatButton(
onPressed: (){
showModalBottomSheet(
context: context,
builder: (BuildContext context)=> AddMenuScreen(buttonText: "Menü Ekle",route:"homeScreen"),
);
},
child: Container(
height: 180,
width: 180,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.black12.withOpacity(0.1),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(Icons.add_circle_outline_outlined,size: 100,color: Colors.grey.shade400,),
],
),
),
),
);
}
}
class MenuExtension extends StatefulWidget {
MenuExtension({this.menuExtensionName});
final String menuExtensionName;
#override
_MenuExtensionState createState() => _MenuExtensionState();
}
class _MenuExtensionState extends State<MenuExtension> {
Widget buildBottomSheet(BuildContext context)=>AddMenuScreen(buttonText: "Tarif Ekle",route: MealScreen,);
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
centerTitle: true,
automaticallyImplyLeading: false,
elevation: 5,
backgroundColor: Color(0xFFF2C3D4).withOpacity(1),
title:BorderedText(
child:Text(
widget.menuExtensionName,
style: TextStyle(
color: Color(0XFFFFFB00),
fontSize: 30,
fontFamily: "Graduate"
),
),
strokeWidth: 5,
strokeColor: Colors.black,
),
actions: [
CircleAvatar(
radius: 27,
backgroundColor: Colors.transparent,
backgroundImage: AssetImage("images/cuttedlogo.PNG"),
),
],
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("images/logoBGopacity.png"),
fit: BoxFit.cover,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: GridView.count(
crossAxisCount: 2,
children:menuExtensionCards,
),
),
Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: EdgeInsets.all(10),
child: Container(
decoration: BoxDecoration(
boxShadow:[
BoxShadow(
color: Colors.black.withOpacity(1),
spreadRadius: 2,
blurRadius: 7,
offset: Offset(0,4),
),
],
color: kColorTheme7,
borderRadius: BorderRadius.circular(40),
),
child: FlatButton(
onPressed: (){
showModalBottomSheet(
context: context,
builder: (BuildContext context)=> AddMenuScreen(buttonText: "Tarif Ekle", route:"mealScreen"),
);
},
child: BorderedText(
strokeWidth: 5,
strokeColor: Colors.black,
child:Text("Tarif Ekle",style: TextStyle(
color: Colors.white,
fontFamily:'Graduate',
fontSize:30,
),
),
),
),
),
),
],
)
],
),
),
),
);
}
}
class TitleBorderedText extends StatelessWidget {
TitleBorderedText({this.title, this.textColor});
final Color textColor;
final String title;
#override
Widget build(BuildContext context) {
return BorderedText(
strokeWidth: 5,
strokeColor: Colors.black,
child:Text(title,style: TextStyle(
color: textColor,
fontFamily:'Graduate',
fontSize:30,
),
),
);
}
}
Hi I would like to know how can I access the items of a list on a different class where the list was created.Particularly i want to access items of the restaurantList on the Restaurant Screen class.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:projectfooddelivery/Src/models/restaurant.dart';
List<Restaurant> restaurantList=[
Restaurant(image:"kfcloja.jpg",distance: "2 miles away",location:"Shoprite do magoanine",restaurantName: "KFC"),
Restaurant(image:"dominos.jpg",distance: "0.9 miles away",location:"Downtown",restaurantName: "Dominos"),
Restaurant(image:"kfclogo.png",distance: "2 miles away",location:"Shoprite do magoanine",restaurantName: "KFC"),
];//I would like to access the items on the list
class RestaurantWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
height: 350,
child: ListView.builder(
scrollDirection: Axis.vertical,
itemCount: restaurantList.length,
itemBuilder: (_, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 1.0,
color: Colors.grey[100]
),
borderRadius: BorderRadius.circular(20)
),
child: Row(
children: <Widget>[
Container(
width: 150,
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Image.asset("images/${restaurantList[index].image}",fit:BoxFit.cover ,)
)
),
Padding(
padding: const EdgeInsets.all(3.0),
child: Container(
padding: EdgeInsets.all(2),
height: 70,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("${restaurantList[index].restaurantName}",style: TextStyle(fontWeight: FontWeight.bold),),
Row(
children: <Widget>[
Icon(Icons.star,size: 15,color:Colors.yellowAccent,),
Icon(Icons.star,size: 15,color:Colors.yellowAccent),
Icon(Icons.star,size: 15,color:Colors.yellowAccent),
Icon(Icons.star,size: 15,color:Colors.yellowAccent),
Icon(Icons.star_half,size: 15,color:Colors.yellowAccent),
],
),
Text("${restaurantList[index].location}"),
Text("${restaurantList[index].distance}"),
],
),
),
),
],
),
),
);
},
),
);
}
}
In this class
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:projectfooddelivery/Src/widgets/menu_widget.dart';
import 'package:smooth_star_rating/smooth_star_rating.dart';
class RestaurantScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: 400,
child: Column(
children: <Widget>[
Stack(
children: <Widget>[
Image.asset(
"images/kfcloja.jpg",
fit: BoxFit.cover,
),
Positioned(
child: IconButton(
icon: Icon(Icons.keyboard_arrow_left,size: 40,color: Colors.white,),
onPressed: (){},
),
top: 15,
)
],
),
Padding(
padding: const EdgeInsets.only(top: 14, left: 14, right: 14),
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Restaurant KFC",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
Text(
"0.2 miles away",
style: TextStyle(
fontSize: 16,
),
),
],
),
Align(
alignment: Alignment.topLeft,
child: SmoothStarRating(
allowHalfRating: false,
starCount: 5,
size: 20.0,
filledIconData: Icons.blur_off,
halfFilledIconData: Icons.blur_on,
color: Colors.yellowAccent,
borderColor: Colors.yellowAccent,
spacing: 0.0),
),
Align(
alignment: Alignment.topLeft,
child: Text("200 Main St, New york"),
),
Padding(
padding: const EdgeInsets.only(
left: 30, right: 30, top: 20, bottom: 5),
child: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
FlatButton.icon(
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(10.0),
),
color: Theme.of(context).primaryColor,
icon: Icon(
Icons.rate_review,
color: Colors.white,
),
label: Text(
'Reviews',
style: TextStyle(color: Colors.white),
),
onPressed: () {},
),
FlatButton.icon(
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(10.0),
),
color: Theme.of(context).primaryColor,
icon: Icon(
Icons.contact_phone,
color: Colors.white,
),
label: Text(
'Contact',
style: TextStyle(color: Colors.white),
),
onPressed: () {},
)
],
),
),
),
Text(
"Menu",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 20),
),
MenuWidget(),
],
)
),
)
],
),
),
);
}
}
You can send and receive the data from one screen to another as follow , you need to use the Navigator for it , In below example i am sending the data from class A to class B as follow
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => B(bean: restaurantList[index])), //// HERE B IS THE CLASS ON WHICH YOU NEED TO CARRY DATA FROM CLASS A
);
And inside the B class you need to create the contrsutor to receive the data from A like below
class B extends StatefulWidget {
Restaurant bean;
B ({Key key, #required this.bean}) : super(key: key); ////YOU WILL GET THE DATA HERE FROM THE CONSTRUCTOR , AND USE IT INSIDE THE CLASS LIKE "widget.bean"
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _B();
}
}
And please check the example of it to pass data from one class to another
A class which send data to B class
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'B.dart';
import 'Fields.dart';
class A extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _A();
}
}
class _A extends State<A> {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Screen A',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.red,
accentColor: Color(0xFFFEF9EB),
),
home: Scaffold(
appBar: new AppBar(),
body: Container(
margin: EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: Text("Screen A"),
),
Expanded(
child: ListView.builder(
itemCount: fields.length,
itemBuilder: (BuildContext ctxt, int index) {
return ListTile(
title: new Text("Rating #${fields[index].rating}"),
subtitle: new Text(fields[index].title),
onTap: (){
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => B(bean: fields [index])), //// HERE B IS THE CLASS ON WHICH YOU NEED TO CARRY DATA FROM CLASS A
);
},
);
}),
)
],
),
)));
}
}
List<Fields> fields = [
new Fields(
'One',
1,
),
new Fields(
'Two',
2,
),
new Fields(
'Three',
3,
),
new Fields(
'Four',
4,
),
new Fields(
'Five',
5,
),
];
Now check B class which receive the data from A class
import 'package:flutter/material.dart';
import 'Fields.dart';
class B extends StatefulWidget{
Fields bean;
B ({Key key, #required this.bean}) : super(key: key); ////YOU WILL GET THE DATA HERE FROM THE CONSTRUCTOR , AND USE IT INSIDE THE CLASS LIKE "widget.bean"
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _B ();
}
}
class _B extends State<B> {
#override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
title: 'Screen A',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.red,
accentColor: Color(0xFFFEF9EB),
),
home: Scaffold(
appBar: new AppBar(),
body: Container(
margin: EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: Center(
child: Text("Screen B" ,style: TextStyle(fontSize: 20.0),),
)
),
Text("Rating=>>> ${widget.bean.rating} and Title ${widget.bean.title} ")
],
),
)));
}
}
And I have used the Pojo class for the list ,please check it once
Fields.dart
class Fields {
final String title;
final int rating;
Fields(this.title, this.rating);
}
And the output of the above program as follow.
I have tried to implement a layout like this using flutter.
I have used the Cupertino Picker Class for that.
But it just looks not as good as I want it to look.
I have tried to fix it by using the properties, that are listed on the flutter website, but I did not find any better solution. How can I fix this issue or is there even another widget that is better in this case?
My code looks like this:
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
backgroundColor: Colors.red,
),
child: Container(
child: Center(
child: CupertinoPicker(
itemExtent: 40,
diameterRatio: 5,
offAxisFraction: 10,
backgroundColor: Colors.black54,
onSelectedItemChanged: (int index) {
print(index);
},
children: <Widget>[
Text('Tap', style: TextStyle(color:Colors.white)),
Text('Colorbattle',style: TextStyle(color:Colors.white)),
Text('Patience',style: TextStyle(color:Colors.white)),
],
))));
}
}
Playing around your code, I've tried to implement the same behavior. I've observed that changing the values of diameterRatio and offAxisFraction could change the way your UI look like. In my sample, the values of diameterRatio and offAxisFraction is 10 and -1 respectively. Just imagine this kind of roulette:
diameterRatio is the diameter of the cylinder and offAxisFraction is the axis where the side of the cylinder is facing. To mimic the example in the picture, set the value of the offAxisFraction to a positive value, in the implementation shown below, I've set it to 10.
Below is an example of copy the behavior of the UI you're trying to replicate:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
backgroundColor: Colors.red,
),
child: Center(
child: Container(
// color: Colors.black54,
decoration: BoxDecoration(
border: Border.all(color: Colors.white),
borderRadius: BorderRadius.all(
Radius.circular(15),
),
),
width: 200.0,
height: 150.0,
child: Center(
child: CupertinoPicker(
itemExtent: 40,
diameterRatio: 10,
offAxisFraction: -1,
backgroundColor: Colors.black54,
onSelectedItemChanged: (int index) {
print(index);
},
children: <Widget>[
Align(
alignment: Alignment.centerRight,
child: Padding(
padding: const EdgeInsets.only(right: 40.0),
child: Text(
'Estimate',
style: TextStyle(color: Colors.white),
),
),
),
Align(
alignment: Alignment.centerRight,
child: Padding(
padding: const EdgeInsets.only(right: 40.0),
child: Text(
'Random',
style: TextStyle(color: Colors.white),
),
),
),
Align(
alignment: Alignment.centerRight,
child: Padding(
padding: const EdgeInsets.only(right: 40.0),
child: Text(
'Colorbattle',
style: TextStyle(color: Colors.white),
),
),
),
Align(
alignment: Alignment.centerRight,
child: Padding(
padding: const EdgeInsets.only(right: 40.0),
child: Text(
'Patience',
style: TextStyle(color: Colors.white),
),
),
),
Align(
alignment: Alignment.centerRight,
child: Padding(
padding: const EdgeInsets.only(right: 40.0),
child: Text(
'Tap',
style: TextStyle(color: Colors.white),
),
),
),
],
),
),
),
),
);
}
}
Output: