Shrink SliverAppBar Image animation Like Title Text in Flutter - flutter

I am trying to replicate the text shrink effect that comes naturally with a SliverAppBar with an image such that the background image of the sliverhead shrinks to a leading icon in the appbar of the sliverAppBar.
I have tried using the AnimatedPostioned flutter widget along with a scroll controller that toggles the state of the isSkrink boolean when the page is scrolled.
Below is AnimatedPosition widget:
AnimatedPositioned(
width: isShrink ? 10.0 : 200.0,
height: isShrink ? 10.0 : 200.0,
duration: Duration(seconds: 2),
curve: Curves.linear,
child: Stack(
children: [
Container(
child: Image.asset(
'assets/images/user-avatar.png'),
),
],
),
),
Below is the SliverAppBar with the AnimatedPositioned in the stack and the user icon in the leading param of the SliverAppBar
SliverAppBar(
leading: isShrink
? Padding(
padding: EdgeInsets.all(10),
child: CircleAvatar(
backgroundImage:
AssetImage('assets/images/user-avatar.png'),
backgroundColor: Colors.white,
radius: 3,
),
)
: Container(),
floating: true,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
title: Row(
children: <Widget>[
Text(
"Username",
style: bodyText1Style(
context,
color: isShrink ? Colors.black : Colors.white,
fontSize: isShrink ? 18 : 15,
fontWeight: FontWeight.w600,
),
),
],
),
background: Stack(
children: <Widget>[
AnimatedPositioned(
width: isShrink ? 10.0 : 200.0,
height: isShrink ? 10.0 : 200.0,
duration: Duration(seconds: 2),
curve: Curves.linear,
child: Stack(
children: [
Container(
child: Image.asset(
'assets/images/user-avatar.png'),
),
],
),
),
],
),
),
expandedHeight: size.height * 0.35,
);
This is the result of the code above:

After a long research I was able to come with this using https://stackoverflow.com/a/59323713/3636615 as reference:
Scaffold(
body: CustomScrollView(
slivers: <Widget>[
TransitionAppBar(
// extent: 250,
extent: 300,
avatar: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
'assets/images/user-avatar.png'), // NetworkImage(user.imageUrl),
fit: BoxFit.cover)),
),
title: "Emmanuel Olu-Flourish",
),
SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return Container(
child: ListTile(
title: Text("${index}a"),
));
}, childCount: 25))
],
),
);
Check out the TransitionAppBar implementation here:
https://gist.github.com/Oluflourish/2f0789bd2e8ee576a2d6364d709c1c14
Below is demo of the result:

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.

not overlap SliverToBoxAdapter with a transparent SliverAppBar

Is it possible for a SliverToBoxAdapter to not be overlaped with a transparentSliverAppBar when scrolled upon?
Or give up on using SliverAppBar and just use AppBar instead?
Widget build(BuildContext context) {
return SafeArea(
child: Stack(
children: [
Image(
image: bkgImage,
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
fit: BoxFit.cover,
alignment: Alignment.centerLeft,
),
Scaffold(
backgroundColor: Colors.transparent,
body: CustomScrollView(
slivers: [
SliverAppBar(
actions: <Widget>[
IconButton(
icon: const Icon(Icons.search),
onPressed: () {},
),
],
pinned: _pinned,
snap: _snap,
floating: _floating,
expandedHeight: 160,
backgroundColor: Colors.transparent,
elevation: 0.0,
flexibleSpace: FlexibleSpaceBar(
expandedTitleScale: 1.6,
titlePadding: EdgeInsets.all(18),
title: Text('Panahon'),
),
),
SliverList(
delegate: SliverChildListDelegate([
SizedBox(
height: 200,
child: Card(),
),
SizedBox(
height: 200,
child: Card(),
),
SizedBox(
height: 200,
child: Card(),
),
SizedBox(
height: 200,
child: Card(),
),
SizedBox(
height: 200,
child: Card(),
),
]),
)
],
),
),
],
),
);
}
The goal is this:
Precious view:
To get actual effect, we can use SliverPersistentHeaderDelegate. Concept is we need to pass image itself [both image must be screen size].
class MySliverHeaderDelegate extends SliverPersistentHeaderDelegate {
final double _maxExtent = 160;
final VoidCallback onActionTap;
final Image imageWidget;
MySliverHeaderDelegate({
required this.onActionTap,
required this.imageWidget,
});
#override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
debugPrint(shrinkOffset.toString());
return Stack(
children: [
Positioned(
top: 0,
left: 0,
right: 0,
child: imageWidget,
),
Align(
alignment: Alignment.bottomLeft,
child: Padding(
padding: const EdgeInsets.all(16),
child: Text(
'Panahon',
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: Colors.white,
),
),
),
),
// here provide actions
Positioned(
top: 0,
right: 0,
child: IconButton(
icon: const Icon(
Icons.search,
color: Colors.white,
),
onPressed: onActionTap,
),
),
],
);
}
#override
double get maxExtent => _maxExtent;
#override
double get minExtent => kToolbarHeight;
#override
bool shouldRebuild(covariant MySliverHeaderDelegate oldDelegate) {
return oldDelegate != this;
}
}
And use
Widget build(BuildContext context) {
final imageWidget = Image.asset(
"assets/images/image01.png",
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
fit: BoxFit.cover,
alignment: Alignment.centerLeft,
);
return SafeArea(
child: Stack(
children: [
imageWidget,
Scaffold(
backgroundColor: Colors.transparent,
body: CustomScrollView(
slivers: [
SliverPersistentHeader(
pinned: true,
delegate: MySliverHeaderDelegate(
imageWidget: imageWidget,
onActionTap: () {
debugPrint("on Tap");
}),
),
//.....
],
),
),
],
),
);
}
Others way to handle this situation
Being SliverAppBar's backgroundColor:Colors.transparent you are able to see though appbar.
If you provide your preferable color, that will fix the issue in this case, but you will not get background effect on appBar.
SliverAppBar(
backgroundColor: Colors.green, // the one you like
For your case, you can use CupertinoSliverNavigationBar instead of using SliverAppBar. It will still block the background on scroll and it won't get that much height.
CupertinoSliverNavigationBar(
backgroundColor: Colors.transparent,
largeTitle: const Align(
alignment: Alignment.bottomLeft,
child: SizedBox(
child: Text('Panahon'),
),
),
trailing: IconButton(
icon: const Icon(Icons.search),
onPressed: () {},
),
),

Flutter SliverList freezes while its loading images

I have a flutter app. One of my screens is loading lots of images from assets. Sometimes my app is freezing while the images are loading.
Here is my solution: I will put a loading animation, this animation needs to end up after the images are finished rendering but how do I understand all the images are finished rendering?
If you have any other solutions you can share with me :)
here is the Widget tree that loads images, in case if you need to know.
final posts = [
Post(
ownerName: "McQueen95",
avatarPath: "images/mcqueen.jpg",
imagePaths: ['images/mcqueen.jpg'],
),
Post(
ownerName: "BugsBunny",
imagePaths: ['images/Bugs_Bunny.png'],
),
Post(
ownerName: "Venom",
imagePaths: ['images/venom.jpg'],
),
Post(
ownerName: "Po",
imagePaths: ["images/kungfu_panda.jpg"],
avatarPath: "images/po.jpg",
),
Post(
ownerName: "Po",
imagePaths: ["images/kai.jpg", "images/oogway.jpg", "images/crane.png"],
avatarPath: "images/po.jpg",
),
];
#override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: [
SliverAppBar(
title: Text("Cossy", style: TextStyle(color: Colors.purple)),
// elevation: 0,
pinned: true,
// expandedHeight: 150.0,
backgroundColor: backgroundColor,
systemOverlayStyle: SystemUiOverlayStyle(
systemNavigationBarColor: backgroundColor,
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => Padding(
child: posts[index],
padding: EdgeInsets.only(
bottom: (index == posts.length - 1) ? 82 : 12,
),
),
childCount: posts.length,
),
)
],
);
}
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_image_slider/carousel.dart';
class Post extends StatelessWidget {
Post({
Key? key,
this.avatarPath,
required this.ownerName,
required this.imagePaths,
}) : super(key: key);
final String? avatarPath;
final String ownerName;
final List<String> imagePaths;
#override
Widget build(BuildContext context) {
if (imagePaths.length == 0) return Text("no image?");
return Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Color(0xFFF2F2F2),
offset: Offset(0.0, 1.0), //(x,y)
blurRadius: 6.0,
),
],
// color: Color(0xFFF2F2F2),
color: Colors.deepOrange,
borderRadius: BorderRadius.all(Radius.circular(10)),
),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(4.0),
child: Row(
children: [
CircleAvatar(
child: avatarPath == null ? Icon(Icons.person) : null,
backgroundImage:
avatarPath == null ? null : AssetImage(avatarPath ?? ""),
),
SizedBox(width: 10),
Text(ownerName),
Expanded(
child: SizedBox(height: 30),
),
Icon(Icons.settings),
],
),
),
Carousel(
indicatorBarColor: Colors.transparent,
autoScrollDuration: Duration(seconds: 2),
animationPageDuration: Duration(milliseconds: 500),
activateIndicatorColor: Colors.grey.shade200,
animationPageCurve: Curves.bounceInOut,
indicatorBarHeight: 30,
indicatorHeight: 10,
indicatorWidth: 20,
unActivatedIndicatorColor: Colors.grey.shade700,
stopAtEnd: true,
autoScroll: false,
// widgets
items: imagePaths
.map(
(imagePath) => Container(
decoration: BoxDecoration(color: Colors.black),
child: ConstrainedBox(
constraints: new BoxConstraints(
minHeight: 100,
minWidth: 100,
// maxHeight: 500,
maxHeight: MediaQuery.of(context).size.height * 3 / 2,
maxWidth: MediaQuery.of(context).size.width,
),
child: FittedBox(
fit: BoxFit.scaleDown,
alignment: Alignment.center,
child: Image(
image: AssetImage("$imagePath"),
),
),
),
),
)
.toList(),
),
Padding(
padding: const EdgeInsets.only(
left: 16,
right: 16,
top: 4,
),
child: Row(
children: [
TextButton(
onPressed: () {
print(123);
},
child: Icon(
Icons.star_border_outlined,
size: 30,
// color: Colors.grey,
),
),
Expanded(
child: SizedBox(
height: 30,
),
),
Icon(
Icons.send_outlined,
size: 30,
// color: Colors.grey,
),
],
),
),
],
),
);
}
}
I solved the bug by giving certain height and width values to the Widget that contains images. Using ConstrainedBox and FittedBox means it will load images first and then measure all items' height and widths and then give height value to ListView. So, that's why the app freezes, measuring ListView's size takes a lot of time.
I changed this:
Container(
decoration: BoxDecoration(color: Colors.black),
child: ConstrainedBox(
constraints: new BoxConstraints(
minHeight: 100,
minWidth: 100,
maxHeight: MediaQuery.of(context).size.height * 3 / 2,
maxWidth: MediaQuery.of(context).size.width,
),
child: FittedBox(
fit: BoxFit.scaleDown,
alignment: Alignment.center,
child: Image(
image: AssetImage("$imagePath"),
),
),
),
),
To this:
AspectRatio(
aspectRatio: 1 / 1,
child: Container(
decoration: BoxDecoration(color: Colors.black),
width: MediaQuery.of(context).size.width,
alignment: Alignment.center,
child: ClipRRect(
// borderRadius: BorderRadius.circular(10),
child: Image(
image: AssetImage("${imagePaths[0]}"),
),
),
),
),

SliverAppBar without fading in the AppBar

I really love using Slivers, but really have a Problem with SliverAppBar:
usually, I use the SliverAppBar Widget for creating a AppBar that has a Background Image with the Parallax effect. So all I use is the flexible space, which unfortunately gets blocked by the AppBar Portion whenever you scroll down.
I tried making the AppBar portion transparent by setting the color value to transparent, but all it does is make the whole thing, including the flexiblespace, transparent..
Is there a way to use only the flexiblespace of a SliverAppBar without fading in the AppBar portion when scrolling down?
here is the code I use:
SliverAppBar(
expandedHeight: 220,
pinned: false,
forceElevated: true,
backgroundColor: Colors.transparent,
stretch: true,
leading: Container(),
flexibleSpace: FlexibleSpaceBar(
collapseMode: CollapseMode.pin,
background:Stack(
children: <Widget>[
Image(
fit: BoxFit.cover,
width: MediaQuery.of(context).size.width,
image: AssetImage('assets/images/image2.png'),
),
Positioned(
bottom: 0,
child: Container(
height: 110,
width: MediaQuery.of(context).size.width,
color: Colors.grey,
),
),
Positioned(
bottom: 10,
left: 10,
child: CircleAvatar(
radius: 45,
backgroundImage: AssetImage('assets/images/image.png'),
),
),
Positioned(
bottom: 77,
left: 110,
child: Container(
width: MediaQuery.of(context).size.width -110 -60,
child: Text(
'Name...',
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(
fontSize: 20,
color: Colors.white
),
),
),
),
Positioned(
bottom: 63,
left: 110,
child: Container(
width: MediaQuery.of(context).size.width -110 -60,
child: Text(
'description...',
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(
fontSize: 14,
color: Colors.white70
),
),
),
),
Positioned(
bottom: 5,
left: 110,
child: Container(
width: MediaQuery.of(context).size.width-110,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
],
),
),
),
],
),
),
),
Hope these Images help explain my problem:
The flexiblespace looks as follows:Image 1
but once you scroll down, the flexible space fades away as seen in this picture:Image 2
I don't want to flexiblespace to fade away.
You've propably found the answer allready but I thought if someone like me encounter your question this might be a the answer you are looking for.
FlexibleSpaceBar include fade out animation and only way to exclude it is to write your own LayoutBuilder that will handle the collapse.
Here is a code example how you can create the custom flexibleSpace Widget with LayoutBuilder.
NestedScrollView(
headerSliverBuilder: (context, innerBoxIsScrolled) {
return [
SliverAppBar(
titleSpacing: 0,
pinned: false,
backgroundColor: Colors.transparent,
automaticallyImplyLeading: false,
elevation: 0.0,
actions: [
IconButton(
splashRadius: 20,
icon: Icon(
FontAwesomeIcons.cog,
color: Colors.grey[200],
),
onPressed: () {
},
),
],
toolbarHeight: kToolbarHeight,
expandedHeight: maxExtent,
flexibleSpace: LayoutBuilder(
builder: (context, constraints) {
double currentExtent = constraints.maxHeight;
final double deltaExtent = maxExtent - minExtent;
// 0.0 -> Expanded
// 1.0 -> Collapsed to toolbar
final double t =
(1.0 - (currentExtent - minExtent) / deltaExtent)
.clamp(0.0, 1.0) as double;
return Stack(
fit: StackFit.loose,
overflow: Overflow.clip,
children: [
Positioned(
top: _getCollapsePadding(t),
left: 0.0,
right: 0.0,
height: maxExtent,
child: Wrap(
crossAxisAlignment: WrapCrossAlignment.start,
children: [
//Insert Widgets add to your flexible space
],
),
),
],
);
},
),
),
];
},
body: Container()
),
double get maxExtent => 300;
double get minExtent => kToolbarHeight;
double _getCollapsePadding(double t) {
final double deltaExtent = maxExtent - minExtent;
return -Tween<double>(begin: 0.0, end: deltaExtent / 4).transform(t);
}

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