Flutter NeverScrollableScrollPhysics pagenation not work - flutter

I am trying to bind NestedScrollView and GridView with pagenation.
However, I put NeverScrollableScrollPhysics() in the GridView, the pagenation function does not work.
I guess it is caused by scrollcontroller.
How can I solve this problem?
I will attach my code.
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
//infinite scroll
List<DocumentSnapshot> products = []; // stores fetched products
bool isLoading = false; // track if products fetching
bool hasMore = true; // flag for more products available or not
int documentLimit = 20; // documents to be fetched per request
DocumentSnapshot
lastDocument; // flag for last document from where next 10 records to be fetched
ScrollController _scrollController =
ScrollController(); // listener for listview scrolling
#override
void initState() {
getProducts();
_scrollController.addListener(() {
double maxScroll = _scrollController.position.maxScrollExtent;
double currentScroll = _scrollController.position.pixels;
double delta = MediaQuery.of(context).size.height * 0.20;
if (maxScroll - currentScroll <= delta) {
getProducts();
}
});
}
#override
void dispose() {
_scrollController?.dispose();
super.dispose();
}
getProducts() async {
//...
//get items from firebase
//...
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.backgroundwhite,
title: Image(
width: 132.0,
height: 40.0,
image: AssetImage('images/logo_horiz.png'),
),
),
body: NestedScrollView(
headerSliverBuilder: (context, isScrolled) {
return <Widget>[
SliverList(
delegate: SliverChildListDelegate([
Padding(
padding: const EdgeInsets.all(18.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"다른 유저가 키우는",
style: TextStyle(
fontSize: 24.0,
color: Colors.black,
fontWeight: FontWeight.w200,
fontFamily: "Roboto"),
),
Padding(padding: EdgeInsets.fromLTRB(0, 0, 0, 5.0)),
Row(
children: <Widget>[
Text(
"율마",
style: new TextStyle(
fontSize: 24.0,
color: Colors.black,
fontWeight: FontWeight.bold,
fontFamily: "Roboto"),
),
Text(
"가 궁금하신가요?",
style: new TextStyle(
fontSize: 24.0,
color: Colors.black,
fontWeight: FontWeight.w200,
fontFamily: "Roboto"),
),
],
),
Padding(padding: EdgeInsets.fromLTRB(0, 0, 0, 25.0)),
Container(
color: Colors.transparent,
width: double.infinity,
height: 46,
child: FlatButton(
color: Theme.of(context).colorScheme.lightGrey,
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SearchPage()),
);
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)),
child: Row(
children: <Widget>[
Icon(Icons.search,
size: 30.0, color: Colors.black12),
Padding(
padding:
const EdgeInsets.only(right: 10.0),
),
Text(
"율마",
style: new TextStyle(
fontSize: 20.0,
color: Theme.of(context)
.colorScheme
.textBlack,
fontWeight: FontWeight.w200,
fontFamily: "Roboto"),
)
],
))),
]),
),
]))
];
},
body: LayoutBuilder(
builder:(BuildContext context, BoxConstraints viewportConstraints) {
return ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: IntrinsicHeight(
child: Column(children: <Widget>[
Flexible(
// this will host our Tab Views
child: GridView.builder(
// physics: NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: 1.0,
mainAxisSpacing: 1.0,
crossAxisSpacing: 1.0),
controller: _scrollController,
itemCount: products.length,
itemBuilder: (context, index) {
return _buildListItem(context, products[index]);
},
)),
])));
}),
));
}
Widget _buildListItem(BuildContext context, item) {
return Hero(
tag: item.documentID,
child: Material(
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => DetailPostPage(item)),
);
},
child: Image.network(item['imageUrls'][0]['url'], fit: BoxFit.cover),
),
),
);
}
}
Thank you so much

Oh! finally I have solved this problem using CustomScrollView instead of NestedScrollview.
In addition, I wraped the CustomScrollView as LayoutBuilder.
Hense the final code of the body part of Scaffold is following:
LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: CustomScrollView(
// physics: AlwaysScrollableScrollPhysics(),
controller: _scrollController,
slivers: <Widget>[
SliverList(
delegate: SliverChildListDelegate([
_buildHeader()
])),
SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: 1.0,
mainAxisSpacing: 1.0,
crossAxisSpacing: 1.0),
delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
return _buildListItem(context, products[index]);
},
childCount: products.length,
),
)
]
)
);
}),
I hope it would be helpful for you!

Related

Drawer with ListViewBuilder and Header in Flutter

I'm trying to make a drawer widget that uses a ListViewBuilder to populate itself based on a list injected into the ViewModel.
However, I'm having issues getting it to play ball.
I've wrapped the LVB in a SizedBox to provide it with vertical bounds (since it was throwing a bunch of errors, as suggeested by another answer, and that's stopped those, but now I'm getting an overflow.
The header also doesn't fill out the width anymore either.
class MainDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Consumer<MainDrawerViewModel>(builder: (context, model, child) {
return Drawer(
child: Column(
children: [
DrawerHeader(
decoration: const BoxDecoration(color: ThemeColors.primaryDark),
child: Text(S.current.drawerTitle, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 30)),
),
SizedBox(
height: double.maxFinite,
child: ListView.builder(
padding: EdgeInsets.zero,
itemCount: model.mainDrawerItems.length,
itemBuilder: (_, index) {
final drawerItem = model.mainDrawerItems[index];
return ListTile(
leading: drawerItem.icon,
title: Text(drawerItem.title, style: Theme.of(context).textTheme.headline6),
selected: model.currentScreen == drawerItem.screen,
selectedTileColor: ThemeColors.selectedDrawerItem,
onTap: () {
model.selectScreen(drawerItem.screen);
Navigator.pop(context);
},
);
}),
),
],
));
});
}
}
This feels like something that should be pretty easy... What am I missing here?
Use Expanded widget on listView instead of height: double.maxFinite,
Expanded(
child: ListView.builder(
padding: EdgeInsets.zero,
double.maxFinite = 1.7976931348623157e+308; and it is equal to 1.7976931348623157 × 10^308 which is too big. and the overflow happens.
For header, you can wrap With SizedBox and provide width: double.maxFinite,. Also you can just use a container with decoration like
class MainDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Drawer(
child: Column(
children: [
Container(
width: double.maxFinite,
height: 200, // based on your need
decoration: const BoxDecoration(color: Colors.amber),
padding: EdgeInsets.only(left: 16, top: 16),
child: Text(
"S.cu ",
style: TextStyle(
color: ui.Color.fromARGB(255, 203, 19, 19),
fontWeight: FontWeight.bold,
fontSize: 30),
),
),
Expanded(
child: ListView.builder(
padding: EdgeInsets.zero,
itemCount: 3,
itemBuilder: (_, index) {
return ListTile(
leading: Icon(Icons.abc_outlined),
title: Text("drawerItem.title",
style: Theme.of(context).textTheme.headline6),
selected: true,
onTap: () {},
);
}),
),
],
));
}
}

How to scroll with NestedScrollView to use stack Circle Avatar over SliverAppBar?

I am dealing with a Flutter project recently and I have such a problem.
See photo 1: here's my code: the photo and text should be between the TabBar widget and the red background like in design (blue).
Here you can see my actual code:
class Main
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
PortfolioSliverAppBar(_pages[_tabController.index].item1),
SliverPersistentHeader(
delegate: SliverPersistentHeaderDelegateImpl(
tabBar: TabBar(
padding: EdgeInsets.only(top: 15.0),
labelColor: Colors.black,
indicatorColor: Colors.black,
indicator: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(18)),
color: Colors.blue),
controller: _tabController,
tabs: _pages
.map<Tab>((Tuple3 page) => Tab(text: page.item1))
.toList(),
),
),
),
];
},
body: Container(
margin: EdgeInsets.only(top: 20.0),
child: TabBarView(
controller: _tabController,
children: _pages.map<Widget>((Tuple3 page) => page.item2).toList(),
),
),
class Silver
class SliverPersistentHeaderDelegateImpl extends SliverPersistentHeaderDelegate {
final TabBar tabBar;
final Color color;
const SliverPersistentHeaderDelegateImpl({
Color color = Colors.transparent,
#required this.tabBar,
}) : this.color = color;
#override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
return Container(
color: color,
child: tabBar,
);
}
See photo 2: here's the given design:
my view
the actual UI
Thanks a lot!
Please refer to below code
class NestedScrollWithTabs extends StatefulWidget {
const NestedScrollWithTabs({Key key}) : super(key: key);
#override
_NestedScrollWithTabsState createState() => _NestedScrollWithTabsState();
}
class _NestedScrollWithTabsState extends State<NestedScrollWithTabs>
with TickerProviderStateMixin {
var animation;
var controller;
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: DefaultTabController(
length: 2,
child: NestedScrollView(
physics: NeverScrollableScrollPhysics(),
headerSliverBuilder: (headerCtx, innnerBoxIsScrolled) {
if (innnerBoxIsScrolled) {
/* Animation */
controller = AnimationController(
vsync: this,
duration: Duration(
seconds: 1,
),
);
animation = Tween(
begin: 0.0,
end: 1.0,
).animate(controller);
/* Animation */
controller.forward();
}
return <Widget>[
SliverAppBar(
expandedHeight: ScreenUtil().setHeight(185.0),
floating: false,
pinned: true,
backgroundColor: Colors.white,
automaticallyImplyLeading: false,
titleSpacing: 0.0,
centerTitle: true,
elevation: 0.0,
leadingWidth: 0.0,
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
if (innnerBoxIsScrolled != null &&
innnerBoxIsScrolled == true)
FadeTransition(
opacity: animation,
child: Text(
"Title",
style: TextStyle(
color: Colors.black,
fontSize: 22,
fontWeight: FontWeight.bold,
),
),
),
],
),
flexibleSpace: FlexibleSpaceBar(
background: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Stack(
alignment: Alignment.center,
clipBehavior: Clip.none,
children: [
Image.network(
"https://images.pexels.com/photos/10181294/pexels-photo-10181294.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" ??
"",
fit: BoxFit.fitWidth,
height: ScreenUtil().setHeight(126.0),
width: ScreenUtil().screenWidth,
filterQuality: FilterQuality.low,
loadingBuilder: (BuildContext context,
Widget child,
ImageChunkEvent loadingProgress) {
if (loadingProgress == null) return child;
return Container(
height: ScreenUtil().setHeight(126.0),
width: ScreenUtil().screenWidth,
color: Colors.grey,
);
},
errorBuilder: (context, error, stackTrace) {
return SizedBox(
height: ScreenUtil().setHeight(126.0),
width: ScreenUtil().screenWidth,
child: Container(
width: ScreenUtil().screenWidth,
),
);
},
),
Positioned(
top: ScreenUtil().setHeight(92.0),
// left: ScreenUtil().setWidth(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
CircleAvatar(
backgroundColor: Colors.transparent,
radius: 30.0,
child: ClipRRect(
borderRadius: BorderRadius.circular(
45.0,
),
child: Image.network(
"https://images.pexels.com/photos/10181294/pexels-photo-10181294.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" ??
"",
fit: BoxFit.fill,
height: ScreenUtil().setHeight(72.0),
width: ScreenUtil().screenWidth,
filterQuality: FilterQuality.low,
loadingBuilder: (BuildContext context,
Widget child,
ImageChunkEvent loadingProgress) {
if (loadingProgress == null)
return child;
return Container(
height:
ScreenUtil().setHeight(72.0),
width: ScreenUtil().screenWidth,
color: Colors.grey,
);
},
errorBuilder:
(context, error, stackTrace) {
return SizedBox(
height:
ScreenUtil().setHeight(72.0),
width: ScreenUtil().screenWidth,
child: Container(
width: ScreenUtil().screenWidth,
),
);
},
),
),
),
Text("Name"),
Text("Place"),
],
),
),
],
),
],
),
),
),
SliverOverlapAbsorber(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
headerCtx),
sliver: SliverPersistentHeader(
delegate: SliverAppBarDelegate(TabBar(
labelColor: Colors.blue,
unselectedLabelColor: Colors.black,
labelStyle: TextStyle(
fontSize: 15.0,
),
unselectedLabelStyle: TextStyle(
fontSize: 15.0,
),
labelPadding: EdgeInsets.zero,
indicatorColor: Colors.blue,
indicatorPadding: EdgeInsets.zero,
physics: NeverScrollableScrollPhysics(),
tabs: [
Tab(
text: "Tab 1",
),
Tab(
text: "Tab 2",
),
],
)),
pinned: false,
),
),
];
},
body: TabBarView(
children: [
/* Tab 1 */
Container(
color: Colors.white,
child: ListView.builder(
itemCount: 100,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: Text("Index value: $index"),
);
},
),
),
/* Tab 2 */
Container(
color: Colors.white,
child: ListView.builder(
itemCount: 10,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: Text("Index value of Tab 2: $index"),
);
},
),
),
],
),
),
),
),
);
}
}
class SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
SliverAppBarDelegate(this.tabBars);
final TabBar tabBars;
#override
double get minExtent => 60.0;
#override
double get maxExtent => 60.0;
#override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
// shinkOffsetPerValue.value = shrinkOffset;
return new Container(
color: Colors.white,
child: Column(
children: [
tabBars,
],
),
);
}
#override
bool shouldRebuild(SliverAppBarDelegate oldDelegate) {
return false;
}
}

Flutter: Scroll view not responding

I am pretty new to flutter. I have build a landing page using grid view and added a bottom navigation bar. The navigation bar is called first after login in and I have added the screen to the navigation class. The issue am facing is that the navigation bar is on top of my grid items, when I try to scroll up, the grid items are sticky and not moving, what am I not doing right??
my home screen code
class GridDashboard extends StatelessWidget {
var services = [
"Home",
"Update",
"Bluetooth",
"Forms",
"Supervisor",
"Messages",
"Settings",
"App updates",
"Logout",
];
var images = [
"assets/home.png",
"assets/updated.png",
"assets/bluetooth.png",
"assets/todo.png",
"assets/supervisor.png",
"assets/message.png",
"assets/setting.png",
"assets/update.ico",
"assets/logout.png",
];
#override
Widget build(BuildContext context) {
List<Items> myList = [home, update, bluetooth, forms, supervisor, messages, settings, check, logout];
var color = 0xff453658;
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 500,
// margin: EdgeInsets.only(top: 10),
// padding: EdgeInsets.all(20),
child: GridView.builder(
// add this
shrinkWrap: true,
itemCount: services.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.4),
),
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
Navigator.push(context, new MaterialPageRoute<Widget>(
builder: (BuildContext context) {
if(myList != null){
return myList[index].screen;
}else{
return null;
}
}));
},
child: Padding(
padding: EdgeInsets.all(3),
child: Card(
elevation: 10,
child: ListView(
children: <Widget>[
SizedBox(
height: 20,
),
Image.asset(
images[index],
height: 50.0,
width: 50.0,
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Text(
services[index],
style: TextStyle(
fontSize: 16.0,
height: 1.2,
color: Colors.white,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
),
],
),
color: Color(color),
),
),
);
},
),
),
);
}
}
class Items {
String title;
String subtitle;
String event;
String img;
final Widget screen;
Items({this.title, this.subtitle, this.event, this.img, this.screen});
}
my Nav bar code
class _NavSCreenState extends State<NavSCreen> {
final List<Widget> _screens = [Home()];
final List<IconData> _icons = const [
Icons.home,
Icons.settings,
MdiIcons.accountCircleOutline,
MdiIcons.accountGroupOutline,
Icons.menu,
];
int _selectedIndex = 0;
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: _icons.length,
child: Scaffold(
body: IndexedStack(index: _selectedIndex, children: _screens),
bottomNavigationBar: Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: CustomTabBar(
icons: _icons,
selectedIndex: _selectedIndex,
onTap: (index) => setState(() => _selectedIndex = index),
),
),
));
}
}
Try this by adding SingleChildScrollView. Hope this will solve your problem.
#override
Widget build(BuildContext context) {
List<Items> myList = [home, update, bluetooth, forms, supervisor, messages, settings, check, logout];
var color = 0xff453658;
return Scaffold(
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 500,
// margin: EdgeInsets.only(top: 10),
// padding: EdgeInsets.all(20),
child: GridView.builder(
// add this
shrinkWrap: true,
itemCount: services.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.4),
),
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
Navigator.push(context, new MaterialPageRoute<Widget>(
builder: (BuildContext context) {
if(myList != null){
return myList[index].screen;
}else{
return null;
}
}));
},
child: Padding(
padding: EdgeInsets.all(3),
child: Card(
elevation: 10,
child: ListView(
children: <Widget>[
SizedBox(
height: 20,
),
Image.asset(
images[index],
height: 50.0,
width: 50.0,
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Text(
services[index],
style: TextStyle(
fontSize: 16.0,
height: 1.2,
color: Colors.white,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
),
],
),
color: Color(color),
),
),
);
},
),
),
),
),
);
}
You need to embed the GridView into a SingleChildScrollView widget. This widget handles the scrolling for its child, which is in your case the GridView. The same applies to ListView.
See the links for detailed documentation.
// ...
child: Container(
height: 500,
child: SingleChildScrollView(
child: GridView.builder(
// ...
)
)
)
// ...
EDIT
I forgot, that you have to give a GridView a height to work inside a SingleChildScrollView. You can use a Container that wraps the GridView.
// ...
child: Container(
height: 500,
child: SingleChildScrollView(
child: Container(
height: 500,
child: GridView.builder(
// ...
)
)
)
)
// ...
But with that approach you have to give your GridView a predefined height. An alternative is the CustomScrollView but you have to use a SliverGrid for that.
CustomScrollView(
slivers: [
SliverGrid(
// ...
)
]
)

How to change place of children widgets in Column?

I need to change the place of the widget in my UI. But I could not achieve it.
I tried this code But it does not work for me. If someone knows how to do it please help.
Change Place of BankCard Widget to Another BankCard Widget, or change the place of any widgets in a Column.
Below you can find code that I tried:
Widget nonNullBody(List<GetConversionCards> cards) {
_column=Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"fromSum".tr(),
style: TextStyle(
fontSize: 16, fontWeight: FontWeight.w700),
textAlign: TextAlign.left,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: BankCard(
card: Bank.CreditCardModel.fromUzCard(
cards[bloc.selectedIndex.value])),
),
IconButton(
icon: Icon(Icons.sync),
onPressed: () {
_key.currentState.setState(() {
Widget t=_column.children[0];
_column.children[0]=_column.children[3];
_column.children[3]=t;
});
},
),
Text("toVisa".tr(),
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w700),
textAlign: TextAlign.left),
Padding(
padding: const EdgeInsets.all(8.0),
child: BankCard(
card: Bank.CreditCardModel.fromVisaCard(
cards[bloc.selectedIndex.value])),
),
],);
bloc.tokenCardUzs = cards[0].uzsCardId;
final size = MediaQuery.of(context).size;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: SingleChildScrollView(
child: Container(
height: size.height - appBar().preferredSize.height + 5,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: 30,
child: ValueListenableBuilder(
valueListenable: bloc.selectedIndex,
builder: (context, v, w) {
return ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: cards.length,
itemBuilder: (context, index) {
return Container(
width: 8.0,
height: 8.0,
margin: EdgeInsets.symmetric(
vertical: 12.0, horizontal: 2.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: bloc.selectedIndex.value == index
? Color.fromRGBO(0, 0, 0, 0.9)
: Color.fromRGBO(0, 0, 0, 0.4)),
);
});
}),
),
Flexible(
fit: FlexFit.loose,
flex: 5,
child: PageView.builder(
scrollDirection: Axis.horizontal,
itemCount: cards.length,
onPageChanged: (_) {
bloc.tokenCardUzs = cards[_].uzsCardId;
bloc.selectedIndex.value = _;
},
itemBuilder: (BuildContext context, int index) {
return StatefulBuilder(
key: _key,
builder: (BuildContext context,
void Function(void Function()) state) {
return _column; );
}),
),
Flexible(
child: TextFieldWidget(
controller: bloc.amountFieldController,
iconData: Icons.monetization_on,
validator: null,
hintText: "enterAmount".tr(),
labelText: "dollarCurrency".tr(),
),
),
ConfirmButton(
text: 'next'.tr(),
onPressed: () {
showPopUp(context, () async {
Navigator.of(context, rootNavigator: true).pop();
waitTransactionWidget(context);
int usd =
(double.parse(bloc.amountFieldController.text) * 100)
.toInt();
bool result = await Repository.getInstance()
.convUzsUsd(bloc.tokenCardUzs, usd);
print("result conv $result");
Navigator.of(context, rootNavigator: true).pop();
Navigator.pushReplacement(
context,
PageTransition(
child: MyHomePage(),
type: PageTransitionType.fade));
},
title: Text("wouldYouLikeToExchange".tr()),
subtitle: Text("${bloc.amountFieldController.text} " +
"dollarCurrency".tr()));
},
),
],
),
),
),
);
}
I recommend you create a list that contains widgets then assign it to the childrens parameters of Column. So when you change something about the list it will change the column as well.
like this :
List<Widget> list = new List();
#override
Widget build(BuildContext context) {
Column(
children: list,
);
}
adjustWidgetList() {
setState(() {
list.add(Text("lorem ipsum"));
list.add(Text("dolar sit amet."));
.
.
.
list.remove(0);
});
}
But don't forget to make your changes inside of setState.

How to create multiple horizontal `GridView` in the same screen using flutter

Is there's a way to create a lists of GridViews as the below image in one screen...
I have a some Screen as the below one:
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
var _showOnlyFavorites = false;
AnimationController animationController;
bool multiple = true;
#override
void initState() {
animationController = AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
super.initState();
}
Future<bool> getData() async {
await Future<dynamic>.delayed(const Duration(milliseconds: 0));
return true;
}
#override
void dispose() {
animationController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppTheme.white,
body: FutureBuilder<bool>(
future: getData(),
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
if (!snapshot.hasData) {
return const SizedBox();
} else {
return Padding(
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
appBar(),
Expanded(
child: FutureBuilder<bool>(
future: getData(),
builder:
(BuildContext context, AsyncSnapshot<bool> snapshot) {
if (!snapshot.hasData) {
return const SizedBox();
} else {
return PropertiesGrid(_showOnlyFavorites);
}
},
),
),
],
),
);
}
},
),
);
}
Widget appBar() {
return SizedBox(
height: AppBar().preferredSize.height,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 8, left: 8),
child: Container(
width: AppBar().preferredSize.height - 8,
height: AppBar().preferredSize.height - 8,
),
),
Expanded(
child: Center(
child: Padding(
padding: const EdgeInsets.only(top: 4),
child:
Image.asset('assets/images/logo.png', fit: BoxFit.contain),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 8, right: 8),
child: Container(
width: AppBar().preferredSize.height - 8,
height: AppBar().preferredSize.height - 8,
color: Colors.white,
child: Material(
color: Colors.transparent,
child: InkWell(
borderRadius:
BorderRadius.circular(AppBar().preferredSize.height),
child: Icon(
multiple ? Icons.dashboard : Icons.view_agenda,
color: AppTheme.dark_grey,
),
onTap: () {
setState(() {
multiple = !multiple;
});
},
),
),
),
),
],
),
);
}
}
as I have a widget which have the GridView.builder as the below code:
import 'package:aradi_online_vtwo/providers/properties.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/properties.dart';
import './property_item.dart';
class PropertiesGrid extends StatelessWidget {
final bool showFavs;
PropertiesGrid(this.showFavs);
#override
Widget build(BuildContext context) {
final productsData = Provider.of<Properties>(context);
final products = showFavs ? productsData.favoriteItems : productsData.items;
return GridView.builder(
padding: const EdgeInsets.all(10.0),
itemCount: products.length,
itemBuilder: (ctx, i) => ChangeNotifierProvider.value(
// builder: (c) => products[i],
value: products[i],
child: PropertyItem(
// products[i].id,
// products[i].title,
// products[i].imageUrl,
),
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 1,
childAspectRatio: 3 / 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
), scrollDirection: Axis.horizontal,
);
}
}
I tried to set the height of the grid by wrapping it with a Container and set the height of it as to add more grids but it doesn't work.
and here's my Grid Item widget code:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/property.dart';
class PropertyItem extends StatelessWidget {
#override
Widget build(BuildContext context) {
final property = Provider.of<Property>(context, listen: false);
return InkWell(
onTap: () => {},
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
elevation: 7,
margin: EdgeInsets.all(2),
child: Stack(
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(15),
topRight: Radius.circular(15),
),
// color: Colors.transparent,
child: Image.asset(
property.image,
fit: BoxFit.fill,
),
),
Positioned(
top: 8,
right: 8,
child: Consumer<Property>(
builder: (ctx, property, _) => IconButton(
icon: Icon(
property.isFavorite ? Icons.favorite : Icons.favorite_border,
),
color: Colors.red,
onPressed: () {
property.toggleFavoriteStatus();
},
),
),
),
Positioned(
right: 20,
top: 100,
child: Container(
width: 300,
color: Colors.black54,
padding: EdgeInsets.symmetric(
vertical: 5,
horizontal: 20,
),
child: Text(
property.title,
style: TextStyle(
fontSize: 20,
color: Colors.white,
),
softWrap: true,
overflow: TextOverflow.fade,
),
),
)
],
),
),
);
}
}
You'll need a column where each ListView or GridView is wrapped inside a SizedBox (if you have a specific height) and you also can use Expanded to take whatever available space (like the last one in the given example):
You can post the code below in dartpad.dev and see how it works:
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyApp(),
));
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
SizedBox(
height: 100,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 10,
itemBuilder: (c, i) {
return Card(
child: Container(
height: 100,
width: 100,
child: Center(child: Text("$i")),
),
);
},
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Align(
child: Text("The Second List"),
alignment: Alignment.centerRight,
),
),
SizedBox(
height: 100,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 10,
itemBuilder: (c, i) {
return Card(
child: Container(
height: 100,
width: 100,
child: Center(child: Text("$i")),
),
);
},
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Align(
child: Text("The Third List"),
alignment: Alignment.centerRight,
),
),
Expanded(
//height: 200,
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 3 / 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
scrollDirection: Axis.vertical,
itemCount: 20,
itemBuilder: (c, i) {
return Card(
child: Container(
height: 100,
width: 100,
child: Center(child: Text("$i")),
),
);
},
),
),
],
),
);
}
}