return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.vertical(
bottom: Radius.circular(25.0),
),
color: Theme.of(context).primaryColor,
),
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(
top: 25.0,
left: 20.0,
right: 20.0,
bottom: 10.0,
),
child: Row(
children: [
Expanded(
flex: 1,
child: Consumer<SessionModel>(
builder: (context, session, child) {
if (session.user.isNotEmpty &&
session.user['is_admin']) {
return CircleAvatar(
radius: 25,
backgroundColor:
const Color.fromARGB(64, 255, 255, 255),
child: IconButton(
onPressed: () => context
.push('/update/${data["animal_id"]}'),
icon: const Icon(
Icons.edit,
color: Colors.white,
),
),
);
} else {
return Container();
}
},
),
),
Expanded(
flex: 2,
child: Stack(
alignment: Alignment.center,
children: [
const CircleAvatar(
radius: 60,
backgroundColor: Colors.white,
child: CircleAvatar(
radius: 57,
foregroundImage:
AssetImage('assets/images/cow-example.png'),
),
),
if (!data['is_expired'])
Transform.translate(
offset: const Offset(35, -45),
child: Container(
width: 15.0,
height: 15.0,
decoration: BoxDecoration(
border: Border.all(
width: 1.0,
color: Colors.white,
),
shape: BoxShape.circle,
// if cow is inside red, if outside green
color: data['most_recent_out'] != null &&
data['most_recent_out']
['closed_at'] ==
null
? const Color(0xff1abc9c)
: const Color(0xffe74c3c),
),
),
)
],
),
),
Expanded(
flex: 1,
child: CircleAvatar(
radius: 25,
backgroundColor:
const Color.fromARGB(64, 255, 255, 255),
child: data['is_expired']
// Animal is sold or this deceased, nothing to do
? const Icon(
Icons.not_interested,
color: Colors.white,
)
: _buildHandleOutButton(
data['most_recent_out'],
),
),
),
],
),
),
Text(
_buildMostRecentOutLabel(data['most_recent_out']),
style: const TextStyle(
color: Color.fromARGB(170, 255, 255, 255),
fontWeight: FontWeight.w300,
fontSize: 12.0,
),
),
Padding(
padding: const EdgeInsets.only(
top: 10.0, left: 20.0, right: 20.0, bottom: 25.0),
child: SegmentedButton<int>(
style: ButtonStyle(
iconColor: const MaterialStatePropertyAll(Colors.white),
backgroundColor: MaterialStateProperty.resolveWith<Color>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return const Color(0xff1abc9c);
}
return const Color.fromARGB(28, 255, 255, 255);
},
),
foregroundColor:
const MaterialStatePropertyAll(Colors.white),
textStyle: const MaterialStatePropertyAll(
TextStyle(fontSize: 12),
),
side: const MaterialStatePropertyAll(
BorderSide(width: 0),
),
shape: MaterialStatePropertyAll(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
),
segments: const <ButtonSegment<int>>[
ButtonSegment<int>(
value: 1,
label: Text('Zdrava'),
icon: Icon(Icons.health_and_safety)),
ButtonSegment<int>(
value: 2,
label: Text('Bolesna'),
icon: Icon(Icons.vaccines)),
ButtonSegment<int>(
value: 3,
label: Text('Povrijeđena'),
icon: Icon(Icons.personal_injury)),
],
selected: {data['health']},
showSelectedIcon: false,
),
),
],
),
),
const SizedBox(
height: 5.0,
),
Padding(
padding: EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width * 0.01,
),
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_buildInfoPair(
const IconData((0xe0c8), fontFamily: 'MaterialIcons'),
'Ime',
data['name']),
_buildInfoPair(
const IconData(0xe3c5, fontFamily: 'MaterialIcons'),
'Pol',
data['sex'] == 1 ? 'muški' : 'ženski'),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_buildInfoPair(
const IconData(0xf06bb, fontFamily: 'MaterialIcons'),
'Starost',
"$oldMonths mj."),
if (data['passport'] != null)
_buildInfoPair(
const IconData(0xe1f2, fontFamily: 'MaterialIcons'),
'Pasoš',
data['passport'],
),
],
),
Row(
children: [
_buildInfoPair(
const IconData(0xe4f5, fontFamily: 'MaterialIcons'),
'Tag',
data['tag']),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_buildInfoPair(
const IconData(0xe038, fontFamily: 'MaterialIcons'),
'Dodato',
formatter.format(
DateTime.parse(data['created_at']).toLocal(),
),
),
if (data['is_expired'])
_buildInfoPair(
const IconData(0xe570, fontFamily: 'MaterialIcons'),
'Prodato',
formatter.format(
DateTime.parse(data['expired_at']).toLocal(),
),
),
],
),
const SizedBox(
height: 20,
),
],
),
),
),
],
);
}
Widget _buildInfoPair(IconData icon, String key, String value) {
return Expanded(
flex: 1,
child: Padding(
padding: EdgeInsets.symmetric(
vertical: 2.0,
horizontal: MediaQuery.of(context).size.width * 0.02,
),
child: Card(
elevation: 2,
color: Colors.white,
surfaceTintColor: Colors.white,
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 15.0, vertical: 15.0),
child: Row(
children: [
Column(
children: [
Padding(
padding: const EdgeInsets.only(
right: 15.0,
),
child: Icon(
icon,
color: const Color(0xff1abc9c),
size: 30.0,
),
),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
key,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 19.0,
),
),
const SizedBox(
height: 2.0,
),
Text(
value,
style: const TextStyle(
color: Color.fromARGB(255, 90, 90, 90),
fontSize: 12.0,
),
),
],
),
],
),
),
),
),
);
I want to make the black box fixed and the white box to be scrollable. I tried to wrap the Column in which is all content from below with Singlechildscrollview, but it doesn’t solve the problem. I also tried all combinations that I found on the Internet (added container to Column, replace Column with Stack…), but nothing helps. Do you have some solution for this?
2
Answers
The
SingleChildScrollView
you are using doesn’t have any sort of constraint on its height, so it doesn’t think it needs to enable scrolling. It’s your mainColumn
that is actually overflowing. To fix this, you’ll need to wrap thePadding
of theSingleChildScrollView
in anExpanded
widget, to tell that part of the content to fill the remaining vertical space. You also need to move theSizedBox(height: 5.0)
into the innerColumn
.Here’s your code rewritten as I described:
Your Problem is that your outer Column provides "unbound constraints" to its children so that they may size themselves as big as they want. But a SingleChildScrollView needs to have a fixed size so that its own child can be scrollable in its viewport. So either wrap your
SingleChildScrollView
inside of aSizedBox
to give it a fixed size, or you can wrap it with aFlexible
, orExpanded
widget to give it a fraction of the available free space of the column after laying out all fixed position non-flexible children.The following contains your slightly modified code so that it can be run everywhere without your state variables and data, etc (just make sure not to directly copy it):
Also i always recommend working with more helper methods, or even better working with more custom widgets for the separate sections of your widget tree(better performance than helper methods).
The bigger the build method, the more confusing it can get.