Flutter : Image Lost in SliverAppBar - flutter

I'm Working with SliverAppBar.
Previous I have 2 Page Let's Say (Search,and Detail) ,
In Detail Page,I have problem When i Scroll Down and make Image not visible after that I'm press button Back , My Image lost in Search Page. But if i Scroll down and then little Scroll Up to make Image visible after that i press Back button , My image not lost and still stay there.
It's may be confusing, but you can see the GIF for more detail.
Can you help Me with this ?
Thank's
It's Detail.dart :
import 'package:flutter/material.dart';
import 'package:flutter_news/model/Berita_model.dart';
import 'package:flutter_news/widget/Widget_builder.dart';
class WartawanDetail extends StatefulWidget {
final int idWartawan;
final String gambarWartawan;
final String namaWartawan;
WartawanDetail({this.idWartawan, this.gambarWartawan, this.namaWartawan});
#override
_WartawanDetailState createState() => _WartawanDetailState();
}
class _WartawanDetailState extends State<WartawanDetail> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
floating: true,
pinned: false,
leading: IconButton(
icon: Icon(Icons.arrow_left),
onPressed: () => Navigator.pop(context),
),
expandedHeight: 300.0,
centerTitle: true,
flexibleSpace: FlexibleSpaceBar(
background: Hero(
tag: widget.idWartawan,
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(widget.gambarWartawan),
fit: BoxFit.cover),
),
child: Stack(
children: <Widget>[
Positioned(
bottom: 10,
left: 10,
child: Material(
color: Colors.transparent,
child: Chip(
backgroundColor: Colors.blue,
labelStyle: TextStyle(color: Colors.white),
label: Text(widget.namaWartawan),
),
),
),
Positioned(
bottom: 10,
right: 10,
child: Material(
color: Colors.transparent,
child: Chip(
backgroundColor: Colors.blue,
labelStyle: TextStyle(color: Colors.white),
label: Text("2 Berita"),
),
),
),
],
),
),
),
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.more_horiz),
onPressed: () => "",
),
],
),
SliverFixedExtentList(
itemExtent: MediaQuery.of(context).size.height,
delegate: SliverChildListDelegate(
[
Container(
padding: EdgeInsets.all(8),
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: beritas.length,
itemBuilder: newsBuilderHome),
),
],
),
)
],
),
);
}
}
It's My Search.dart
Widget wartawanBuilderSearch(BuildContext context, int index) {
ThemeData localTheme = Theme.of(context);
return Container(
margin: EdgeInsets.all(8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: Container(
child: Hero(
tag: wartawans[index].idWartawan,
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () => Navigator.push(
context,
PageTransition(
type: PageTransitionType.downToUp,
child: WartawanDetail(
idWartawan:wartawans[index].idWartawan,
gambarWartawan: wartawans[index].gambarWartawan,
namaWartawan: wartawans[index].namaWartawan,
),
),
),
child: CircleAvatar(
backgroundColor: Colors.red,
radius: 50,
backgroundImage:
AssetImage(wartawans[index].gambarWartawan),
),
),
),
),
),
),
Container(
child: Align(
alignment: Alignment.bottomLeft,
child: Text(
wartawans[index].namaWartawan,
style: localTheme.textTheme.caption
.copyWith(fontSize: 14, fontWeight: FontWeight.bold),
overflow: TextOverflow.ellipsis,
),
),
)
],
),
);
}

Related

How I put Blur image in the scaffold background in flutter

I want to put the transparent image on the background with text on it. I tried with container in return but it's not working. Also I tried container in the body, but unfortunately that is also not working for me. It's a single screen app. Below is my code. Your answer will be very helpful for me.
Thanks in advance.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Padding(
padding: const EdgeInsets.all(8.0),
child: Image.asset(
"assets/tree.png",
),
),
centerTitle: true,
title: Text(
"Welcome To Plants",
style: TextStyle(
color: Colors.green,
fontWeight: FontWeight.w800,
),
)),
body: Column(
children: [
Flexible(
child: ListView.builder(
itemCount: _messages.length,
reverse: true,
itemBuilder: (context, index) => Padding(
padding: const EdgeInsets.all(8.0), child: _messages[index]),
),
),
const Divider(
color: Color.fromARGB(255, 51, 223, 56),
thickness: 1,
),
_istyping ? LinearProgressIndicator() : Container(),
Padding(
padding: const EdgeInsets.only(bottom: 10),
child: Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: _controller,
onSubmitted: (value) => _sendMessage(),
decoration: const InputDecoration.collapsed(
hintText: "Type Here",
hintStyle: TextStyle(fontSize: 20)),
),
)),
ButtonBar(children: [
IconButton(
onPressed: () {
_isImageSearch = false;
_sendMessage();
},
icon: Icon(
Icons.send,
color: Theme.of(context).primaryColor,
)),
TextButton(
onPressed: () {
_isImageSearch = true;
_sendMessage();
},
child: Text("Show Image"))
]),
],
),
)
],
)
Import the following module
import 'dart:ui';
make sure you included the asset in your yaml file
eg: used lib/utils/images/test.jpg
Example Scaffold
Scaffold(
backgroundColor: Colors.transparent,
body: Stack(
children: <Widget>[
Image.asset('lib/utils/images/test.jpg', fit: BoxFit.fill),
BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5.0, sigmaY: 5.0),
child: Container(
color: Colors.black.withOpacity(0.5),
),
),
// Add your UI component here
],
),
);
Example screenshot

Flutter Listview colour but not text remains visible outside of container

I am trying to render a listview and divider in a column and have used a container to restrict the height.The text of the List Tiles is shown only within the Container however the listtile colour is shown outside the container. I want this layout but for the colour to be only shown within the container as well.
Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(10),
),
height: MediaQuery.of(context).size.height * 0.5,
width: MediaQuery.of(context).size.width * 0.8,
child: ListView.builder(
itemCount: 20,
itemBuilder: (ctx, index) => Column(
children: [
ListTile(
tileColor: Colors.red,
leading: Text("Test"),
),
Divider()
],
),
),
)
Simply wrap the ListTile with the Card to avoid overflow; similar to the example in the docs.
Card(
child: ListTile(//...)
//...
)
updated
import 'package:flutter/material.dart';
class SEList extends StatelessWidget {
const SEList({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Icon(
Icons.menu,
color: Colors.white,
),
title: Text("User Profile"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: LayoutBuilder(
builder: (context, constraints) => Column(
children: [
Container(
child: Center(
child: Column(
children: [
Text("Name"),
Text("Name"),
Text("Name"),
Text("Name"),
Container(
height: 70,
child: Text(
"Job",
style: TextStyle(
fontSize: 24,
),
),
)
],
),
),
),
SizedBox(
/// 70% of screen for listView
height: constraints.maxHeight * .65,
child: ListView.separated(
itemBuilder: (context, index) => Container(
child: Text("Text $index"),
height: 70,
color: Colors.redAccent,
),
separatorBuilder: (context, index) => Divider(
thickness: 1.2,
),
itemCount: 30,
),
)
],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: Icon(
Icons.upload_file,
),
),
);
}
}

How to change the whole background color of Drawer in Flutter

first of all i'm new to flutter and so i am quite confused how to change the "whole" background color in drawer flutter.
i managed to change my ListTile and my so called DrawerHeader to the color i want but the rest (below the ListTile is all white). And there is a line below the DrawerHeader that i don't really want but i can't get rid of it.
here is the code
import 'package:flutter/material.dart';
import '../style/theme.dart' as style;
class MyDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
// width: MediaQuery.of(context).,
child: Drawer(
elevation: 0,
child: ListView(
children: <Widget>[
Container(
height: 170,
width: 170,
padding: EdgeInsets.only(top:30),
color: style.Colors.secondColor,
child: Column(children: <Widget>[
Material(
borderRadius: BorderRadius.all(Radius.circular(100)),
child: Padding(padding: EdgeInsets.all(20.0),
child: Image.asset('images/circle.png',width: 80, height: 80,),),
//TODO ganti logo
),
],),
),
Container(
color: style.Colors.secondColor,
child: Column(
children: <Widget>[
ListTile(
leading: Icon(Icons.help_outline_sharp),
title: Text('Help', style: TextStyle(fontSize: 18,),),
onTap: () {},
),
ListTile(
leading: Icon(Icons.person),
title: Text('About us', style: TextStyle(fontSize: 18,),),
onTap: () {},
),
],
),
),
],
),
),
);
}
}
here is the photo of the current situation
Here is the photo
Another Question
what if i want to put a single ListTile on the bottom? (like log out)
For changing the background color of drawer you can just swap the Drawer Widget with Container and give color to container
class MyDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Drawer(
elevation: 0,
child: Container(
color: Colors.blue,
child: ListView(
children: <Widget>[
Container(
height: 170,
width: 170,
padding: EdgeInsets.only(top:30),
color: Colors.red,
child: Column(children: <Widget>[
Material(
borderRadius: BorderRadius.all(Radius.circular(100)),
child: Padding(padding: EdgeInsets.all(20.0),
child: Image.asset('images/circle.png',width: 80, height: 80,),),
),
],),
),
Container(
color: Colors.red,
child: Column(
children: <Widget>[
ListTile(
leading: Icon(Icons.help_outline_sharp),
title: Text('Help', style: TextStyle(fontSize: 18,),),
onTap: () {},
),
ListTile(
leading: Icon(Icons.person),
title: Text('About us', style: TextStyle(fontSize: 18,),),
onTap: () {},
),
],
),
),
],
),
),
);
}
}
This can be the final code you can use, it has answer to all your three questions
class MyDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Drawer(
child: Column(
children: <Widget>[
Expanded(
child: ListView(
children: <Widget>[
Container(
height: 170,
width: 170,
padding: EdgeInsets.only(top:30),
color: Colors.blue,
child: Column(children: <Widget>[
Material(
borderRadius: BorderRadius.all(Radius.circular(100)),
child: Padding(padding: EdgeInsets.all(20.0),
child: Image.asset('images/circle.png',width: 80, height: 80,),),
),
],
),
),
ListTile(
leading: Icon(Icons.help_outline_sharp),
title: Text('Help', style: TextStyle(fontSize: 18,),),
onTap: () {},
),
ListTile(
leading: Icon(Icons.person),
title: Text('About us', style: TextStyle(fontSize: 18,),),
onTap: () {},
),
],
),
),
Align(
alignment: Alignment.bottomCenter,
child: ListTile(
leading: Icon(Icons.logout),
title: Text('Logout')
),
),
],
),
);
}
}
To change the color, wrap the Drawer widget in a Theme widget as follows:
Scaffold(
drawer:Theme(
data:Theme.of(context).copyWith(
canvasColor://the desired color will go here
),
child:Drawer(/*drawer content*/)
)
)
Hope this is useful for someone

Flutter SliverAppbar in NestedScrollView header does not stretch and zoom like it would stretch in CustomScrollView

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:

How can I add a Button on bottom of SliverAppBar and make it overlap on ExtentList?

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: () {},
),
),
),
),