Flutter - Widgets not scrolling in NestedScrollView - flutter

I am trying to make a page that contains a SliverAppBar, some Widgets with texts, and a List.
I used a NestedScrollView that contains the Sliver header, and a Column, that itself contains the widgets with texts and the list.
Here is the build function :
#override Widget build(BuildContext context) {
var _bar = widget.bar ;
_screenWidth = MediaQuery.of(context).size.width ;
return Scaffold(
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
expandedHeight: 200.0,
floating: false,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
centerTitle: true,
title: Text(_bar.name,
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
)),
background: Image.network(
"https://s1.qwant.com/thumbr/0x380/1/2/2a39f1f558f2cbbec11a08e43493bde861d612add6be643dbc5ad6fe0b16fc/BDBE5B56-B1B4-586D-27C8A70A4A54E50A.jpg?u=https%3A%2F%2Fimages.bwwstatic.com%2Fcolumnpic6%2FBDBE5B56-B1B4-586D-27C8A70A4A54E50A.jpg&q=0&b=1&p=0&a=1",
fit: BoxFit.cover,
)),
),
];
},
body: _offer(_bar),
),
);
}
The _offer function is the main issue, here is it :
Widget _offer(Bar bar) {
return Column(
children: <Widget>[
Row(
children: <Widget>[
Container(
width: _screenWidth / 4,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
fit: BoxFit.fill,
image: Image.network("https://s1.qwant.com/thumbr/0x380/3/9/60c4de7be57ee1b7d24d07dde941c3027588bc313699cba9ef9ef8fb6c7fda/1280px-Hard_Rock_Cafe_Logo.svg.png?u=https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2Fthumb%2F2%2F2c%2FHard_Rock_Cafe_Logo.svg%2F1280px-Hard_Rock_Cafe_Logo.svg.png&q=0&b=1&p=0&a=1").image
)
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
bar.name.toUpperCase(),
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
Text(
"Bar category" + " - " + "Bar address",
style: TextStyle(
fontWeight: FontWeight.bold
),
),
Text(
"Opening hours" + " - " + "01.12.12.12.12",
style: TextStyle(
fontWeight: FontWeight.bold
),
),
Text(
"Happy Hour de 20h a 23h",
style: TextStyle(
color: Colors.deepOrange,
fontWeight: FontWeight.bold,
),
)
],
),
],
),
Image.asset("assets/favorites.png"),
Padding(padding: EdgeInsets.all(20),),
Center(
child: Text(
"Menu".toUpperCase(),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25
),
),
),
Padding(padding: EdgeInsets.all(20)),
Flexible(
fit: FlexFit.loose,
child: CustomScrollView(
slivers: <Widget>[
SliverList(
delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
return productItem(context, _productsList[index]);
},
childCount: _productsList.length,
),
),
],
),
)
],
);
}
Here is the result :
Link to the gif : https://ibb.co/x8j6vvm
(if someone know how to integrate gif in a question, feel free to edit it !)
I want the data from second "TestName1" to the heart image to completely scroll with the rest of the page. How can I achieve this ?

Using a CustomScrollView removes the problem of adding a NestedScrollView. You can add the SilverAppBar to the CustomScrollView to implement this.
CustomScrollView(
slivers: <Widget>[
SliverAppBar(
expandedHeight: 200.0,
floating: false,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
centerTitle: true,
title: Text(_bar.name,
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
)),
background: Image.network(
"https://s1.qwant.com/thumbr/0x380/1/2/2a39f1f558f2cbbec11a08e43493bde861d612add6be643dbc5ad6fe0b16fc/BDBE5B56-B1B4-586D-27C8A70A4A54E50A.jpg?u=https%3A%2F%2Fimages.bwwstatic.com%2Fcolumnpic6%2FBDBE5B56-B1B4-586D-27C8A70A4A54E50A.jpg&q=0&b=1&p=0&a=1",
fit: BoxFit.cover,
)),
),
SliverFixedExtentList(
itemExtent: 150.0,
delegate: SliverChildListDelegate(
[
// Your Can Add you body items here.
],
),
),
],
),
Hope this helps.

Related

A widget in my SliverAppBar is causing a bottom overflow, how do i correct this in flutter?

I use a SliverAppBar and use flexibleSpace title instead of the default sliver title, on portrait mode, it is perfectly fine as shown :
But when i get to landscape mode it causes a bottom overflow by 13px, VScode tells me the renderflex is caused by a column.
This is how it looks like in landscape :
It is so messy that when i discovered this bug i couldn't continue coding until i fix this and this is what i've been trying to do :(
I will give my SliverAppBar code and also the widget used in the sliverapp flexibleSpace title as snippet below
I have tried using Expanded instead of Flexible, but it causes even more errors.
I also tried using some screen utility packages in pub.dev but seem like i don't use it properly.
Main view with sliverapp :
class HomeView extends GetView<HomeController> {
#override
Widget build(BuildContext context) {
controller.initScrollController();
return WillPopScope(
onWillPop: Helper().onWillPop,
child: Scaffold(
body: RefreshIndicator(
onRefresh: () async {
Get.find<LaravelApiClient>().forceRefresh();
controller.refreshHome(showMessage: true);
Get.find<LaravelApiClient>().unForceRefresh();
},
child: CustomScrollView(
physics: const AlwaysScrollableScrollPhysics(),
controller: controller.scrollController,
shrinkWrap: false,
slivers: <Widget>[
SliverAppBar(
backgroundColor: Color(0xffFFFFFF),
expandedHeight: MediaQuery.of(context).size.height * 0.18,
elevation: 0.5,
floating: false,
iconTheme: IconThemeData(color: Get.theme.primaryColor),
actions: [NotificationsButtonWidget()],
flexibleSpace: FlexibleSpaceBar(
collapseMode: CollapseMode.parallax,
title: MainProfileDetails(),//i suspect this is the widget causing the bug
),
),
SliverToBoxAdapter(
child: Wrap(
children: [
JobSummaryView(),
//BookingsListWidget(),
],
),
),
],
)),
),
);
}
}
MainProfileDetails() code:
class MainProfileDetails extends StatelessWidget {
const MainProfileDetails({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Obx(() {
return Padding(
padding: const EdgeInsets.only(left: 5.0),
child: Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Stack(
children: [
GestureDetector(
onTap: () {
Get.toNamed(Routes.PROFILE);
},
child: Container(
child: Stack(
children: [
SizedBox(
width: 60,
height: 60,
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(80)),
child: CachedNetworkImage(
height: 100,
width: double.infinity,
fit: BoxFit.cover,
imageUrl: Get.find<AuthService>()
.user
.value
.avatar
.thumb,
placeholder: (context, url) => Image.asset(
'assets/img/loading.gif',
fit: BoxFit.cover,
width: double.infinity,
height: 80,
),
errorWidget: (context, url, error) =>
Icon(Icons.error_outline),
),
),
),
Positioned(
top: 35,
left: 30,
right: 0,
child: Get.find<AuthService>()
.user
.value
.verifiedPhone ??
false
? Icon(Icons.check_circle,
color: Color(0xffB0BEC1), size: 24)
: Icon(Icons.error_outline),
)
],
),
),
),
],
),
SizedBox(
width: 10,
),
Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flexible(
flex: 2,
child: Padding(
padding: const EdgeInsets.only(left: 1.0),
child: Text(
'Hello, ${Get.find<AuthService>().user.value.name}',
style: GoogleFonts.poppins(
color: Color(0xff34495E), fontSize: 9),
),
),
),
Flexible(
flex: 2,
child: Padding(
padding: const EdgeInsets.only(top: 1.0, bottom: 1.0),
child: Text(
'Good Stitching',
style: GoogleFonts.poppins(
fontSize: MediaQuery.of(context).size.width * 0.04,
color: Color(0xff000000),
fontWeight: FontWeight.w600),
),
),
),
Flexible(
child: Container(
decoration: BoxDecoration(
color: Color(0xffeeeeee),
borderRadius: BorderRadius.circular(15),
),
child: Padding(
padding: const EdgeInsets.only(
top: 3.0, bottom: 3.0, left: 10.0, right: 10.0),
child: Get.find<AuthService>().user.value.verifiedPhone ??
false
? Text(
'Verified',
style: GoogleFonts.poppins(
fontSize:
MediaQuery.of(context).size.width * 0.025,
fontStyle: FontStyle.italic),
)
: Text(
'Unverified',
style: GoogleFonts.poppins(
fontSize:
MediaQuery.of(context).size.width * 0.025,
fontStyle: FontStyle.italic),
),
),
)),
],
),
//NotificationsButtonWidget(),
],
),
);
});
}
}
Please i need your time and assistance on this one. Thank you!
After many hours of asking for help here, i decided to go with simple AppBar in flutter as SliverAppBar flexibleSpace title is only customisable to a limit.
And that was goodbye to orientation issues.
Thanks everyone for your support.

Nested Scrollview can't scroll until the bottom (constrained)

I'm new to flutter development and I'm trying to create a contact book page that will load recent contact and all of my contact list, I managed to get the data and build it into the widget.
The problem is when there are a lot of contact (let say 20 contacts). If the screen size is small it can only scroll until 7-8 contacts, but I know there's more to it. But I guess my nestedScrollView won't let me to scroll down anymore.. Like it's constrained by something
what's the problem and how to fix this ? Here's my code:
/// BODY
body: WillPopScope(
onWillPop: () {
print('hello');
},
child: ListView(
physics: BouncingScrollPhysics(),
shrinkWrap: true,
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 20),
height: MediaQuery.of(context).size.height,
child: NestedScrollView(
controller: _scrollController,
headerSliverBuilder: (context, isScrolled) {
return [
SliverPersistentHeader(
pinned: true,
floating: false,
delegate: ChooseUsersHeaderDelegate(
widgetList: Container(
color: Colors.white,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
/// Build Search Box Function
buildSearch(),
],
),
),
minHeight: selectedContactId.isNotEmpty ? 135 : 60,
maxHeight: selectedContactId.isNotEmpty ? 135 : 60,
parentContext: context,
),
),
];
},
body: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
/// Recent Contacts Subtitle
Text(
'recent',
style: GoogleFonts.montserrat(
fontSize: 14,
fontWeight: FontWeight.w500,
color: primaryColor,
fontStyle: FontStyle.normal,
),
).tr(),
/// Recent Contacts
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
isLoading
? ReusableLoadingContact()
: NotificationListener<
OverscrollIndicatorNotification>(
onNotification: (overScroll) {
overScroll.disallowIndicator();
return true;
},
child: buildWidget(context, 'recent')),
],
),
SizedBox(height: 15),
/// All Contacts Subtitle
Text(
'allContacts',
style: GoogleFonts.montserrat(
fontSize: 14,
fontWeight: FontWeight.w500,
color: primaryColor,
fontStyle: FontStyle.normal,
),
).tr(),
/// All Contacts
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
isLoading
? ReusableLoadingContact()
: NotificationListener<
OverscrollIndicatorNotification>(
onNotification: (overScroll) {
overScroll.disallowIndicator();
return true;
},
child: buildWidget(context, 'contacts')),
],
),
],
),
),
),
)
],
),
),

Extra "Space" In ListView and Card Flutter

I'm having this "extra space" on my first listview item that is a card being encapsulated in a container.
How do I remove it?
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(15.0),
height: 300,
child: Column(children: [
Row(children: [
Expanded(
child: Text("Lowest Fuel Price",
style: TextStyle(
fontWeight: FontWeight.w500,
color: Theme.orange3,
fontSize: 16.0)))
]),
Container(
height: 250,
child: Card(
elevation: 3,
child: ListView.builder(
itemCount: cheapest.length,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
final item = cheapest[index];
return Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Text(
item.petrolType,
style: TextStyle(
color: Theme.gray1, fontSize: 18),
),
Text(
"\$" + item.petrolPrice,
style: TextStyle(
color: Theme.gray1, fontSize: 25),
),
Image(
fit: BoxFit.fill,
image: new AssetImage(
'assets/images/fuel_station/' +
item.petrolStation.toLowerCase() +
'.png')),
]),
index != cheapest.length - 1
? Divider(
color: Colors.grey,
)
: Divider(color: Colors.white)
],
);
})),
)
]));
}
https://api.flutter.dev/flutter/widgets/ListView-class.html
By default, ListView will automatically pad the list's scrollable extremities to avoid partial obstructions indicated by MediaQuery's padding. To avoid this behaviour, override with a zero-padding property.
Card(
elevation: 3,
child: MediaQuery.removePadding(
context: context,
removeTop: true,
child: ListView.builder(),
),
),

Flutter: How to enlarge an Image when scrolling to the top of a page in an app?

I have a page with an Image on the top and some other widget underneath it. The entire page is scrollable.
Does anyone know how to enlarge the image when scrolling to the top to create an effect similar to the one in Apple Music?
Here you find an example of what I'm trying to create:
https://i.stack.imgur.com/MiYLZ.gif
try to use Sliver
final bannerHigh = 150.0;
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
backgroundColor: Color(0xFF0084C9),
leading: IconButton(
icon: Icon(
Icons.blur_on,
color: Colors.white70,
),
onPressed: () {
Scaffold.of(context).openDrawer();
},
),
expandedHeight: bannerHigh,
floating: true,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
title: Text("Your title",
style: TextStyle(
fontSize: 18,
color: Colors.white,
fontWeight: FontWeight.w600)),
background: Image.network(
'image url',
fit: BoxFit.cover,
),
),
),
SliverList(
delegate: SliverChildListDelegate(
<Widget>[
],
),
),
],
),
);

Set background image height, width, position in Flutter

I have a background image in my SliverAppBar. I've tried the BoxFit.contain, BoxFit.fill...etc, but none of them work for what I'd like to do.
Here is what I can get:
But here's what I want:
I see there is BoxFit.values but I cannot find any documentation showing how to use this (if it's the right thing?)
Here's my code:
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:my_app/Theme.dart' as MyTheme;
import 'package:my_app/ui/rule_section_details/RuleRow.dart';
#override
class SliverHeaderTest extends StatelessWidget {
final DocumentSnapshot ruleGroup;
SliverHeaderTest(this.ruleGroup);
#override
Widget build(BuildContext context) {
return Material(
child: CustomScrollView(slivers: <Widget>[
SliverAppBar(
floating: true,
backgroundColor: Color(int.parse(ruleGroup['color'])),
expandedHeight: 200.0,
flexibleSpace: FlexibleSpaceBar(
// background: Image.asset('assets/img/circular-image.png',
// fit: BoxFit.contain),
background: new Image(
image: new AssetImage(ruleGroup['image']),
height: MyTheme.Dimens.ruleGroupListIconHeight,
width: MyTheme.Dimens.ruleGroupListIconWidth,
),
title: Text(ruleGroup['name'],
style: MyTheme.TextStyles.ruleSectionPageTitle),
centerTitle: true,
),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.share),
tooltip: 'Share',
onPressed: () {/* ... */},
),
],
),
StreamBuilder(
stream: Firestore.instance
.collection('rules')
.where("section", isEqualTo: ruleGroup['id'])
.orderBy("subsection")
.orderBy("subsubsection")
.orderBy("subsubsubsection")
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SliverList(
delegate: SliverChildListDelegate(
[
Container(
child: new Center(child: new Text('Loading...')),
)
],
),
);
}
return SliverPadding(
padding: EdgeInsets.only(top: 16.0),
sliver: SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return new RuleRow(snapshot.data.documents[index]);
}, childCount: snapshot.data.documents.length)));
})
]),
);
}
}
It is the Desired behavior of background: property of FlexibleSpaceBar - its Suppose to fill all the background area of the Appbar, now title here is not separate element to render below background, but a foreground widget of the FlexibleSpaceBar to show on top of background:
If You really need to separate the title & Image here you can't use background & title property, but Instead you need to use Column or ListView instead of FlexibleSpaceBar.
You can try the Following Code with Possible options:
Recommended Solution:
SliverAppBar(
backgroundColor: Colors.blue,
expandedHeight: 200.0,
floating: true,
// pinned: true,
flexibleSpace: FlexibleSpaceBar(
centerTitle: true,
title: Text("Collapsing Toolbar",
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
)),
background: Row(
children: <Widget>[
Spacer(),
CircleAvatar(
radius: 54.0,
backgroundImage: NetworkImage(
"https://placeimg.com/640/480/animals",
),
),
Spacer(),
],
)),
),
This Image is with radius: 68.0,.
Following are using fixed Margins, might cause issue in responsive design, but still works.
With ClipOval:
SliverAppBar(
backgroundColor: Colors.blue,
expandedHeight: 200.0,
floating: true,
// pinned: true,
flexibleSpace: FlexibleSpaceBar(
centerTitle: true,
title: Text("Collapsing Toolbar",
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
)),
background: Container(
margin:
EdgeInsets.symmetric(horizontal: 125.0, vertical: 50.0),
child: ClipOval(
child: Image.network(
"https://placeimg.com/640/480/animals",
),
),
)),
),
with CircleAvatar
SliverAppBar(
backgroundColor: Colors.blue,
expandedHeight: 200.0,
floating: true,
// pinned: true,
flexibleSpace: FlexibleSpaceBar(
centerTitle: true,
title: Text("Collapsing Toolbar",
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
)),
background: Container(
margin:
EdgeInsets.symmetric(horizontal: 125.0, vertical: 50.0),
child: CircleAvatar(
radius: 30.0,
backgroundImage: NetworkImage(
"https://placeimg.com/640/480/animals",
),
),
)),
),
Update:
with ListView Option.
Note: AppBar height is Determined by expandedHeight: property & will not increase in case of increase in Image Radius.
SliverAppBar(
backgroundColor: Colors.blue,
expandedHeight: 200.0,
floating: true,
// pinned: true,
flexibleSpace: Center(
child: ListView(
shrinkWrap: true,
children: <Widget>[
Row(
children: <Widget>[
Spacer(),
CircleAvatar(
radius: 68.0,
backgroundImage: NetworkImage(
"https://placeimg.com/640/480/animals",
),
),
Spacer(),
],
),
Center(
child: Text("Collapsing Toolbar",
style: TextStyle(
color: Colors.white,
fontSize: 22.0,
)),
),
],
),
),
),