Reputation: 23005
I am trying to make a scrollable UI in flutter. I added a ListView
and then inside it a Stack
.
Below is my code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
var scaffoldKey = GlobalKey<ScaffoldState>();
class TestPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
drawer: Drawer(
child: ListView(
// Important: Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Text('Drawer Header'),
decoration: BoxDecoration(
color: Colors.blue,
),
),
ListTile(
title: Text('Item 1'),
onTap: () {
// Update the state of the app
// ...
// Then close the drawer
Navigator.pop(context);
},
),
ListTile(
title: Text('Item 2'),
onTap: () {
// Update the state of the app
// ...
// Then close the drawer
Navigator.pop(context);
},
),
],
),
),
body: Container(
height: double.infinity,
child: ListView(
shrinkWrap: true,
children: <Widget>[TestPageUI()],
),
),
key: scaffoldKey,
);
}
}
class TestPageUI extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return TestPageState();
}
}
class TestPageState extends State<TestPageUI> {
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height * .30,
width: double.infinity,
child: ClipPath(
clipper: ClippingClass(),
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * .30,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: AssetImage("assets/images/morning_image.png"))),
),
),
),
SafeArea(
child: Row(
children: <Widget>[
IconButton(
icon: Icon(
Icons.menu,
color: Colors.white,
),
onPressed: () {
print("clicked");
scaffoldKey.currentState.openDrawer();
},
),
Spacer(
flex: 2,
),
IconButton(
icon: Icon(
Icons.notifications,
color: Colors.white,
),
onPressed: () {},
),
],
),
),
Positioned(
top: MediaQuery.of(context).size.height * .2,
left: 0.0,
right: 0.0,
child: Align(
alignment: Alignment.center,
child: Container(
child: Text(
"Good Morning, Fred",
style: Theme.of(context)
.textTheme
.headline
.apply(color: Colors.white),
),
),
),
),
Positioned(
top: MediaQuery.of(context).size.height * .3,
left: 0.0,
right: 0.0,
child: Container(
margin: EdgeInsets.only(left: 10, right: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width * .22,
height: 100,
child: Column(
children: <Widget>[
Image.asset(
"assets/icons/car_service.png",
width: 48,
height: 48,
),
Container(
margin: EdgeInsets.all(5),
child: Text(
"ONE",
style: Theme.of(context)
.textTheme
.caption
.apply(color: Colors.black),
textAlign: TextAlign.center,
),
)
],
),
),
Spacer(
flex: 1,
),
Container(
width: MediaQuery.of(context).size.width * .22,
height: 100,
child: Column(
children: <Widget>[
Image.asset(
"assets/icons/car_service.png",
width: 48,
height: 48,
),
Container(
margin: EdgeInsets.all(5),
child: Text(
"FOUR",
style: Theme.of(context)
.textTheme
.caption
.apply(color: Colors.black),
textAlign: TextAlign.center,
),
)
],
),
),
],
),
),
),
Positioned(
top: MediaQuery.of(context).size.height * .54,
left: 0.0,
right: 0.0,
child: Container(
height: MediaQuery.of(context).size.height,
child: ListView.builder(
itemCount: 100,
itemBuilder: (BuildContext context, int index) {
return Container(
margin: EdgeInsets.only(bottom: 10, left: 10, right: 10),
child: _createAdvertisement(),
);
},
),
),
)
],
);
}
Widget _createAdvertisement() {
return Card(
elevation: 4.0,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
clipBehavior: Clip.antiAlias,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
FadeInImage.assetNetwork(
alignment: Alignment.topCenter,
placeholder: "https://picsum.photos/200",
image: "https://picsum.photos/200",
fit: BoxFit.fill,
width: double.infinity,
height: MediaQuery.of(context).size.height * .9 / 4,
),
],
),
);
}
@override
void initState() {
// TODO: implement initState
super.initState();
}
}
class ClippingClass extends CustomClipper<Path> {
@override
Path getClip(Size size) {
var path = Path();
path.lineTo(0.0, size.height);
path.quadraticBezierTo(
size.width / 4, size.height - 30, size.width / 2, size.height - 30);
path.quadraticBezierTo(size.width - (size.width / 4), size.height - 30,
size.width, size.height);
path.lineTo(size.width, 0.0);
path.close();
return path;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
There is an issue, below is the output
You can see that after the top background image, there is no content. The container holding the top background image is 30% of the height. whatever not within its area, will not get displayed. However if you increase its height, the rest of the content will get displayed as well as the background image size will increase.
What is wrong in here? How to display the content below the 30% height without an issue?
Also please note that I have another ListView
at the end of the code. I do not want this ListView
to scroll by its own, because the top ListView
does the job of scrolling the full page.
Upvotes: 2
Views: 2041
Reputation: 41
Use overflow:Overflow.visible
inside Stack()
like this-
Stack(overflow: Overflow.visible,
child:.....)
Upvotes: 1