Here is my code:
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.grey[900],
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => Navigator.of(context).pop(false),
),
),
backgroundColor: Colors.grey[900],
body: Visibility(
visible: questionLoaded,
child: Builder(builder: (context) {
return Wrap(
spacing: 8.0,
runSpacing: 4.0,
direction: Axis.horizontal,
children: [
Container(
width: double.infinity,
child: Text(
question!.question,
textAlign: TextAlign.center,
style: GoogleFonts.mukta(
textStyle: TextStyle(
color: Colors.amber,
fontSize: 24,
shadows: const [
Shadow(
color: Colors.white,
offset: Offset.zero,
blurRadius: 15)
]),
),
),
),
if (question?.answer1 != "")
RadioButton(
textStyle: TextStyle(color: Colors.white),
description: (question?.answer1)!,
value: "1",
groupValue: _decision,
onChanged: (value) => setState(
() => _decision = value!,
),
),
if (question?.answer2 != "")
RadioButton(
textStyle: TextStyle(color: Colors.white),
description: (question?.answer2)!,
value: "2",
groupValue: _decision,
onChanged: (value) => setState(
() => _decision = value!,
),
),
if (question?.answer3 != "")
RadioButton(
textStyle: TextStyle(color: Colors.white),
description: (question?.answer3)!,
value: "3",
groupValue: _decision,
onChanged: (value) => setState(
() => _decision = value!,
),
),
if (question?.answer4 != "")
RadioButton(
textStyle: TextStyle(color: Colors.white),
description: (question?.answer4)!,
value: "4",
groupValue: _decision,
onChanged: (value) => setState(
() => _decision = value!,
),
),
],
);
})),
);
This produces the following issue:
Any idea why and how can I fix it ?
Wrap your Text widget Flexible or Expanded widget.
Expnaded( child: Text( question!.question,....
If your text is wrapped in column then column should be wrapped expanded widget.
Expanded(
child: Column(
children: [
Text(
'datadatadatadatadatadata',
overflow: TextOverflow.ellipsis,
)
],
),
),
But if your text is wrapped in a row then your text should be wrapped expanded widget.
Row(
children: [
Expanded(
child: Text(
'datadatadatadatadatadata',
overflow: TextOverflow.ellipsis,
),
)
],
),
I want to be able to call either one of two different widgets based on the result of an if statement.
I am able to get a Text Widget to show two different answers based on the result of the first dropdown box, but I am not able to call another widget the same way ...
import 'package:flutter/material.dart';
class FilterPage extends StatefulWidget {
const FilterPage({Key? key}) : super(key: key);
#override
State<FilterPage> createState() => _FilterPageState();
}
class _FilterPageState extends State<FilterPage> {
String firstDropdownValue = 'Option A';
String secondDropdownValue = 'Option B';
#override
void dispose() {
super.dispose();
}
static const String _title = 'Filter Code Sample';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
Padding(
padding: EdgeInsets.all(4),
),
],
title: Column(
children: [
Text(
'Filter',
style: TextStyle(fontSize: 22, color: Colors.amberAccent),
),
],
),
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Text(
'What are the Options ?',
style: TextStyle(fontSize: 16, color: Colors.white),
),
/*
* This is the first dropdown that is called, This dropdown provides
* two possible options,
* */
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: firstDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
firstDropdownValue = newValue!;
});
},
items: <String>['Option A', 'Option B']
.map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
/*
* So this is the if Statement that works based upon the first
* drop down box's answer...
*
* The problem is I can not get the system to call another Drop down Butten
* Widget based on the answer of the first DropdownBox,
* However, i can get a Text Widget to print...
* */
Text((() {
if (firstDropdownValue == 'Option A') {
return "Option is Option A";
}
return "Option is Option B";
})()),
/*
* This is the second dropbox that I would like to be called if the
* previous statement is met instead of the Text Widget above...
*(DROPBOX 2)
* */
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: secondDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
secondDropdownValue = newValue!;
});
},
items: <String>[
'Option 1',
'Option 2',
'Option 3',
].map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
/*
* This is also drop box two, but this dropbox with these different
* options should be called when the if statement is not met ..
*(DROPBOX 2)
* */
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: secondDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
secondDropdownValue = newValue!;
});
},
items: <String>[
'Option 4',
'Option 5',
'Option 6',
].map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
],
),
),
),
);
}
}
The flow diagram is maybe easier to get the whole picture from.
You can use a if(condition)...[widgetA] else...[WidgetB] structure:
class _FilterPageState extends State<FilterPage> {
String firstDropdownValue = 'Option A';
String secondDropdownValue = 'Option B';
#override
void dispose() {
super.dispose();
}
static const String _title = 'Filter Code Sample';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
Padding(
padding: EdgeInsets.all(4),
),
],
title: Column(
children: [
Text(
'Filter',
style: TextStyle(fontSize: 22, color: Colors.amberAccent),
),
],
),
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Text(
'What are the Options ?',
style: TextStyle(fontSize: 16, color: Colors.white),
),
/*
* This is the first dropdown that is called, This dropdown provides
* two possible options,
* */
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: firstDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
firstDropdownValue = newValue!;
});
},
items: <String>['Option A', 'Option B']
.map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
if(firstDropDownValue)...[
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: secondDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
secondDropdownValue = newValue!;
});
},
items: <String>[
'Option 1',
'Option 2',
'Option 3',
].map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
] else ...[
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: secondDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
secondDropdownValue = newValue!;
});
},
items: <String>[
'Option 4',
'Option 5',
'Option 6',
].map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
]
],
),
),
),
);
}
}
Not the best approach for this probably, but you can use a Builder widget, inside it put your if statement and if you don't want to show your widget there, return SizedBox.shrink() instead (don't forget to setState((){}) so that the widget containing them both rebuilds them. But a better answer may be using Bloc or some other state management package. Or even ValueNotifiers and ValueListenableBuilders to update your UI only where it's needed.
One solution here is to use an inline if condition like this:
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: firstDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
firstDropdownValue = newValue!;
});
},
items: <String>['Option A', 'Option B']
.map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
firstDropdownValue == 'Option A'?
DropdownButton(/*first dropdown*/) :
DropdownButton(/*second dropdown*/),
The other is creating a Widget variable at the beginning of the build method and giving it a value before returning the Scaffold, then put the created variable as one of the Column children:
#override
Widget build(BuildContext context) {
Widget bottomDropdown;
if (firstDropdownValue == 'Option A'){
bottomDropdown = DropdownButton(/*first dropdown*/);
} else {
bottomDropdown = DropdownButton(/*second dropdown*/);
}
return Scaffold(
appBar: AppBar(
//...other code
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: firstDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
firstDropdownValue = newValue!;
});
},
items: <String>['Option A', 'Option B']
.map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
bottomDropdown,
You can use the Dart short if form: if ? then : else.
Since the only thing that changes are the dropdown options, you can dynamically change them without the need to use another widget.
import 'package:flutter/material.dart';
class FilterPage extends StatefulWidget {
const FilterPage({Key? key}) : super(key: key);
#override
State<FilterPage> createState() => _FilterPageState();
}
class _FilterPageState extends State<FilterPage> {
String firstDropdownValue = '';
String secondDropdownValue = 'Option B';
#override
void dispose() {
super.dispose();
}
static const String _title = 'Filter Code Sample';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
Padding(
padding: EdgeInsets.all(4),
),
],
title: Column(
children: [
Text(
'Filter',
style: TextStyle(fontSize: 22, color: Colors.amberAccent),
),
],
),
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Text(
'What are the Options ?',
style: TextStyle(fontSize: 16, color: Colors.white),
),
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: firstDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
firstDropdownValue = newValue!;
});
},
items: <String>['Option A', 'Option B']
.map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
if(firstDropdownValue.isNotEmpty)
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: secondDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
secondDropdownValue = newValue!;
});
},
items: <String>[
firstDropdownValue == 'Option A' ?
...['Option 1',
'Option 2',
'Option 3'] : ...['Option 5',
'Option 6',
'Option 7']
].map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
],
),
),
),
);
}
}
My app contains multiple cards with check box which makes wheather a work is done or not.
I want to create expansion panel list which contains multiple expansion panel. But when i want to give 16px spacing between each ExpansionPanels when it's not expanded but there is no option to do that. Can you please help.
If there is any other alternative to design this layout please help.
ExpansionPanelList(
// animationDuration: Duration(milliseconds: 10),
expandedHeaderPadding: EdgeInsets.only(top: 08),
elevation: 0,
children: [
ExpansionPanel(
isExpanded: _isOpen[0],
headerBuilder: (context, isOpen) {
return Padding(
padding: const EdgeInsets.symmetric(
vertical: 12, horizontal: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"0 Month",
style: ThemeText.s18w500Black,
),
Visibility(
visible: toggele0[0] && toggele0[1] && toggele0[2],
child: Row(
children: [
SvgPicture.asset(
"assets/icons/icon-vaccination-check.svg"),
SizedBox(
width: 6.5,
),
Text(
"Done",
style: ThemeText.s12w400Green2,
),
],
),
)
],
),
);
},
body: Column(
children: [
CheckboxListTile(
controlAffinity: ListTileControlAffinity.leading,
activeColor: HexColor(HexColors.textColorGreen2),
title: Text(
"Oral Polio Vaccine (2nd dose)",
style: ThemeText.s16w400Black.copyWith(
decoration: toggele0[0]
? TextDecoration.lineThrough
: TextDecoration.none),
),
subtitle: Text("Protects against Poliomyelitis"),
value: toggele0[0],
onChanged: (value) {
setState(() {
toggele0[0] = !toggele0[0];
});
}),
CheckboxListTile(
controlAffinity: ListTileControlAffinity.leading,
activeColor: HexColor(HexColors.textColorGreen2),
title: Text(
"Oral Polio Vaccine (2nd dose)",
style: ThemeText.s16w400Black.copyWith(
decoration: toggele0[1]
? TextDecoration.lineThrough
: TextDecoration.none),
),
subtitle: Text("Protects against Poliomyelitis"),
value: toggele0[1],
onChanged: (value) {
setState(() {
toggele0[1] = !toggele0[1];
});
}),
CheckboxListTile(
controlAffinity: ListTileControlAffinity.leading,
activeColor: HexColor(HexColors.textColorGreen2),
title: Text(
"Oral Polio Vaccine (2nd dose)",
style: ThemeText.s16w400Black.copyWith(
decoration: toggele0[2]
? TextDecoration.lineThrough
: TextDecoration.none),
),
subtitle: Text("Protects against Poliomyelitis"),
value: toggele0[2],
onChanged: (value) {
setState(() {
toggele0[2] = !toggele0[2];
});
})
],
)),
ExpansionPanel(
isExpanded: _isOpen[1],
headerBuilder: (context, isOpen) {
return Padding(
padding: const EdgeInsets.symmetric(
vertical: 12, horizontal: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"1 Month",
style: ThemeText.s18w500Black,
),
Visibility(
visible: toggele1[0] && toggele1[1] && toggele1[2],
child: Row(
children: [
SvgPicture.asset(
"assets/icons/icon-vaccination-check.svg"),
SizedBox(
width: 6.5,
),
Text(
"Done",
style: ThemeText.s12w400Green2,
),
],
),
)
],
),
);
},
body: Column(
children: [
CheckboxListTile(
controlAffinity: ListTileControlAffinity.leading,
activeColor: HexColor(HexColors.textColorGreen2),
title: Text(
"Oral Polio Vaccine (2nd dose)",
style: ThemeText.s16w400Black.copyWith(
decoration: toggele1[0]
? TextDecoration.lineThrough
: TextDecoration.none),
),
subtitle: Text("Protects against Poliomyelitis"),
value: toggele1[0],
onChanged: (value) {
setState(() {
toggele1[0] = !toggele1[0];
});
}),
CheckboxListTile(
controlAffinity: ListTileControlAffinity.leading,
activeColor: HexColor(HexColors.textColorGreen2),
title: Text(
"Oral Polio Vaccine (2nd dose)",
style: ThemeText.s16w400Black.copyWith(
decoration: toggele1[1]
? TextDecoration.lineThrough
: TextDecoration.none),
),
subtitle: Text("Protects against Poliomyelitis"),
value: toggele1[1],
onChanged: (value) {
setState(() {
toggele1[1] = !toggele1[1];
});
}),
CheckboxListTile(
controlAffinity: ListTileControlAffinity.leading,
activeColor: HexColor(HexColors.textColorGreen2),
title: Text(
"Oral Polio Vaccine (2nd dose)",
style: ThemeText.s16w400Black.copyWith(
decoration: toggele1[2]
? TextDecoration.lineThrough
: TextDecoration.none),
),
subtitle: Text("Protects against Poliomyelitis"),
value: toggele1[2],
onChanged: (value) {
setState(() {
toggele1[2] = !toggele1[2];
});
})
],
)),]),
I'm making a Terms and Conditions agreement and I want this sentence to be highlighted and clickable, when clicked it should take the user to another page in the app where they can read the agreement. I'm having trouble creating something that's both clickable and highlighted.
Here is my code:
CheckboxListTile(
value: checkboxValue,
onChanged: (val) {
if (checkboxValue == false) {
setState(() {
checkboxValue = true;
});
} else if (checkboxValue == true) {
setState(() {
checkboxValue = false;
});
}
},
subtitle: !checkboxValue
? Text(
'Required.',
style: TextStyle(color: Colors.red),
)
: null,
title: new Text(
'I agree to the Terms and Conditions.',
style: TextStyle(fontSize: 14.0),
),
controlAffinity: ListTileControlAffinity.leading,
activeColor: Colors.green,
),
```
Wrap your Text widget with a GestureDetector(). See code below
CheckboxListTile(
value: checkboxValue,
onChanged: (val) {
setState(() {
checkboxValue = !checkboxValue;
});
},
subtitle: !checkboxValue
? Text(
'Required.',
style: TextStyle(color: Colors.red),
)
: null,
title: GestureDetector(
onTap: (){
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context){
return Page();
},
),
);
},
child: Text(
'I agree to the Terms and Conditions.',
style: TextStyle(fontSize: 14.0),
),
),
controlAffinity: ListTileControlAffinity.leading,
activeColor: Colors.green,
)
Wrap your text with Inkwell or GestureDetector.
Sample code here:
GestureDetector(
onTap: () { },
child: Text(
"Sample Text",
style: TextStyle(
fontWeight: FontWeight.w800, color: Colors.blue
),
),
)