SingleChildScrollView in Column Widget - flutter

The SingleChildScrollView is surrounded by the Flexible widget
because there's an overflow error. However, placing the Flexible
then makes the text too small!?
Please, how can I do this in a better way?
#override
Widget build(BuildContext context) {
return Scaffold(
// primary: false,
appBar: AppBar(
title: I10n.t('Playhouse'),
centerTitle: true,
automaticallyImplyLeading: false,
elevation: 0,
excludeHeaderSemantics: true,
),
endDrawer: const ScrapBookDrawer(),
body: SafeArea(
child: Column(
children: [
/// Submodule Name | Short Description
Flexible(
flex: 3,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Padding(
padding: const EdgeInsets.only(top: 4),
child: Text(
widget.subTask['subName'],
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
),
const Flexible(
child: Padding(
padding: EdgeInsets.only(top: 4),
child: Text(
'Submodule description',
),
),
),
],
),
),
Flexible(
flex: 5,
fit: FlexFit.tight,
child: Stack(
alignment: AlignmentDirectional.topCenter,
children: <Widget>[
/// Large Picture
Crop(
interactive: false,
backgroundColor: Colors.white,
dimColor: Colors.white,
controller: CropController(),
child: Image.memory(
base64.decode(
con.submodule['image'],
),
),
),
Positioned(
left: 0,
right: 0,
top: 200,
/// Rounded Container
child: Material(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(60),
topRight: Radius.circular(60),
),
child: Column(
children: <Widget>[
Container(
height: 225,
child: Column(
children: <Widget>[
/// Task Name and Number
Padding(
padding: const EdgeInsets.only(
top: 30, bottom: 20,),
child: Text(
widget.subTask['name'],
style: const TextStyle(
fontSize: 26,
fontWeight: FontWeight.bold,
),
),
),
/// Short Description or Title
Padding(
padding: const EdgeInsets.only(
top: 10, bottom: 30,),
child:
Text(widget.subTask['short_description']),
),
/// Long Description
Flexible(
child: SingleChildScrollView(
child:
Text(widget.subTask['long_description']),
),
),
],
),
),
],
),
),
),
],
),
),
],
),
),
);
}
In the next version below, I've gotten rid of the Positioned widget, but now (marked with red arrows) I don't see how to get rid of the whitespace?
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: I10n.t('Playhouse'),
centerTitle: true,
automaticallyImplyLeading: false,
elevation: 0,
excludeHeaderSemantics: true,
),
endDrawer: const ScrapBookDrawer(),
body: Stack(
children: <Widget>[
Crop(
interactive: false,
backgroundColor: Colors.white,
dimColor: Colors.white,
controller: CropController(),
child: Image.memory(
base64.decode(
con.submodule['image'],
),
),
),
SafeArea(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Flexible(
child: Text(
widget.subTask['subName'],
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
),
const Flexible(
child: Text(
'Submodule description',
),
),
]),
const Spacer(),
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.white),
child: Column(
children: <Widget>[
/// Task Name and Number
Padding(
padding: const EdgeInsets.only(
top: 30,
bottom: 20,
),
child: Text(
widget.subTask['name'],
style: const TextStyle(
fontSize: 26,
fontWeight: FontWeight.bold,
),
),
),
/// Short Description or Title
Padding(
padding: const EdgeInsets.only(
top: 10,
bottom: 30,
),
child: Text(widget.subTask['short_description']),
),
const SizedBox(height: 30),
Flexible(
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Text(widget.subTask['long_description']),
),
),
],
),
),
)
],
),
)
],
),
);
}

Knowing that the second one is the closest to what you need, to remove the whitespace you only need to remove the bottom paddings and the sizedBox, because you are the one controlling the whitespaces with those widgets and set a width size to your container with long and short description, like this:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: I10n.t('Playhouse'),
centerTitle: true,
automaticallyImplyLeading: false,
elevation: 0,
excludeHeaderSemantics: true,
),
endDrawer: const ScrapBookDrawer(),
body: Stack(
children: <Widget>[
Crop(
interactive: false,
backgroundColor: Colors.white,
dimColor: Colors.white,
controller: CropController(),
child: Image.memory(
base64.decode(
con.submodule['image'],
),
),
),
SafeArea(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Flexible(
child: Text(
widget.subTask['subName'],
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
),
const Flexible(
child: Text(
'Submodule description',
),
),
]),
const Spacer(),
Expanded(
child: Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.white),
child: Column(
children: <Widget>[
/// Task Name and Number
Padding(
padding: const EdgeInsets.only(
top: 30,
bottom: 20,
),
child: Text(
widget.subTask['name'],
style: const TextStyle(
fontSize: 26,
fontWeight: FontWeight.bold,
),
),
),
/// Short Description or Title
Padding(
padding: const EdgeInsets.only(
top: 10,
),
child: Text(widget.subTask['short_description']),
),
Flexible(
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Text(widget.subTask['long_description']),
),
),
],
),
),
)
],
),
)
],
),
);
}

Related

Flutter Stack Widget has Whitespace for some unknown reason

I'm still having trouble with Flutter's approach to laying out widgets.
There's this 'whitespace' that I would remove or cover (see red arrows).
How would I extend the 'image' up to the menu bar?
As you can see in the code below, I'm using a Stack widget.
I don't know what is making the 'whitespace' between the Stack widget and the appbar?? Possibly, it's due to the Crop widget (a third-party package). I'll look into that now, but decided to post this question anyway.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: I10n.t('Playhouse'),
centerTitle: true,
automaticallyImplyLeading: false,
elevation: 0,
excludeHeaderSemantics: true,
),
endDrawer: const ScrapBookDrawer(),
body: Stack(
children: <Widget>[
Crop(
interactive: false,
backgroundColor: Colors.white,
dimColor: Colors.white,
controller: CropController(),
child: Image.memory(
base64.decode(
con.submodule['image'],
),
),
),
SafeArea(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Flexible(
child: Text(
widget.subTask['subName'],
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
),
const Flexible(
child: Text(
'Submodule description',
),
),
]),
const Spacer(),
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.white),
child: Column(
children: <Widget>[
/// Task Name and Number
Padding(
padding: const EdgeInsets.only(
top: 30,
bottom: 20,
),
child: Text(
widget.subTask['name'],
style: const TextStyle(
fontSize: 26,
fontWeight: FontWeight.bold,
),
),
),
/// Short Description or Title
Padding(
padding: const EdgeInsets.only(
top: 10,
),
child: Text(widget.subTask['short_description']),
),
const SizedBox(height: 30),
Flexible(
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Text(widget.subTask['long_description']),
),
),
],
),
),
)
],
),
)
],
),
);
}
It seems it is actually due to Crop widget. It automatically determines the aspect ratio of your picture. You should manually set your aspect ratio by adding the aspectRatio parameter to your CropController, something like this:
Crop(
interactive: false,
backgroundColor: Colors.white,
dimColor: Colors.white,
controller: CropController(aspectRatio: 0.75),
child: Image.memory(
base64.decode(
con.submodule['image'],
),
),
)
In your case it seems that aspect ratio of ~0.75 works the best, play around with this to find your best value.

How do they work? : The Stack Widget and The Position Widget

Please, would you look at the attached screenshot and tell me where that band of off-white is coming from?? (red arrow.)
I want the rounded container to display text right down to the bottom of the screen--any text-overflow will simply be scrolled by the SingleChildScrollView widget, but the container just gets thinner and thinner while that block of grey just stays there??
Been working in Flutter since March of 2018, and Flutter's layout widgets are still a mystery!
Here is the code:
#override
Widget build(BuildContext context) {
return Scaffold(
// primary: false,
appBar: AppBar(
title: I10n.t('Playhouse'),
centerTitle: true,
automaticallyImplyLeading: false,
elevation: 0,
excludeHeaderSemantics: true,
),
endDrawer: const ScrapBookDrawer(),
body: SafeArea(
child: Column(
children: [
/// Submodule Name | Short Description
Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 10, top: 4),
child: Text(
'${widget.subTask['subName']} |',
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
),
),
const Expanded(
child: Padding(
padding: EdgeInsets.only(top: 4),
child: Text(
'Submodule description',
),
),
),
],
),
Stack(
alignment: AlignmentDirectional.topCenter,
children: <Widget>[
/// Large Picture
Container(
height: 500, // double.infinity,
child: Crop(
interactive: false,
backgroundColor: Colors.white,
dimColor: Colors.white,
controller: CropController(),
child: Image.memory(
base64.decode(
con.submodule['image'],
),
),
),
),
Positioned(
left: 0,
right: 0,
top: 300,
/// Rounded Container
child: Container(
height: 500,
decoration: const BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(60),
topRight: Radius.circular(60),
),
color: Colors.white,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
/// Task Name and Number
Padding(
padding: const EdgeInsets.only(top: 30, bottom: 20),
child: Text(
widget.subTask['name'],
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
),
/// Short Description or Title
Padding(
padding: const EdgeInsets.only(bottom: 20),
child: Text(widget.subTask['short_description']),
),
/// Long Description
Flexible(
flex: 300,
child: SingleChildScrollView(
child: Text(widget.subTask['long_description']),
),
),
],
),
),
)
],
),
],
),
),
);
}
I got rid of the white area by increasing height of the first Container in the Stack. Seems like it is just a default background that's not covered with anything.

Divider in AppBar not appearing

I am struggling to figure out why my divider in my app bar is not appearing. When I increase the height of the divider, I notice my widgets move up. I looked at similar issues and none have worked. My appBar consists of two columns and one row for the user profile information and information on their "Partner". I wanted to use the divider to separate the partner name and username from the win/loss ratio.strong text
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
return Scaffold(
appBar: AppBar(
backgroundColor: Color(0xFF2430346),
bottom: PreferredSize(
preferredSize: const Size.fromHeight(100.0),
child: Row(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.only(left:20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
_buildUserInfo(user),
Text(
"#username",
style: new TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Colors.white,
)
)
],
),
),
),
Padding(
padding: const EdgeInsets.only(right:70.0),
child: Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"My Partner",
style: new TextStyle(
fontSize: 24,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
Text(
"Dorian",
style: new TextStyle(
color: Colors.white,
),
),
Text(
"#Doetheman",
style: new TextStyle(
color: Colors.white,
),
),
// Mfer aint appearing
Padding(
padding: const EdgeInsets.only(left: 16, right: 16, top: 10, bottom: 10),
child: Divider(
height: 2.0,
color: Colors.white,
),
),
],
),
),
),
],
),
),
),
),
Widget _buildUserInfo(User user) {
return Column(
children: [
Avatar(
photoUrl: user.photoUrl,
radius: 40,
borderColor: Colors.black54,
borderWidth: 2.0,
),
const SizedBox(height: 8),
if (user.displayName != null)
Text(
user.displayName,
style: TextStyle(color: Colors.white),
),
const SizedBox(height: 8),
],
);
}
}
What I want it to look in view:
enter image description here
Instead of divider you can use container like this
Container(
alignment: Alignment.center,
width: 250,
height: 1,
color: Colors.black
),
Use IntrinsicWidth widget to wrap Column
IntrinsicWidth(
child: Column(
children: [
// ....
Divider(),
],
),
)

Flutter layout: how to expand widget vertically

I am struggling to understand how to layout my widget so that they are occupying the entire yellow space. More specifically I would like that the "hero' and the "boss" widget expand to occupy the available space on screen (excluding the keyboard)
My current code achieve the following result
I would like to get the following result below
Here is my code. I have used resizeToAvoidBottomInset: true to ensure the widget is resized with the keyboard popping up
Widget build(BuildContext context) {
return Container(
child: Scaffold(
resizeToAvoidBottomInset: true,
backgroundColor: kColorPrimary,
appBar: AppBar(
backgroundColor: kColorPrimaryLight,
title: Text('Time to Spell'),
),
body: ModalProgressHUD(
inAsyncCall: showSpinner,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(
child: Container(
height: 100,
color: Colors.amberAccent,
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
flex: 2,
child: Container(
color: Colors.blue,
child: Text(
result,
textAlign: TextAlign.center,
style: kTitleTextStyle,
),
),
),
Expanded(
flex: 1,
child: Container(
color: Colors.blue,
child: Text(
'Timer: 2:00',
textAlign: TextAlign.center,
),
),
),
],
),
Row(
children: <Widget>[
Expanded(
child: Container(
height: 279,
color: Colors.purple,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.white,
child: Text(
'Hero',
textAlign: TextAlign.center,
),
),
),
),
),
Expanded(
child: Container(
height: 279,
color: Colors.greenAccent,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.white,
child: Text(
'Boss',
textAlign: TextAlign.center,
),
),
),
),
),
],
),
],
),
),
),
],
),
),
))));
}
Try this. I have added comments as well. Feel free to comment if anything is not clear.
#override
Widget build(BuildContext context) {
return SafeArea(
child: Container(
color: Colors.amberAccent,
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
flex: 2,
child: Container(
color: Colors.blue,
child: Text(
"Click start",
textAlign: TextAlign.center,
),
),
),
Expanded(
flex: 1,
child: Container(
color: Colors.blue,
child: Text(
'Timer: 2:00',
textAlign: TextAlign.center,
),
),
),
],
),
Expanded(
child: Row(
children: <Widget>[
//child 1 of row takes half of the space
Expanded(
child: Column(
children: <Widget>[
//expanding the container to the bottom
Expanded(
child: Container(
//maximizing the width of the container
width: double.infinity,
color: Colors.purple,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.white,
child: Text(
'Hero',
textAlign: TextAlign.center,
),
),
),
),
),
],
),
),
//child 2 of row takes half of the space
Expanded(
child: Column(
children: <Widget>[
//expanding the container to the bottom
Expanded(
child: Container(
//maximizing the width of the container
width: double.infinity,
color: Colors.greenAccent,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.white,
child: Text(
'Boss',
textAlign: TextAlign.center,
),
),
),
),
),
],
),
),
],
),
),
],
),
),
);
}

how to make a list builder with a row

how do i create a list builder that's going to return a row like in the picture or a list builder that goes horizontal axis until it finds the end of the screen and then goes next line please see this Image
Use a GridView.builder() to dynamically render as user scrolls.
Below example modified from this: https://www.kindacode.com/article/flutter-gridview-builder-example/
List<String> data = ["1", "2", "3", "4", "5", "6"];
return GridView.builder(
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200,
childAspectRatio: 3 / 2,
crossAxisSpacing: 20,
mainAxisSpacing: 20),
itemCount: data.length,
itemBuilder: (BuildContext ctx, index) {
// Add your card/widget/grid element here
return Container(
alignment: Alignment.center,
child: Text(data[index]),
decoration: BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.circular(15),
),
);
},
);
check this out - it worked for me
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.teal,
body: SafeArea(
child: Row(
children: <Widget>[
SizedBox(width: 15),
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Card(
color: Colors.white,
child: Center(
child: Padding(
padding: EdgeInsets.all(75.0),
child: Text(
'1',
style: TextStyle(fontSize: 40, color: Colors.black),
),
),
),
),
Card(
color: Colors.white,
child: Center(
child: Padding(
padding: EdgeInsets.all(75.0),
child: Text(
'3',
style: TextStyle(fontSize: 40, color: Colors.black),
),
),
),
),
Card(
color: Colors.white,
child: Center(
child: Padding(
padding: EdgeInsets.all(75.0),
child: Text(
'5',
style: TextStyle(fontSize: 40, color: Colors.black),
),
),
),
),
],
),
SizedBox(width: 15),
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Card(
color: Colors.white,
child: Center(
child: Padding(
padding: EdgeInsets.all(75.0),
child: Text(
'2',
style: TextStyle(fontSize: 40, color: Colors.black),
),
),
),
),
Card(
color: Colors.white,
child: Center(
child: Padding(
padding: EdgeInsets.all(75.0),
child: Text(
'4',
style: TextStyle(fontSize: 40, color: Colors.black),
),
),
),
),
Card(
color: Colors.white,
child: Center(
child: Padding(
padding: EdgeInsets.all(75.0),
child: Text(
'6',
style: TextStyle(fontSize: 40, color: Colors.black),
),
),
),
),
],
),
],
),
)),
);
}
}