I will be sure to accept the correct answer to this question
Hello,
I am trying to create a layout similar to this one
My plan was to create a column with two expanded widgets, one with a flex of five and the other with a flex of five so that they both take half of the available space, inside the first expanded, I added a background Image, and a Stack widget. Inside the Stack widget, I put 2 text widgets and a listview, I wrapped the listview in a container and set it a height to avoid an unbounded constraint. Then I wrapped the listview inside a positioned widget and tried to nudge it below. I can position the widget later but all I care about is for the listview to be horizontal and overflow the parent container slightly, but nothing shows up when I run the given code.
Here is all the code under main.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String user = FirebaseAuth.instance.currentUser.email == null
? FirebaseAuth.instance.currentUser.phoneNumber
: FirebaseAuth.instance.currentUser.email;
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Column(
children: [
Expanded(
flex: 4,
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(35),
bottomRight: Radius.circular(35),
),
),
child: Stack(
alignment: AlignmentDirectional.center,
fit: StackFit.expand,
children: [
Text(
'1268',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w900,
fontSize: 60,
fontFamily: 'Rubik',
),
),
Text(
'Points Available',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w900,
fontSize: 15,
fontFamily: 'Rubik',
),
),
Positioned(
//TODO: Mess with this to make the listview overflow its parent container
top: 100,
child: Container(
height: 44,
color: Colors.white,
child: ListView(
children: [],
),
),
)
],
),
),
),
Expanded(
flex: 6,
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(35),
topRight: Radius.circular(35),
),
),
),
)
],
),
),
);
}
}
STEPS TO REPRODUCE
font_awesome_flutter: ^9.1.0
Under the pubspec.yaml and import the package in the main.dart
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
This is all you need to reproduce the error, you should see that nothing shows up, I am not sure why and I would love to finally be able to reproduce this layout
The problem is not with the ListView, but with Positioned.
Add left: 0 and right: 0 values to it.
Positioned (
left: 0,
right: 0,
top: 100,
child: ...
)
In this case, do not forget to explicitly specify the width of the child widget. For example: width: double.infinity,
Another option:
you can only add left: 0 to Positioned and not add right: 0, but then Positioned itself or its child widget must have a fixed width. For example: width: 200
Related
This is my emulator image which is showing the problem, I also use my mobile but it same condition
I having problems when my container height is more than 100. I can solve my problem by using SingleChildScrollView. But I want to scroll my only my list portion and that's why I don't wanna use SingleChildScrollView. Will my container size increase or container height increase show any render problem?
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import '../models/transaction.dart';
class TransactionList extends StatelessWidget {
final List<Transaction> transaction;
TransactionList(this.transaction);
#override
Widget build(BuildContext context) {
return Container(
height: 200,
// height: 300, when i use 300 then the problem occures.
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemBuilder: (ctx, index) {
return Card(
child: Row(
children: <Widget>[
Container(
margin: EdgeInsets.symmetric(horizontal: 15, vertical: 10),
decoration: BoxDecoration(
border: Border.all(
color: Colors.purple,
width: 2,
),
),
padding: EdgeInsets.all(10),
child: Text(
'\$${transaction[index].amount.toStringAsFixed(2)}',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.purple,
),
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
transaction[index].title,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
Text(
DateFormat.yMMMd().format(transaction[index].date),
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.grey[600],
),
)
],
)
],
),
);
},
itemCount: transaction.length,
),
);
}
}
Wrap your MainScreen with SingleChildScollView Widget
I have solved this problem. But now my whole screen is scrollable. but it's ok now. I will manage. I add SingleChildScroll... in my main. Now it's ok to use.
I am new to flutter learning a flutter UI build from youtube. While I am using the expanded widget, I found the output is not what I want, just wanna ask is there any way to limit the height of the expanded widget.
This is my current UI looks like.
SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Align(
alignment: Alignment.topRight,
child: Container(
alignment: Alignment.center,
height: 52,
width: 52,
decoration: BoxDecoration(
color: Color(0xFFF2BEA1),
shape: BoxShape.circle,
),
child: SvgPicture.asset("icons/icons/menu.svg"),
),
),
Text(
"\t\tMake Cents out of \n\t\tSolar",
style: Theme.of(context).textTheme.subtitle1!.copyWith(
fontWeight: FontWeight.w900,
fontSize: 38,
color: Colors.blueGrey[900]),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 5),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(29.5),
),
child: TextField(
decoration: InputDecoration(
hintText: "Search",
icon: SvgPicture.asset("icons/icons/search.svg"),
border: InputBorder.none,
),
),
),
),
Expanded(
child: GridView.count(
crossAxisCount: 2,
childAspectRatio: .85,
children: <Widget>[
CategoryCard(
title: "Promotion of the day",
svgSrc: "icons/icons/Hamburger.svg",
press: () {},
),
CategoryCard(
title: "Promotion of the day",
svgSrc: "icons/icons/Hamburger.svg",
press: () {},
),
],
),
),
Container(
padding: EdgeInsets.fromLTRB(20.0, 0, 0, 0),
child: Text(
"Solar Panel",
style: Theme.of(context).textTheme.subtitle1!.copyWith(
fontWeight: FontWeight.w900,
fontSize: 20,
color: Colors.black),
),
),
],
I wanna know is there any way to control the height of the expanded widget so that my container with text can connect right below the custom Category Card. Or should I use another widget instead of using the expanded widget?
By definition, the Expanded widget will fill up all the remaining screen space. If you instead want to use a set size, you can use a Container or SizedBox with their width and height parameters.
To get a better understanding of constraints in general, I suggest you check out this flutter documentation page all about constraints.
To set a minimum and maximum size (width and height) for a widget you can use ConstrainedBox widget, learn more about it here
You can't control the height of the Expanded widget. It takes all the space that is available on the screen. I suggest you to use SizedBox and explicitly provide the required height and set width as double.infinity.
I had same issue. I suggest ConstrainedBox widget to set minimum and maximum heights.
I'm trying to get the splash to match the same shape as my Container that has a FlatButton as its child.
When pressed, the splash currently fills a different shape as shown here:
My code for the widget is below:
import 'package:flutter/material.dart';
class RoundedButton extends StatelessWidget {
const RoundedButton( {this.buttonColor, this.buttonTitle, #required this.onPressed});
final Color buttonColor;
final String buttonTitle;
final Function onPressed;
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.symmetric(vertical: 16.0),
height: 42.0,
width: 200.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.0),
color: buttonColor,
),
child: FlatButton(
onPressed: onPressed,
child: Text(
buttonTitle,
style: TextStyle(
color: Colors.white
),
),
),
);
}
}
You can use ClipRRect widget which clips the underlying widget with rounded corners and by using borderRadius property and passing same radius as of parent widget ie, Container, ie, wrap the FlatButton with ClipRRect to achieve desired effect. Sample working code below:
body: Container(
margin: EdgeInsets.symmetric(vertical: 16.0),
height: 42.0,
width: 200.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.0),
color: Colors.red,
),
child: ClipRRect(
borderRadius: BorderRadius.circular(30),
child: FlatButton(
onPressed: () {
print('pressed');
},
child: Text(
'Send',
style: TextStyle(
color: Colors.white
),
),
),
)
),
Hope this answers your question.
Clipping allows me to draw only the part which I want to show. How do I remove the extra part which is not drawn but still takes up space?
The code
import 'package:flutter/material.dart';
class ClipTut extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
children: <Widget>[
ClipRect(
clipper: CustomRect(),
child: Container(
decoration: BoxDecoration(
border: Border.all(width: 4, color: Colors.black),
color: Colors.blue,
),
width: 200.0,
height: 200.0,
),
),
Container(
height: 200,
width: 100,
decoration: BoxDecoration(
border: Border.all(width: 4, color: Colors.black),
color: Colors.green,
),
)
],
),
),
);
}
}
class CustomRect extends CustomClipper<Rect> {
#override
Rect getClip(Size size) => Rect.fromLTRB(0, 0.0, size.width/2, size.height);
#override
bool shouldReclip(CustomRect oldClipper) => true;
}
My Solution
I had a similar problem recently (I needed to clip the image in half) and found this sample code on the flutter api site (use the other alignment points to change slicing behaviors) - no extra space left over:
ClipRect(
child: Align(
alignment: Alignment.topCenter,
heightFactor: 0.5,
child: Image.network(userAvatarUrl),
),
)
My base widget is a Column. The first element is a Container which has a BoxShadow. The second element is a ListView which builds several Card, depending on the context. If the scroll is 0 the shadow gets displayed. However when start scrolling, the card is "over" the shadow (higher z-index) and hides it.
unscrolled
scrolled
The shadow should stay always on top, over the Cards. How is this done?
EDIT
if you don't want container shadow to disappear on scroll remove the ScrollNotification and NotificationListener
There is a widget for that 😉
You can use ScrollNotification with NotificationListener. Try this;
Happy coding! 🤓
class TestPage extends StatefulWidget {
const TestPage({Key key}) : super(key: key);
#override
_TestPageState createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
double blurRadius = 10.0;
double spreadRadius = 1.0;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blueGrey,
title: Text('Title'),
),
body: Container(
width: Get.width,
height: Get.height,
child: Stack(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0).copyWith(
top: 62.0,
),
child: NotificationListener<ScrollNotification>(
// ignore: missing_return
onNotification: (scrollNotification) {
if (scrollNotification is ScrollStartNotification) {
setState(() {
blurRadius = 0.0;
spreadRadius = 0.0;
});
} else if (scrollNotification is ScrollEndNotification) {
setState(() {
blurRadius = 10.0;
spreadRadius = 1.0;
});
}
},
child: ListView.builder(
// controller: _controller,
itemCount: 10,
itemBuilder: (context, index) {
return Card(
child: Container(
width: Get.width * .8,
height: 100.0,
child: Center(
child: Text('child # index : $index'),
)),
);
},
),
),
),
Positioned(
top: 0,
left: 0,
right: 0,
child: Container(
width: Get.width,
height: 60.0,
margin: EdgeInsets.only(),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(20.0),
bottomRight: Radius.circular(20.0),
),
boxShadow: [
BoxShadow(
color: Colors.grey,
blurRadius: blurRadius,
spreadRadius: spreadRadius,
),
],
),
child: Center(
child: Text('TOP CONTAINER'),
),
),
),
],
),
),
);
}
}
According to your question, here is the concept of what is going wrong here.
The 1st child of Column is a Container with shadow. Shadow renders outside of the defined size. If you don't provide any spaces after this Container we won't be able to see the shadow. This space can be done by Container margin , SizedBox or wrapping our list with Padding. But now our main question is how we get shadow while index=0. I believe it is coming from ListChildren`. They contain upper spaces, that's why we can see only the 1st time.
On Ui render priority starts from bottom to Top.
How to solve this problem:
We can provide space at the bottom of our container or assign margin(not padding), or use a SizedBox after the container providing the same amount of height as shadow.
providing bottom margin on the container.
adding a SizedBox with height of shadow.
wrapping our list with Padding and providing top:.
In this image,
our shadow: white, background:amber.
Demo code:
import 'package:flutter/material.dart';
class ColumnWithContainerShadow extends StatelessWidget {
const ColumnWithContainerShadow({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.amber,
body: Column(
children: [
Container(
height: 50,
width: double.infinity,
////* we dont need margin if we have padding on ListView
// margin: EdgeInsets.only(bottom: 12),
decoration: BoxDecoration(
color: Colors.green,
boxShadow: [
BoxShadow(
offset: Offset(0, 12),
color: Colors.white,
)
],
),
child: Center(child: Text("Container A")),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 12),
child: ListView(
children: [
...List.generate(
333,
(index) => Container(
/// enable this margine and remove other spaces to see 1st child shadow.(shadow depend on children position)
// margin: EdgeInsets.only(top: 12),
height: 60,
color: Colors.deepPurple,
child: Text("$index"),
),
)
],
),
),
),
Container(
height: 50,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.green,
boxShadow: [
BoxShadow(
offset: Offset(0, 12),
color: Colors.white,
)
],
),
child: Text("Bottom Container"),
),
// Comment to close shadow
SizedBox(
height: 20,
)
],
),
);
}
}
Wrap this upper box in Material widget and provide an elevation.