How to add padding to text in SliverAppBar?
this code is not working:
SliverAppBar(
title: Padding(
padding: EdgeInsets.only(top: 100),
child: Text('text'),
)
)
If you set the padding more than the height of the SilverAppBar, the text won't be visible. A workaround is to add the title to the bottom of the SilverAppBar:
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxScrolled) {
return <Widget>[
SliverAppBar(
pinned: true,
bottom: PreferredSize(
preferredSize: Size.fromHeight(60.0),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Align(
alignment: Alignment.topLeft,
child: Text(
'Tabs demo',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 30),
)),
),
),
)
];
},
body: ...
)
);
}
Result:
Use the SliverAppBar like this with padding works like a charm:
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'NiklasLehnfeld',
home: Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
title: Padding(
padding: const EdgeInsets.only(top: 30.0),
child: Text("Niklas Lehnfeld"),
),
leading: Icon(Icons.menu),
)
],
),
)));
}
If it still doesn't work please provide more code how do you integrate the 'SliverAppBar` on your side.
For only Appbar
AppBar{
toolbarHeight: 180,
}
You can do like this:
SliverAppBar(
expandedHeight: 300, //add expand height
floating: false,
pinned: true,
bottom: PreferredSize( // Add this code
preferredSize: Size.fromHeight(60.0), // Add this code
child: Text(''), // Add this code
), // Add this code
flexibleSpace: Container(
padding: EdgeInsets.all(10),
height: 340,
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
height: 40,
),
Container(
height: 60,
),
Expanded(child: Container()),
Text('TEST'),
],
),
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage('https://picsum.photos/400/400'),
fit: BoxFit.cover)),
),
)
Related
Material elevation in Column not working.
On this code elevation not working.
Scaffold(
backgroundColor: Colors.grey,
appBar: AppBar(
title: const Text('Test'),
),
body: Column(
children: [
Material(
elevation: 8,
child: Container(
height: 50,
color: Colors.yellowAccent,
),
),
Container(
height: 50,
color: Colors.white,
)
],
),
);
But just remove Container is working. why?
Scaffold(
backgroundColor: Colors.grey,
appBar: AppBar(
title: const Text('Test'),
),
body: Column(
children: [
Material(
elevation: 8,
child: Container(
height: 50,
color: Colors.yellowAccent,
),
),
],
),
);
has next Container.
remove next Container.
Include SingleChildScrollView and some content message.
It looks like a little shadow appears in the background, but not in the content.
update simple code:
Scaffold(
backgroundColor: Colors.grey,
appBar: AppBar(
title: const Text('Test'),
elevation: 0,
),
body: Column(
children: [
Material(
elevation: 8,
child: Container(
alignment: Alignment.center,
height: 50,
color: Colors.yellowAccent,
child: const Text('Some title message'),
),
),
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
for (var i = 0; i < 20; i++)
Container(
alignment: Alignment.center,
height: 100,
color: Colors.white,
// Divider
margin: const EdgeInsets.only(bottom: 8),
child: const Text('Some content'),
),
],
),
))
],
),
)
I think you can use Stack instead of Column if you want the shadow of Material was visible even if you scroll the list. And add transparent Container on the top of the list.
Scaffold(
backgroundColor: Colors.grey,
appBar: AppBar(
title: const Text('Test'),
elevation: 0,
),
// Use stack instead of column
body: Stack(
children: [
SingleChildScrollView(
child: Column(
children: [
// Add transparent container
Container(
alignment: Alignment.center,
height: 60,
color: Colors.transparent,
),
for (var i = 0; i < 20; i++)
Container(
alignment: Alignment.center,
height: 100,
color: Colors.white,
// Divider
margin: const EdgeInsets.only(bottom: 8),
child: const Text('Some content'),
),
],
),
),
Material(
elevation: 8,
child: Container(
alignment: Alignment.center,
height: 50,
color: Colors.yellowAccent,
child: const Text('Some title message'),
),
)
],
),
);
The problem:
Why did contents inside flexibleSpace is not hiding when I'm scrolling up?
This is my code:
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
physics: PageScrollPhysics(),
slivers: [
SliverAppBar(
title: Text('Dashboard'),
actions: [
CircleAvatar(
backgroundColor: Colors.transparent,
backgroundImage: NetworkImage('https://i.pinimg.com/originals/da/51/c2/da51c26fe3398b0f8314fee17a98e0e7.jpg'),
),
SizedBox(width: 10.0),
],
floating: false,
pinned: true,
expandedHeight: 300.0,
flexibleSpace: Stack(
children: <Widget>[
Positioned.fill(
child: Image.network(
"https://images.wallpapersden.com/image/download/colorful-neon-bubbles_a2dtaWmUmZqaraWkpJRmbmdlrWZlbWU.jpg",
fit: BoxFit.cover,
)
),
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Join as our member now,\nget discount upto 70%', style: TextStyle(color: Colors.white),),
SizedBox(height: 8.0),
RaisedButton(
child: Text('Subscribe now', style: TextStyle(color: Colors.red),),
onPressed: () {},
)
],
),
)
],
),
),
SliverList(
delegate: SliverChildListDelegate([
Container(
height: 500.0,
),
]),
)
],
),
);
}
}
EDIT: I tried this, but it didn't work.
bottom: PreferredSize(
preferredSize: Size.fromHeight(0),
child: ...
Add a FlexibleSpaceBar, then your Stack as its background, like this:
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
physics: PageScrollPhysics(),
slivers: [
SliverAppBar(
title: Text('Dashboard'),
actions: [
CircleAvatar(
backgroundColor: Colors.transparent,
backgroundImage: NetworkImage(
'https://i.pinimg.com/originals/da/51/c2/da51c26fe3398b0f8314fee17a98e0e7.jpg'),
),
SizedBox(width: 10.0),
],
floating: false,
pinned: true,
expandedHeight: 300.0,
flexibleSpace: FlexibleSpaceBar(
background: Stack(
children: <Widget>[
Positioned.fill(
child: Image.network(
"https://images.wallpapersden.com/image/download/colorful-neon-bubbles_a2dtaWmUmZqaraWkpJRmbmdlrWZlbWU.jpg",
fit: BoxFit.cover,
)),
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'Join as our member now,\nget discount upto 70%',
style: TextStyle(color: Colors.white),
),
SizedBox(height: 8.0),
RaisedButton(
child: Text(
'Subscribe now',
style: TextStyle(color: Colors.red),
),
onPressed: () {},
)
],
),
)
],
),
)),
SliverList(
delegate: SliverChildListDelegate([
Container(
height: 500.0,
),
]),
)
],
),
);
}
}
Anybody how to do the layout similar to the image? I am having difficulty on the CardView and it position is lies between the body. I am still consider quite new to Flutter, having some difficulty in UI part. Full code is as below:
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
appBar: PreferredSize(
preferredSize: Size.fromHeight(45.0),
child: AppBar(
automaticallyImplyLeading: false,
elevation: 0.0,
centerTitle: true,
backgroundColor: Color(0xFFED2849),
leading: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
margin: const EdgeInsets.only(left: 8.0),
child: GestureDetector(
onTap: (){
Navigator.of(context).pop(null);
},
child: Image.asset('assets/ic_user_title_back.png', width: 12.0, height: 12.0,),
),
),
],
),
title: Center(
child: Container(
child: Text(
'账号中心',
style: TextStyle(color: Color(0xFFFFFFFF), fontSize: 14),
),
),
),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
child: GestureDetector(
onTap: (){
//logout
},
child: Text(
'退出登陆',
style: TextStyle(color: Color(0xFFFFFFFF), fontSize: 11),
),
),
),
],
),
)
],
)
),
body: SafeArea(
top: false,
child: Material(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
flex: 3,
child: Container(
color: Color(0xFFED2849),
),
),
Expanded(
flex: 7,
child: Container(
color: Color(0xFFF1F1F1),
),
)
],
),
),
)
);
}
You can do this using Stack
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Stack(
// fit: StackFit.expand,
children: [
Column(
children: [
Expanded(
flex: 3,
child : Container(color: Colors.red)
),
Expanded(
flex: 7,
child: Container(
color : Colors.white)
)
]
),
Positioned(
top: MediaQuery.of(context).size.height * 0.2,
left: 20,
right: 20,
child:Card(
child: Padding(
padding : const EdgeInsets.all(16),
child: Text("Your Text here", ),
),)
)
],
)
Try using Stack() it will allow you to overlap several children in a simple way.
The SliverAppbar will stretch and zoom if it is in a customScrollView but it does not when it is in NestedScrollView. Only the body of NestedScrollView has a BouncingScrollPhysics, how can the header of NestedScrollView also have the BouncingScrollPhysics so it can stretch and zoom the SliverAppBar.
However, if i add scrollController in the body/inner scrollView then the header SliverAppBar stretches, but then they become two separate scroll views and the header does not scroll up when the body is scrolled. Check the
Screen recording
#override
Widget build(BuildContext context) {
return Scaffold(
body: DefaultTabController(
length: 3,
child: NestedScrollView(
physics: BouncingScrollPhysics(),
controller: mainScroller,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
stretch: true,
pinned: true,
floating: false,
elevation: 0,
onStretchTrigger: () {
print('stretch');
return;
},
title: isFlexibleSpaceVisible ? null : Text(widget.name),
expandedHeight: containerHeight - kToolbarHeight,
flexibleSpace: FlexibleSpaceBar(
stretchModes: <StretchMode>[
StretchMode.zoomBackground,
StretchMode.blurBackground,
],
collapseMode: CollapseMode.pin,
background: Container(
color: Theme.of(context).canvasColor,
child: Stack(
children: <Widget>[
Container(
height: headerImageHeight,
width: double.infinity,
decoration: BoxDecoration(
color: kBackgroundColor,
image: DecorationImage(
fit: BoxFit.cover,
colorFilter: ColorFilter.mode(
Colors.black54,
BlendMode.darken,
),
image: NetworkImage(
'https://picsum.photos/seed/${Random().nextInt(100)}/${MediaQuery.of(context).size.width.toInt()}'),
),
),
),
Container(
height: headerSpace,
margin: EdgeInsets.only(
top: headerImageHeight - bringImageUpMargin),
padding: EdgeInsets.only(left: 8, right: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
decoration: BoxDecoration(
color: Theme.of(context).canvasColor,
shape: BoxShape.circle),
padding: EdgeInsets.all(6),
child: CircleAvatar(
backgroundColor: kCardColor,
backgroundImage: NetworkImage(
'https://picsum.photos/seed/${Random().nextInt(100)}/200'),
radius: profileImageRadius,
),
),
Expanded(
child: Container(
margin: EdgeInsets.symmetric(
horizontal: 4, vertical: 12),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: <Widget>[
Text(
widget.name,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w700),
),
SizedBox(height: 2),
Wrap(
alignment: WrapAlignment.spaceBetween,
children: <Widget>[
Container(
padding: EdgeInsets.symmetric(
horizontal: 6, vertical: 2),
decoration: BoxDecoration(
color: kPrimaryColor,
borderRadius:
BorderRadius.circular(4)),
child: Text(
widget.skill,
style: TextStyle(
fontSize: 12,
color: Colors.white),
),
),
Container(
padding: EdgeInsets.symmetric(
vertical: 2, horizontal: 6),
decoration: BoxDecoration(
color: kCardColor,
borderRadius:
BorderRadius.circular(4)),
child: Text(
'\$${widget.rate} / ${widget.per}',
style: TextStyle(
color: kPrimaryColor,
fontSize: 12),
),
),
],
),
],
),
),
)
],
),
),
],
),
),
),
),
SliverToBoxAdapter(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Container(
width: 22,
height: 18,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
color: kSecondaryColor,
),
child: Icon(
Icons.star,
color: Colors.white,
size: 14,
)),
SizedBox(
width: 6,
),
Text('Do you recommend ${widget.name} ?'),
],
),
Row(
children: <Widget>[
Expanded(
child: OutlineButton(
highlightedBorderColor: kSecondaryColor,
color: kSecondaryColor,
borderSide: BorderSide(color: kSecondaryColor),
textColor: kSecondaryColor,
onPressed: () => null,
child: Text('NO'),
),
),
SizedBox(
width: 8,
),
Expanded(
child: RaisedButton(
onPressed: () => null,
child: Text('YES'),
),
),
],
)
],
),
),
),
SliverPersistentHeader(
pinned: true,
delegate: SliverProfileTabs(),
)
];
},
body: ProfileTabsView(data: widget),
),
),
);
}
}
As mentioned in the comment, there is an open bug in GitHub for this.
The reason for this behavior was discussed in this
thread:
The reason the stretch does not happen is because the
_NestedScrollViewCoodinator currently prioritizes the inner scrollable for any overscroll from the user drag. I am thinking we can add a flag
like, NestedScrollView.stretchHeaderSlivers, which will flip that to
send overscroll to the outer scrollable. That part should be easy.
The _NestedScrollViewCoordinator.createOuterBallisticScrollActivity
will need to be refactored since it currently assumes that the outer
scrollable will never overscroll, which may or may not be as easy.
And they have mentioned that this is a huge refactoring and there is no suitable solutions yet:
I've taken a crack at this a few different times and have not found a
suitable solution yet. The NestedScrollView bases much more than I
though on the assumption that the outer scroll view will never
overscroll. I believe this will take a larger refactoring/re-design of
the widget in order to support, maybe work we can schedule for in the
new year. For now, I won't be actively working on this anymore. I am
un-assigning myself for now in case some one else would like to try
solving this in the meantime. :)
Since I'm not able to view your screen recording, I'll just post a sample view of how the bug looks like. It was taken from the GitHub issue thread.
Sample code:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Material App',
theme: ThemeData.dark(),
home: Home(),
);
}
}
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
body: NestedScrollView(
physics: BouncingScrollPhysics(),
headerSliverBuilder: (context, innerScrolled) => <Widget>[
SliverOverlapAbsorber(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
context),
sliver: SliverAppBar(
pinned: true,
stretch: true,
title: Text('username'),
expandedHeight: 325,
flexibleSpace: FlexibleSpaceBar(
stretchModes: <StretchMode>[
StretchMode.zoomBackground,
StretchMode.blurBackground,
],
background: Image.network(
'https://i.imgur.com/QCNbOAo.png',
fit: BoxFit.cover)),
bottom: TabBar(
tabs: <Widget>[Text('test1'), Text('test2')])),
)
],
body: TabBarView(children: [
Center(
child: Builder(
builder: (context) => CustomScrollView(
slivers: <Widget>[
SliverOverlapInjector(
handle:
NestedScrollView.sliverOverlapAbsorberHandleFor(
context)),
SliverFixedExtentList(
delegate: SliverChildBuilderDelegate(
(_, index) => Text('not working'),
childCount: 100),
itemExtent: 25)
],
),
),
),
Center(child: Text('working'))
])),
));
}
}
Output:
I've try to put a Column(a Container inside) in SliverAppBar bottom property as a button, but it can't overlap the ExtentList ,just overflow the bottom margin.
I want to make it overlapped just like Spotify App do.
this is Spotify Sample:
https://imgur.com/VrZRY4c
this is what I've tried:
https://imgur.com/4bNZw8j
My code:
class _MenuListState extends State<MenuList> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverPadding(
padding: EdgeInsets.only(top: 10, bottom: 10),
sliver: SliverAppBar(
pinned: true,
expandedHeight: 300,
title: Text(
'Testing',
style: TextStyle(color: Colors.red),
),
flexibleSpace: FlexibleSpaceBar(
title: Text(''),
background: Image.asset(
'images/w.jpg',
fit: BoxFit.cover,
),
),
bottom: PreferredSize(
child: Column(children: <Widget>[
Text(
'test',
style: TextStyle(),
),
Container(
decoration: BoxDecoration(
color: Color.fromRGBO(109, 76, 65, 1),
borderRadius: BorderRadius.all(
Radius.circular(20),
),
),
height: 54,
width: 100,
),
]),
),
),
),
SliverFixedExtentList(//extentlist)
],
),
);
}
}
Try this
class _MenuListState extends State<MenuList> {
static const double _appBarBottomBtnPosition =
24.0; //change this value to position your button vertically
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
title: Text(
'Testing',
style: TextStyle(color: Colors.red),
),
),
SliverAppBar(
pinned: true,
expandedHeight: 300.0,
flexibleSpace: FlexibleSpaceBar(
centerTitle: true,
titlePadding: EdgeInsets.only(bottom: 25),
title: Text('Title'),
background: Image.asset(
'images/w.jpg',
fit: BoxFit.cover,
),
),
bottom: PreferredSize(
preferredSize: const Size.fromHeight(0.0),
child: Transform.translate(
offset: const Offset(0, _appBarBottomBtnPosition),
child: RaisedButton(
shape: StadiumBorder(),
child: Text("Click Here"),
onPressed: () {},
),
),
),
),
SliverPadding(
padding: EdgeInsets.only(top: _appBarBottomBtnPosition),
),
SliverFixedExtentList(
//extentlist
),
],
),
);
}
}
The answer provided by #Crazy Lazy Cat works .. but if you are worried about using 2 SliverAppBar 's. you can substitute with the code below to replace the 2 SliverAppBar
SliverAppBar(
expandedHeight: 500.0,
flexibleSpace: FlexibleSpaceBar(
background: Image.asset(
'images/w.jpg',
fit: BoxFit.cover,
),
),
bottom: PreferredSize(
preferredSize: const Size.fromHeight(0.0),
child: Transform.translate(
offset: const Offset(0, _appBarBottomBtnPosition),
child: RaisedButton(
shape: StadiumBorder(),
child: Text("Click Here"),
onPressed: () {},
),
),
),
),