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

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

Related

Can I add a CarouselSlider to a PageView.builder, no auto scroll

I have a Futurebuilder that works with a ListView.builder that displays on the screen but I wanted to add the carousel_slider package but nothing happens, the Carouselslider is set to auto scroll . I can still so it manually like a list view.
My Code:
There are just 2 elements from the Future on the screen, image and a title image.
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/material.dart';
import '../../future_carousel.dart';
class CarouselInformation extends StatelessWidget {
CarouselInformation({Key? key}) : super(key: key);
var datasource = const FutureInformation();
getSliderDetailsEvents() async {
List futureEvents = await datasource.getSliderDetails();
return futureEvents;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Sliders')),
body: SingleChildScrollView(
child: Column(
children: [
FutureBuilder(
future: getSliderDetailsEvents(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return const CircularProgressIndicator();
} else {
return Column(
children: [
const Text('Block 1'),
CarouselSlider(
options: CarouselOptions(
aspectRatio: 1.5,
viewportFraction: 1.0,
enlargeCenterPage: true,
enlargeStrategy: CenterPageEnlargeStrategy.height,
enableInfiniteScroll: false,
initialPage: 2,
autoPlay: true,
),
items: [
SizedBox(
height: 260,
width: 375,
child: Expanded(
child: PageView.builder(
scrollDirection: Axis.horizontal,
itemCount: snapshot.data.length,
itemBuilder:
(BuildContext context, int index) {
return Container(
margin: const EdgeInsets.all(5.0),
child: ClipRRect(
borderRadius: const BorderRadius.all(
Radius.circular(5.0)),
child: Stack(
children: [
Image.network(
snapshot.data[index].image,
fit: BoxFit.cover),
Positioned(
bottom: 0.0,
left: 0.0,
right: 0.0,
child: Container(
decoration:
const BoxDecoration(
gradient: LinearGradient(
colors: [
Color.fromARGB(
200, 0, 0, 0),
Color.fromARGB(
0, 0, 0, 0)
],
begin: Alignment
.bottomCenter,
end: Alignment.topCenter,
),
),
padding: const EdgeInsets
.symmetric(
vertical: 10.0,
horizontal: 20.0),
child: Text(
snapshot.data[index].title,
style: const TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight:
FontWeight.bold,
),
),
),
),
],
),
),
);
},
),
),
),
]),
],
);
}
}),
],
),
),
);
}
}
Result of the code above:
I want to achieve the same effect as the bottom Widget as on this clip but the images on that clip which is working are hardcoded not from a Future.
https://www.screencast.com/t/ouWL8AkSuI

How to add 3x3 row of buttons between my slider and floatingbutton

as the title says I want to add a 3x3 buttons grid, but I'm not able to do, I don't understand how to create all of this elements
(I'm thinking in a div way like in html)
Here is my code, at top is my carousel slider and at the bottom is the floatingbutton, I need my 3x3 to be below my carousel slider and top of my floating button
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/material.dart';
final List<String> imgList = [
'https://images.unsplash.com/photo-1520342868574-5fa3804e551c?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=6ff92caffcdd63681a35134a6770ed3b&auto=format&fit=crop&w=1951&q=80',
'https://images.unsplash.com/photo-1522205408450-add114ad53fe?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=368f45b0888aeb0b7b08e3a1084d3ede&auto=format&fit=crop&w=1950&q=80',
];
void main() => runApp(CarouselDemo());
final themeMode = ValueNotifier(2);
class CarouselDemo extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ValueListenableBuilder(
builder: (context, value, g) {
return MaterialApp(
initialRoute: '/',
darkTheme: ThemeData.dark(),
themeMode: ThemeMode.values.toList()[value as int],
debugShowCheckedModeBanner: false,
routes: {
'/': (ctx) => ComplicatedImageDemo(),
},
);
},
valueListenable: themeMode,
);
}
}
class DemoItem extends StatelessWidget {
final String title;
final String route;
DemoItem(this.title, this.route);
#override
Widget build(BuildContext context) {
return ListTile(
title: Text(title),
onTap: () {
Navigator.pushNamed(context, route);
},
);
}
}
final List<Widget> imageSliders = imgList
.map((item) => Container(
child: Container(
margin: EdgeInsets.all(5.0),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
child: Stack(
children: <Widget>[
Image.network(item, fit: BoxFit.cover, width: 1000.0),
Positioned(
bottom: 0.0,
left: 0.0,
right: 0.0,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color.fromARGB(200, 0, 0, 0),
Color.fromARGB(0, 0, 0, 0)
],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
),
),
padding: EdgeInsets.symmetric(
vertical: 10.0, horizontal: 20.0),
child: Text(
'No. ${imgList.indexOf(item)} image',
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
),
),
],
)),
),
))
.toList();
class ComplicatedImageDemo extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Sayapp 0.2')),
body: Container(
child: CarouselSlider(
options: CarouselOptions(
autoPlay: true,
aspectRatio: 2.0,
enlargeCenterPage: true,
),
items: imageSliders,
),
),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {},
label: Text('Alert'),
icon: Icon(Icons.add_alert_sharp),
backgroundColor: Colors.red,
),
);
}
}
body: Column(
children: [
Container(
child: CarouselSlider(
options: CarouselOptions(
autoPlay: true,
aspectRatio: 2.0,
enlargeCenterPage: true,
),
items: imageSliders,
),
),
Column(
children: [
Row(
children: [
Button1();
Button2();
Button3();
],
),
Row(
children: [
Button1();
Button2();
Button3();
],
),
Row(
children: [
Button1();
Button2();
Button3();
],
),
],
),
],
),
You can use GridView.builder() to do this
List<Widget> buttonList = [Button1(),Button2(),Button3(),Button4(),Button5(),Button6(),Button7(),Button8(),Button9()];
// inside body
body: Column(
children: [
CarouselSlider(
options: CarouselOptions(
autoPlay: true,
aspectRatio: 2.0,
enlargeCenterPage: true,
),
items: imageSliders,
),
GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, // number of widgets in a row
crossAxisSpacing: 10.0,
mainAxisSpacing: 10.0,
childAspectRatio: (1.0 / 1.2),
),
itemBuilder: (BuildContext context, int index) {
return buttonList[index];
},
itemCount: buttonList.length,
),
],)

How to Implement a manual carousel slider in Flutter?

I am creating a product image carousel which contains pictures of shoes where the user can change the image to be viewed by selecting a different color.
The user can manually scroll through the images without an issue,however when I try to manually change the displayed carousel image, only the indicator changes, but the image remains on the first image.
class DetailsPage extends StatefulWidget {
final String url;
final String title;
final int index;
DetailsPage({this.url, this.title, this.index});
#override
_DetailsPageState createState() => _DetailsPageState();
}
class _DetailsPageState extends State<DetailsPage> {
List imgList = [
'https://i.dlpng.com/static/png/6838599_preview.png',
'https://www.manelsanchez.pt/uploads/media/images/nike-air-force-max-ii-blue-fury-18.jpg',
'https://www.vippng.com/png/detail/30-302339_nike-women-running-shoes-png-image-transparent-background.png',
];
int _current = 0;
String selected = "grey";
List<T> map<T>(List list, Function handler) {
List<T> result = [];
for (var i = 0; i < list.length; i++) {
result.add(handler(i, list[i]));
}
return result;
}
final CarouselController _buttonCarouselController = CarouselController();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).canvasColor,
appBar: AppBar(
title: Center(
child: Text(
'Details',
style: TextStyle(
fontFamily: 'OpenSansLight',
fontSize: 26,
color: Theme.of(context).textTheme.headline1.color),
),
),
body: ListView(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
//Carousel Slider
CarouselSlider.builder(
options: CarouselOptions(
carouselController: _buttonCarouselController,
height: 200.0,
enlargeCenterPage: true,
enlargeStrategy: CenterPageEnlargeStrategy.height,
initialPage: 0,
reverse: false,
autoPlay: false,
enableInfiniteScroll: false,
scrollDirection: Axis.horizontal,
onPageChanged: (index, fn) {
setState(() {
_current = index;
});
}),
itemCount: imgList.length,
itemBuilder: (BuildContext context, int index) =>
Builder(builder: (BuildContext context) {
return Image.network(
imgList[index],
fit: BoxFit.contain,
);
}),
),
SizedBox(height: 10),
//Indicator to show current index of images
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: map<Widget>(imgList, (index, url) {
return Container(
width: 30.0,
height: 2.0,
margin: EdgeInsets.symmetric(
vertical: 10.0, horizontal: 4.0),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(10.0),
color: _current == index
? Colors.deepPurple
: Colors.grey,
),
);
}),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 30,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Color',
style: TextStyle(
fontFamily: 'OpenSansLight',
fontSize: 24)),
],
),
),
),
Flexible(
fit: FlexFit.loose,
child: Container(
width: width,
height: 120,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: imgList.length,
itemBuilder: (BuildContext context, int index) {
//Color selector from images to manually control the carousel
return GestureDetector(
onTap: () {
setState(() {
selected = imgList[index];
_current = index;
_buttonCarouselController
.animateToPage(_current);
print('I HAVE SELECTED $selected');
});
},
child: ColorTicker(
image: imgList[index],
selected: selected == imgList[index],
),
);
},
),
),
),
],
),
);
Color Ticker Widget
class ColorTicker extends StatelessWidget {
final image;
final bool selected;
ColorTicker({this.image, this.selected});
#override
Widget build(BuildContext context) {
print(selected);
return Container(
margin: EdgeInsets.all(5),
width: 100,
height: 100,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.scaleDown, image: NetworkImage(image)),
shape: BoxShape.circle,
border: selected
? Border.all(color: Colors.deepPurple, width: 3)
: Border.all(color: Colors.grey[500])),
// color: color.withOpacity(0.7)),
child: selected
? Center(child: Icon(Icons.check, size: 40, color: Colors.deepPurple))
: Container(),
);
}
}
I've tried all I could from the documentation : https://pub.dev/packages/carousel_slider/example
But I kept getting an error
Unhandled Exception: NoSuchMethodError: The getter 'options' was called on null
I am almost embarassed at my mistake.
In the configuration of the slider, I placed the controller in the wrong place.
I put the controller inside the Carousel options instead of under CarouselSlider
CarouselSlider(
carouselController: _buttonCarouselController,
options: CarouselOptions(
... ))
It now works :)

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

Flutter NeverScrollableScrollPhysics pagenation not work

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!