How to make the background image behind the transparent SliverAppBar? - flutter

I'm a beginner to Flutter and I have a problem with the screen background, it was filled fully when I used the AppBar, but when I changed it to SliverAppBar, the top bar becomes empty and the image starts after it, how to solve this because most of the issues when I searched, are regarding the SliverAppBar background itself, not the main background
Also, how to control the location of the leading image (logo) without its size being changed, because when I change the location using margin, it becomes smaller
// ignore_for_file: deprecated_member_use, unnecessary_const
import 'package:decorated_icon/decorated_icon.dart';
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
HomePage({Key? key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFFFFFFF),
extendBodyBehindAppBar: true,
body: NestedScrollView(
headerSliverBuilder: (context, innerBoxIsScrolled) => [
SliverAppBar(
actions: [
Stack(
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(0, 15, 12, 0),
child: IconButton(
icon: const DecoratedIcon(
Icons.notifications,
color: Color.fromARGB(255, 0, 0, 0),
size: 30.0,
shadows: [
BoxShadow(
blurStyle: BlurStyle.normal,
blurRadius: 7.0,
color: Color.fromARGB(255, 0, 0, 0),
offset: Offset.zero,
),
],
),
onPressed: () {},
),
),
],
),
// ),
],
leading: Container(
margin: const EdgeInsets.fromLTRB(20, 20, 0, 0),
child: const Padding(
padding: EdgeInsets.fromLTRB(0, 0, 0, 0),
child: Image(
image: AssetImage('images/logo.png'),
height: 500,
fit: BoxFit.fill,
),
),
),
backgroundColor: Colors.transparent,
elevation: 0,
),
],
body: Stack(
children: <Widget>[
Container(
decoration: const BoxDecoration(
image: const DecorationImage(
image: const AssetImage("images/background.jpg"),
fit: BoxFit.fill,
),
),
),
],
),
),
);
}
}

Try this,
return Container(
height:screenheight,
width:screenwidth,
child:Scaffold()
);

Implemented like this in my code. Hope this helps you as well.
SliverAppBar(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
expandedHeight: 310,
elevation: 0,
floating: true,
iconTheme: IconThemeData(color: Theme.of(context).primaryColor),
centerTitle: true,
automaticallyImplyLeading: false,
leading: new IconButton(
icon: Container(
decoration: BoxDecoration(shape: BoxShape.circle, boxShadow: [
BoxShadow(
color: Get.theme.primaryColor.withOpacity(0.5),
blurRadius: 20,
),
]),
child: new Icon(Icons.arrow_back_ios, color: Get.theme.hintColor),
),
onPressed: () => {Get.back()},
),
flexibleSpace: FlexibleSpaceBar(
collapseMode: CollapseMode.parallax,
background: Obx(() {
return Stack(
alignment: AlignmentDirectional.bottomCenter,
children: <Widget>[
buildCarouselSlider(_eService),
],
);
}),
).marginOnly(bottom: 50),
),

Related

Make Listeview work nested inside of column inside of a container in flutter

I am trying and make a Listeview work, which is nested inside of column that is nested inside of a container in flutter. The container is supposed to be a dialog. I think the problem is that the container has no defined hight (it is supposed to adapt to the screen size). With the current code I get a bottom overflow. Maybe because of the padding of the container?
I tried differen variants with expanded, flexible and singlechildscrollview but I can't make it work. The standard tip, wrap the ListView with Expanded seems not to work.
Thanks for your help!
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Dialog',
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Welcome to Flutter'),
),
body: Center(
child: Column(
children: [
MaCard(mitarbeiterName: "Name"),
CustomDialogBoxRow(
title: "Sturmtruppler",
descriptions: "wird noch weichen",
text: "text")
],
),
),
),
);
}
}
class Constants {
Constants._();
static const double padding = 20;
static const double avatarRadius = 100;
static const double buttonHight = 100;
}
class CustomDialogBoxRow extends StatefulWidget {
final String title, descriptions, text;
const CustomDialogBoxRow({
Key? key,
required this.title,
required this.descriptions,
required this.text,
}) : super(key: key);
#override
_CustomDialogBoxRowState createState() => _CustomDialogBoxRowState();
}
class _CustomDialogBoxRowState extends State<CustomDialogBoxRow> {
#override
Widget build(BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(Constants.padding),
),
elevation: 0,
backgroundColor: Colors.transparent,
child: contentBox(context),
);
}
contentBox(context) {
return Stack(
children: <Widget>[
Container(
constraints: const BoxConstraints(minWidth: 400, maxWidth: 800),
padding: const EdgeInsets.only(
left: Constants.padding,
right: Constants.padding,
bottom: Constants.padding),
margin: const EdgeInsets.only(top: Constants.avatarRadius),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.white,
borderRadius: BorderRadius.circular(Constants.padding),
boxShadow: [
const BoxShadow(
color: const Color.fromARGB(255, 79, 73, 73),
offset: const Offset(0, 5),
blurRadius: 5),
]),
child: Column(
children: [
SizedBox(
height: Constants.avatarRadius,
child: Row(
children: [
const SizedBox(
child: const Placeholder(),
),
const Expanded(
child: Placeholder(),
),
],
),
),
SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 50,
child: Text("bla"),
),
SizedBox(
height: 50,
child: Text("bla"),
),
SizedBox(
height: 50,
child: Text("bla"),
),
SizedBox(
height: 50,
child: Text("bla"),
)
],
),
)
],
),
),
Positioned(
left: Constants.padding,
right: Constants.padding,
child: Stack(
children: [
Container(
child: Align(
alignment: Alignment.topLeft,
child: Container(
width: Constants.avatarRadius * 2,
height: Constants.avatarRadius * 2,
child: const CircleAvatar(
radius: Constants.avatarRadius * 2,
backgroundImage: AssetImage('assets/images/SBE.jpg'),
),
),
),
),
],
),
),
],
);
}
}
class MaCard extends StatefulWidget {
MaCard({
Key? key,
required this.mitarbeiterName,
}) : super(key: key);
final String mitarbeiterName;
#override
State<MaCard> createState() => _MaCardState();
}
class _MaCardState extends State<MaCard> {
#override
Widget build(BuildContext context) {
return Card(
child: InkWell(
onTap: () {
print("card taped");
/*showDialog(context: context, builder: (BuildContext context) {
return
})*/
showDialog(
context: context,
builder: (BuildContext context) {
return CustomDialogBoxRow(
title: "Stormtrouper",
descriptions: "Jojo, this is card",
text: "Roger Roger",
);
});
},
child: SizedBox(
height: Constants.buttonHight,
width: 300,
child: Center(child: Text(widget.mitarbeiterName)),
),
));
}
}
Here is picture of what it should look like. My wonderful handdrawing is supposed to be the scrollable content.
Goal
It would be better using LayoutBuilder to get parent constraints and size the inner elements. Also You need to wrap with Expaned to get available spaces for infinite size widget.
I will highly recommend to check this video from Flutter.
Changes are made
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Dialog',
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Welcome to Flutter'),
),
body: Center(
child: Column(
children: [
MaCard(mitarbeiterName: "Name"),
Expanded( //here
child: CustomDialogBoxRow(
title: "Sturmtruppler",
descriptions: "wird noch weichen",
text: "text"),
)
],
),
),
),
);
}
}
And on contentBox
contentBox(context) {
return LayoutBuilder(builder: (context, constraints) {
print(constraints);
return SizedBox(
width: constraints.maxWidth,
height: constraints.maxHeight,
child: Stack(
children: <Widget>[
Container(
constraints: const BoxConstraints(minWidth: 400, maxWidth: 800),
padding: const EdgeInsets.only(
left: Constants.padding,
right: Constants.padding,
bottom: Constants.padding),
margin: const EdgeInsets.only(top: Constants.avatarRadius),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.white,
borderRadius: BorderRadius.circular(Constants.padding),
boxShadow: const [
BoxShadow(
color: Color.fromARGB(255, 79, 73, 73),
offset: Offset(0, 5),
blurRadius: 5),
]),
child: Column(
children: [
SizedBox(
height: Constants.avatarRadius,
child: Row(
children: [
const Expanded(
child: const Placeholder(),
),
const Expanded(
child: Placeholder(),
),
],
),
),
Expanded(
// or sizedBOx ( constraints.maxHeight- Constants.avatarRadius,)
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 450,
child: Text("bla"),
),
SizedBox(
height: 50,
child: Text("bla"),
),
SizedBox(
height: 50,
child: Text("bla"),
),
SizedBox(
height: 50,
child: Text("bla"),
)
],
),
),
)
],
),
),
// Positioned(
// left: Constants.padding,
// right: Constants.padding,
// child: Stack(
// children: [
// Container(
// child: Align(
// alignment: Alignment.topLeft,
// child: Container(
// width: Constants.avatarRadius * 2,
// height: Constants.avatarRadius * 2,
// child: const CircleAvatar(
// radius: Constants.avatarRadius * 2,
// backgroundImage: AssetImage('assets/images/SBE.jpg'),
// ),
// ),
// ),
// ),
// ],
// ),
// ),
//
],
),
);
});
}

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

Designing a Flutter button with image and text

If I just throw together an image and some text in a rounded-corner rectangle, the user will not know that they can "click here". But I don't have to bake my own solution. InkWell covers this scenario, complete with a nice shadow.
I am positioning
a custom clickable icon using the
InkWell
class, itself requiring to be inside an
Ink
instance.
import 'package:flutter/material.dart';
const boat_url = ('https://upload.wikimedia.org/wikipedia/commons/thumb/0/05/'
'Segelboot_Bodensee_Mainau_%28Foto_Hilarmont%29.JPG/'
'182px-Segelboot_Bodensee_Mainau_%28Foto_Hilarmont%29.JPG');
void main() {
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Image',
home: Scaffold(
backgroundColor: Colors.grey,
body: MyImage(),
)));
}
class MyImage extends StatelessWidget {
MyImage({Key key,});
#override
Widget build(BuildContext context) {
Size sz = MediaQuery.of(context).size * 0.4;
double border = 4;
return Stack(children: [
Positioned(
top: 100,
left: 100,
width: sz.width,
height: sz.height,
child: Material(
child: Ink(
decoration: BoxDecoration(
boxShadow: <BoxShadow>[
new BoxShadow(
color: Colors.red,
blurRadius: 10.0,
offset: new Offset(30.0, 20.0),
),
],
border: Border.all(
color: Colors.blue,
width: border,
),
borderRadius: BorderRadius.circular(40),
),
child: InkWell(
onTap: (){/*..*/},
child: Column(
children: [
Container(
height: 4 * (sz.height - 2 * border) / 5,
alignment: Alignment.center,
child: Image.network(boat_url),
),
Container(
height: (sz.height - 2 * border) / 5,
child: FittedBox(
clipBehavior: Clip.antiAlias,
alignment: Alignment.centerLeft,
fit: BoxFit.fitHeight,
child: Text('A long descriptive sentence')),
)
],
)),
),
)),
]);
}
}
1- I'm not actually using Colors.white, and the Scaffold itself has
backgroundColor: Colors.grey. Where is the white background coming from?
2- When we talk of a "shadow", I'm expecting the shadow to be behind
the ink/inkwell object. Why does the shadow appear in front?
Related: 1
That white color is from the Material widget, to remove that you can use type param.
Material(
type: MaterialType.transparency,
child: Container(),
);
Here is code to achieve the custom button
Video link
Scaffold(
backgroundColor: Colors.blueGrey,
body: SafeArea(
child: Container(
decoration: BoxDecoration(
color: Colors.green.shade200,
border: Border.all(color: Colors.green),
borderRadius: BorderRadius.circular(5),
boxShadow: [
BoxShadow(
blurRadius: 5,
spreadRadius: 2,
color: Colors.black26,
)
]),
margin: const EdgeInsets.all(20),
child: Material(
type: MaterialType.transparency,
child: InkWell(
onTap: () {},
splashColor: Colors.black26,
child: IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(mainAxisSize: MainAxisSize.min, children: [
Image.asset(
'assets/images/marked_tyre_base.png',
fit: BoxFit.cover,
width: 80,
height: 80,
),
const SizedBox(
height: 10,
),
Text(
'Tyre 1',
style: TextStyle(color: Colors.white),
)
]),
),
),
),
),
),
),
);
Screenshot:
Create a class, ImageTextButton:
class ImageTextButton extends StatelessWidget {
final VoidCallback onPressed;
final ImageProvider image;
final double imageHeight;
final double radius;
final Widget text;
ImageTextButton({
#required this.onPressed,
#required this.image,
this.imageHeight = 200,
this.radius = 28,
#required this.text,
});
#override
Widget build(BuildContext context) {
return Card(
elevation: 8,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(radius)),
clipBehavior: Clip.hardEdge,
child: InkWell(
onTap: onPressed,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Ink.image(
image: image,
height: imageHeight,
fit: BoxFit.cover,
),
SizedBox(height: 6),
text,
SizedBox(height: 6),
],
),
),
);
}
}
Usage:
ImageTextButton(
onPressed: () {},
image: AssetImage('chocolate_image'),
text: Text('Chocolate'),
)

How to overlap two circles?

Can someone help me get this layout with the first circle over the second?
image
I have this function:
Widget overlapped() {
final overlap = 25;
final items = [
Container(
padding: EdgeInsets.only(right: 2),
decoration: new BoxDecoration(
color: Colors.blue,
shape: BoxShape.circle,
),
child: CircleAvatar(
radius: 22,
backgroundImage: AssetImage('assets/example_logo.png'),
backgroundColor: Colors.black,
),
),
CircleAvatar(
radius: 22,
backgroundColor: Colors.white,
child: ClipOval(
child: Image.network(
"https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Google_%22G%22_Logo.svg/1200px-Google_%22G%22_Logo.svg.png",
errorBuilder: (context, exception, stackTrace) {
return Container(color: Colors.white);
},
height: 35,
))),
CircleAvatar(
child: Text('+2', style: TextStyle(color: Colors.white)),
backgroundColor: Theme.of(context).canvasColor),
];
List<Widget> stackLayers = List<Widget>.generate(items.length, (index) {
return Container(
padding: EdgeInsets.fromLTRB(index.toDouble() * overlap, 0, 0, 0),
child: items[index],
);
});
return Stack(children: stackLayers);
}
This function whenever I add an item to the array, it adds a widget on the right. But I want the first to be above the second, the second of the third, etc ...
you could use the Stack widget :
Stack(
children:<Widget>:[
Positioned(
right: 130.0,
child:Container(
shape: BoxShape.circle,
)
),
Positioned(
left: 130.0,
child:Container(
shape: BoxShape.circle,
)
),
]
)
Use Stack and Positioned together.
import 'package:flutter/material.dart';
class OverLap extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Overlap'),
),
body: Container(
padding: const EdgeInsets.all(8.0),
width: 500.0,
child: Stack(
children: <Widget>[
//Change according to your icon
Icon(
Icons.flaky,
size: 50.0,
color: Colors.red,
),
Positioned(
left: 20.0,
//Change according to your icon
child: Icon(
Icons.flaky,
size: 50.0,
color: Colors.blue,
),
),
],
),
),
);
}
}

How to Give BorderRadius to SliverList

I am using SliverAppBar and SliverListView in my project.
I need BorderRadius to my SliverList that is coming bottom of my SliverAppBar.
Here is screenshot what I need :
And here is my code:
Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
backgroundColor: Colors.transparent,
brightness: Brightness.dark,
actions: <Widget>[
IconButton(icon: Icon(Icons.favorite), onPressed: () {}),
IconButton(icon: Icon(Icons.share), onPressed: () {})
],
floating: false,
pinned: false,
//title: Text("Flexible space title"),
expandedHeight: getHeight(context) - MediaQuery.of(context).padding.top,
flexibleSpace: Container(
height: double.infinity,
width: double.infinity,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: AssetImage("assets/images/Rectangle-image.png")
)
),
),
bottom: _bottomWidget(context),
),
SliverList(
delegate: SliverChildListDelegate(listview),
),
],
),
)
So, with this code the UI is coming like this...
can suggest any other approach that i can take to achieve this kind of design...
I achieved this design using SliverToBoxAdapter my code like this.
final sliver = CustomScrollView(
slivers: <Widget>[
SliverAppBar(),
SliverToBoxAdapter(
child: Container(
color: Color(0xff5c63f1),
height: 20,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
height: 20,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(20.0),
topRight: const Radius.circular(20.0),
),
),
),
],
),
),
),
SliverList(),
],
);
I used 2 containers inside SliverToBoxAdapter.
SliverToBoxAdapter is between the Sliver Appbar and the Sliver List.
first I create a blue (should be Appbar color) container for the corner edge.
then I create the same height white container with border-radius inside the blue container for list view.
Preview on dartpad
Solution
At the time of writing, there is no widget that would support this functionality. The way to do it is with Stack widget and with your own SliveWidget
Before:
Here is your default code:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flexible space title',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
backgroundColor: Colors.transparent,
brightness: Brightness.dark,
actions: <Widget>[IconButton(icon: Icon(Icons.favorite), onPressed: () {}), IconButton(icon: Icon(Icons.share), onPressed: () {})],
floating: false,
pinned: false,
expandedHeight: 250 - MediaQuery.of(context).padding.top,
flexibleSpace: Container(
height: 550,
width: double.infinity,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
'https://images.unsplash.com/photo-1561752888-21eb3b67eb4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=967&q=80'))),
),
//bottom: _bottomWidget(context),
),
SliverList(
delegate: SliverChildListDelegate(_listview(50)),
),
],
),
),
);
}
}
List _listview(int count) {
List<Widget> listItems = List();
listItems.add(Container(
color: Colors.black,
height: 50,
child: TabBar(
tabs: [FlutterLogo(), FlutterLogo()],
),
));
for (int i = 0; i < count; i++) {
listItems.add(new Padding(padding: new EdgeInsets.all(20.0), child: new Text('Item ${i.toString()}', style: new TextStyle(fontSize: 25.0))));
}
return listItems;
}
After
And here is your code done with Stack and SliveWidget widgets:
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flexible space title',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
body: Stack(
children: [
Container(
height: 550,
width: double.infinity,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
'https://images.unsplash.com/photo-1561752888-21eb3b67eb4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=967&q=80'))),
),
CustomScrollView(
anchor: 0.4,
slivers: <Widget>[
SliverWidget(
child: Container(
width: double.infinity,
height: 100,
decoration: BoxDecoration(
color: Colors.yellow, borderRadius: BorderRadius.only(topLeft: Radius.circular(30), topRight: Radius.circular(30))),
child: TabBar(
tabs: [FlutterLogo(), FlutterLogo()],
),
),
),
SliverList(
delegate: SliverChildListDelegate(_listview(50)),
),
],
),
],
),
),
);
}
}
List _listview(int count) {
List<Widget> listItems = List();
for (int i = 0; i < count; i++) {
listItems.add(
Container( //NOTE: workaround to prevent antialiasing according to: https://github.com/flutter/flutter/issues/25009
decoration: BoxDecoration(
color: Colors.white, //the color of the main container
border: Border.all(
//apply border to only that side where the line is appearing i.e. top | bottom | right | left.
width: 2.0, //depends on the width of the unintended line
color: Colors.white)),
child: Container(
padding: EdgeInsets.all(20),
color: Colors.white,
child: new Text(
'Item ${i.toString()}',
style: new TextStyle(fontSize: 25.0),
),
),
),
);
}
return listItems;
}
class SliverWidget extends SingleChildRenderObjectWidget {
SliverWidget({Widget child, Key key}) : super(child: child, key: key);
#override
RenderObject createRenderObject(BuildContext context) {
// TODO: implement createRenderObject
return RenderSliverWidget();
}
}
class RenderSliverWidget extends RenderSliverToBoxAdapter {
RenderSliverWidget({
RenderBox child,
}) : super(child: child);
#override
void performResize() {}
#override
void performLayout() {
if (child == null) {
geometry = SliverGeometry.zero;
return;
}
final SliverConstraints constraints = this.constraints;
child.layout(constraints.asBoxConstraints(/* crossAxisExtent: double.infinity */), parentUsesSize: true);
double childExtent;
switch (constraints.axis) {
case Axis.horizontal:
childExtent = child.size.width;
break;
case Axis.vertical:
childExtent = child.size.height;
break;
}
assert(childExtent != null);
final double paintedChildSize = calculatePaintOffset(constraints, from: 0.0, to: childExtent);
final double cacheExtent = calculateCacheOffset(constraints, from: 0.0, to: childExtent);
assert(paintedChildSize.isFinite);
assert(paintedChildSize >= 0.0);
geometry = SliverGeometry(
scrollExtent: childExtent,
paintExtent: 100,
paintOrigin: constraints.scrollOffset,
cacheExtent: cacheExtent,
maxPaintExtent: childExtent,
hitTestExtent: paintedChildSize,
);
setChildParentData(child, constraints, geometry);
}
}
Use Stack. It's the best and smooth way I found and used.
Preview
import 'dart:math';
import 'package:agro_prep/views/structure/constant.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class CropDetailsPage extends StatelessWidget {
const CropDetailsPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: [
SliverAppBar(
backgroundColor: Colors.white,
actions: <Widget>[
IconButton(icon: Icon(Icons.share), onPressed: () {})
],
floating: false,
pinned: false,
//title: Text("Flexible space title"),
expandedHeight: 281.h,
flexibleSpace: Stack(
children: [
const Positioned.fill(
child: FadeInImage(
image: NetworkImage(tempImage),
placeholder: const NetworkImage(tempImage),
// imageErrorBuilder: (context, error, stackTrace) {
// return Image.asset('assets/images/background.jpg',
// fit: BoxFit.cover);
// },
fit: BoxFit.cover,
),
),
Positioned(
child: Container(
height: 33.h,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(
top: Radius.circular(40),
),
),
),
bottom: -7,
left: 0,
right: 0,
)
],
),
),
SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return ListTile(
tileColor: whiteColor,
title: Text(Random().nextInt(100).toString()),
);
}, childCount: 15))
],
),
);
}
}
Worked for me!
SliverAppBar(
pinned: true,
floating: false,
centerTitle: true,
title: TextWidget(detail.title,
weight: FontWeight.bold
),
expandedHeight: MediaQuery.of(context).size.height/2.5,
flexibleSpace: FlexibleSpaceBar(
centerTitle: true,
collapseMode: CollapseMode.parallax,
background: Stack(
children: [
// Carousel images
Swiper(
itemWidth: MediaQuery.of(context).size.width,
itemHeight: MediaQuery.of(context).size.height /3.5,
itemCount: 2,
pagination: SwiperPagination.dots,
loop: detail.banners.length > 1,
itemBuilder: (BuildContext context, int index) {
return Image.network(
'https://image.com?image=123.png',
fit: BoxFit.cover
);
}
),
//Border radius
Align(
alignment: Alignment.bottomCenter,
child: Container(
color: Colors.transparent,
height: 20,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
height: 10,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(10),
topRight: const Radius.circular(10),
),
),
),
],
),
),
)
],
),
),
)
So the best way to achieve your result is to use "bottom" poperty inside SliverAppBar. This will add your rounded container to bottom of appbar / start of sliverlist
bottom: PreferredSize(
preferredSize: const Size.fromHeight(24),
child: Container(
width: double.infinity,
decoration: const BoxDecoration(
borderRadius: BorderRadius.vertical(
top: Radius.circular(12),
),
color: Colors.white,
),
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Container(
width: 40,
height: 4,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(2),
),
),
),
],
),
),
),
The idea is good but it looks odd in some cases.
You could give a borderRadius to your first element in your list
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topRight: Radius.circular(index == 0 ? 15 : 0),
topLeft: Radius.circular(index == 0 ? 15 : 0),
),
),
)
Hope this helps someone
Try This, It's a Simple Solution
import 'package:flutter/material.dart';
class SliveR extends StatelessWidget {
const SliveR({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
SizedBox(
width: double.infinity,
child: Image.network(
'https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2700&q=80',
fit: BoxFit.cover,
height: MediaQuery.of(context).size.height * 0.35,
),
),
Align(
alignment: Alignment.topCenter,
child: Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(30)),
),
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(30)),
child: CustomScrollView(
anchor: 0.3,
slivers: [
SliverToBoxAdapter(
child: Container(
height: 900,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(40.0),
topRight: Radius.circular(40.0),
),
boxShadow: [
BoxShadow(
color: Colors.grey,
offset: Offset(0.0, 1.0), //(x,y)
blurRadius: 16.0,
),
],
),
child: const Center(
child: Text(
'Hello',
style: TextStyle(color: Colors.grey),
),
),
),
)
],
),
),
),
),
],
),
);
}
}
FlexibleSpaceBar(
title: CustomText(
text: "Renaissance Concourse Hotel",
textSize: kSubtitle3FontSize,
fontWeight: kBold),
centerTitle: true,
collapseMode: CollapseMode.pin,
background: Stack(
children: [
CachedNetworkImage(
imageUrl:
"url",
width: DeviceUtils.getWidth(context),
fit: BoxFit.cover,
placeholder: (context, url) => const Center(
child: CircularProgressIndicator(),
),
errorWidget: (context, url, error) =>
const Icon(Icons.error_rounded),
),
Positioned(
bottom: 50,
right: 0,
left: 0,
child: ContainerPlus(
color: kWhiteColor,
child: const SizedBox(
height: 20,
),
radius: RadiusPlus.only(
topLeft: kBorderRadiusValue10,
topRight: kBorderRadiusValue10,
),
),
)
],
))