after setstate ui is not changing in flutter - flutter

I am making a simple app and I want to show and hide reply of particular comment on button pressed of respective comment.
But the UI is not changing after the state is changing.
How to solve this issue ,suggest me an idea and thanks in advance.
The snapchatReply list have commentId and isShown field,I want to toggle based on isShown value.
toggleReply(String commentId){
for(int a=0;a<snapchatReply.length;a++){
print(snapchatReply.length);
if(commentId==snapchatReply[a]['commentId']){
if(snapchatReply[a]['isShown']==false){
setState(() {
snapchatReply[a]['isShown']=true;
});
}
else{
print("else");
setState(() {
snapchatReply[a]['isShown']=false;
});
}
}
}
print(snapchatReply);
}
It give following outpit:
2
I/flutter ( 8112): 2
I/flutter ( 8112): [{commentId: 6312c32e842444a707b6903f, isShown: true}, {commentId: 6318257479bcbf779df08816, isShown: false}]
I/flutter ( 8112): 4
I/flutter ( 8112): else
I/flutter ( 8112): 4
I/chatty ( 8112): uid=10154(com.example.fbclone) 1.ui identical 1 line
I/flutter ( 8112): 4
I/flutter ( 8112): [{commentId: 6312c32e842444a707b6903f, isShown: false}, {commentId: 6318257479bcbf779df08816, isShown: false}, {commentId: 6312c32e842444a707b6903f, isShown: true}, {commentId: 6318257479bcbf779df08816, isShown: false}]
Full code:
ListView.builder(
itemCount: widget.snapshot.comments.length,
padding: EdgeInsets.only(bottom: 20),
scrollDirection: Axis.vertical,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (context, j) {
commentLike.add({"index":j,
"like":widget.snapshot.comments[j].commentlikes.length,
"commentId":widget.snapshot.comments[j].id});
snapchatReply.add({
"commentId":widget.snapshot.comments[j].id,
"isShown":false
});
return SingleChildScrollView(
child: Container(
width: MediaQuery.of(context).size.width-150,
child: Card(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
IconButton(
iconSize: 50,
onPressed: () {},
icon: CircleAvatar(
radius: 80,
backgroundImage: NetworkImage(
widget.snapshot.comments![j].user.profile),
)),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: MediaQuery.of(context).size.width - 100,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.grey[300]),
padding: EdgeInsets.all(8),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.snapshot.comments![j].user.name,
style: TextStyle(
fontSize: 18,
color: Colors.black,
fontWeight: FontWeight.bold),
),
Text(widget.snapshot.comments![j].commentText),
// Text(widget.snapshot.comments![j].commentText,
// style: TextStyle(
// fontSize: 16,
// color: Colors.grey[700])),
])),
Row(
children: [
Text(convertToAgo(
widget.snapshot.comments![j].commentAt)),
TextButton(
onPressed: () {
likeComment(
widget.snapshot.comments![j].id,
widget.postId,
);
},
child: Text("Like", style: myStyle)),
TextButton(
onPressed: () {
print("isReply");
setState(() {
isReply=true;
commentId=widget.snapshot.comments![j].id;
userName=widget.snapshot.comments![j].user.name;
});
},
child: Text("Reply", style: myStyle),
),
TextButton(onPressed: (){
toggleReply(widget.snapshot.comments![j].id);
},
child: Text("view reply"),
),
if(widget.snapshot.comments![j].commentlikes!.length!=0)...[
if(commentLike[j]['like']!=0)...[
Text(totalLikes(commentLike[j]['like']))
]
],
// Text(totalLikes(widget.snapshot.comments![j].commentlikes!.length),
// style: myStyle),
],
),
reply(snapchatReply: snapchatReply, snapshot: widget.snapshot.comments[j])
],
),
]),
),
),
);
}),
reply.dart
import 'package:flutter/material.dart';
class reply extends StatefulWidget {
const reply({Key? key,required this.snapchatReply,required this.snapshot}) : super(key: key);
final snapshot;
final snapchatReply;
#override
State<reply> createState() => _replyState();
}
class _replyState extends State<reply> {
#override
Widget build(BuildContext context) {
return Column(
children:[
for (int k = 0;k < widget.snapshot.reply!.length;k++) ...[
for(int l=0;l<widget.snapchatReply.length;l++) ...[
if(widget.snapchatReply[l]["commentId"]==widget.snapshot.id && widget.snapchatReply[l]["isShown"]==true) ...[
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
IconButton(
iconSize: 50,
onPressed: () {},
icon: CircleAvatar(
radius: 80,
backgroundImage: NetworkImage(widget.snapshot.reply![k].user.profile),
)),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: MediaQuery.of(context).size.width -200,
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(10),
color: Colors.grey[300]),
padding: EdgeInsets.all(8),
child: Column(
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
widget.snapshot
.reply![k].user.name,
style: TextStyle(
fontSize: 18,
color: Colors.black,
fontWeight:
FontWeight.bold),
),
RichText(
text: TextSpan(
style: TextStyle( fontSize:18,color:Colors.grey[700],fontWeight: FontWeight.bold),
children: <TextSpan>[
TextSpan(text:widget.snapshot.user.name + " ", style: TextStyle(color: Colors.black)),
TextSpan(text:widget.snapshot.reply[k].replyText,style: TextStyle(fontWeight: FontWeight.normal) ),
],
),
),
])),
])
])
]
]
]
],
);
}
}

You can not use snapchatReply[a]['isShown'] to change variable inside map inside the list, you should pass new variable to it, try this:
toggleReply(String commentId) {
for (int a = 0; a < snapchatReply.length; a++) {
print(snapchatReply.length);
if (commentId == snapchatReply[a]['commentId']) {
if (snapchatReply[a]['isShown'] == false) {
setState(() {
snapchatReply[a] = {
'commentId': snapchatReply[a]['commentId'],
'isShown': true
};
});
} else {
print("else");
setState(() {
snapchatReply[a] = {
'commentId': snapchatReply[a]['commentId'],
'isShown': false
};
});
}
}
}
}
your main issue is every time you call setstate this:
snapchatReply.add({
"commentId":widget.snapshot.comments[j].id,
"isShown":false
});
will call, so this is cause doubling you list length every time, what you need to do is, rest you list before it. so try call snapchatReply = []; before returning your ListView.builder.

Related

Insert value textfield to format Map in flutter when get loop

how to insert value textfield controller in looping condition, I want to create new textfield when the button 'Tambah' have presse, but there is problem when I check criemHistories value, this is my code
class _TestingState extends State<Testing> {
int textFieldCount = 1;
List<Map<String, String>> crimeHistories = [];
List<Widget> buildTextFields() {
List<Widget> textFields = [];
for (int i = 0; i < textFieldCount; i++) {
TextEditingController pengadilanC = TextEditingController();
TextEditingController polresC = TextEditingController();
Map<String, String> crimeHistory = {
"court": pengadilanC.text,
"police_department": polresC.text,
};
crimeHistories.add(crimeHistory);
textFields.add(Column(
children: [
Container(
margin: EdgeInsets.only(top: 20),
child: Column(
children: [
Row(
children: [
Expanded(
flex: 3,
child: RichText(
text: TextSpan(
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
),
text: 'Pengadilan Negeri',
),
),
),
Expanded(
flex: 7,
child: Align(
alignment: Alignment.center,
child: TextField(
controller: pengadilanC,
onChanged: (value) {
crimeHistory["court"] = value;
},
),
),
),
],
),
],
),
),
Container(
margin: EdgeInsets.only(top: 20),
child: Column(
children: [
Row(
children: [
Expanded(
flex: 3,
child: RichText(
text: TextSpan(
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
),
text: 'Polres/Polsek',
),
),
),
Expanded(
flex: 7,
child: Align(
alignment: Alignment.center,
child: TextField(
controller: polresC,
onChanged: (value) {
crimeHistory["police_department"] = value;
},
),
),
),
],
),
],
),
),
],
));
// Masukkan Map ke dalam list crimeHistories
}
return textFields;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Column(children: buildTextFields()),
ElevatedButton(
child: Text('Tambah'),
onPressed: () {
textFieldCount++;
},
),
ElevatedButton(
child: Text('Remove'),
onPressed: () {
setState(() {
textFieldCount--;
});
},
),
ElevatedButton(
child: Text("Simpan"),
onPressed: () {
print(crimeHistories);
},
),
],
),
);
}
}
this code can run and add form textfield properly, but when I check crimeHistories value, there is 3 data list, how come it's can be happend? and how to solve it?

Why is my flutter widgets not working when in a different state management

I bought an online template app and i am trying to hardcode my email and password credentials in my flutter frontend because i don't have access to the backend api yet to change from email/password auth to phone auth, so i want to force code the logic into my flutter widget.
This means i am trying to implement the onPressed: () { controller.login(); }, function on a login button to get me to the home screen with my customized widget.
The original code given to me works fine when i hardcode the credentials in the text form field but when i hardcode the text form field in my customized widget and use same onPressed: () { controller.login(); }, function it don't work.
I want to know if it's because of i'm in a different state management or there's something i'm failing to do.
I will give the original code and my customized UI code in the snippets for comparison.
PS: i even tried to use same text form field in my widget but hide it with Visibility() in flutter. When i use Visibility() in the original code, onPressed: () { controller.login(); }, works but when i use it in my customized widget, it doest.
How do work around this? If you need more clarification, i am willing to offer. Thanks.
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../../../common/helper.dart';
import '../../../../../common/ui.dart';
import '../../../../models/setting_model.dart';
import '../../../../routes/app_routes.dart';
import '../../../../services/settings_service.dart';
import '../../../global_widgets/block_button_widget.dart';
import '../../../global_widgets/circular_loading_widget.dart';
import '../../../global_widgets/text_field_widget.dart';
import '../../controllers/auth_controller.dart';
class LoginView extends GetView<AuthController> {
final Setting _settings = Get.find<SettingsService>().setting.value;
#override
Widget build(BuildContext context) {
controller.loginFormKey = new GlobalKey<FormState>();
return Visibility(
visible: false,
child: WillPopScope(
onWillPop: Helper().onWillPop,
child: Scaffold(
appBar: AppBar(
title: Text(
"Login".tr,
style: Get.textTheme.headline6
.merge(TextStyle(color: context.theme.primaryColor)),
),
centerTitle: true,
backgroundColor: Get.theme.colorScheme.secondary,
automaticallyImplyLeading: false,
elevation: 0,
),
body: Form(
key: controller.loginFormKey,
child: ListView(
primary: true,
children: [
Stack(
alignment: AlignmentDirectional.bottomCenter,
children: [
Container(
height: 180,
width: Get.width,
decoration: BoxDecoration(
color: Get.theme.colorScheme.secondary,
borderRadius:
BorderRadius.vertical(bottom: Radius.circular(10)),
boxShadow: [
BoxShadow(
color: Get.theme.focusColor.withOpacity(0.2),
blurRadius: 10,
offset: Offset(0, 5)),
],
),
margin: EdgeInsets.only(bottom: 50),
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
children: [
Text(
_settings.salonAppName,
style: Get.textTheme.headline6.merge(TextStyle(
color: Get.theme.primaryColor, fontSize: 24)),
),
SizedBox(height: 5),
Text(
"Welcome to the best salon service system!".tr,
style: Get.textTheme.caption.merge(
TextStyle(color: Get.theme.primaryColor)),
textAlign: TextAlign.center,
),
// Text("Fill the following credentials to login your account", style: Get.textTheme.caption.merge(TextStyle(color: Get.theme.primaryColor))),
],
),
),
),
Container(
decoration: Ui.getBoxDecoration(
radius: 14,
border:
Border.all(width: 5, color: Get.theme.primaryColor),
),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(10)),
child: Image.asset(
'assets/icon/icon.png',
fit: BoxFit.cover,
width: 100,
height: 100,
),
),
),
],
),
Obx(() {
if (controller.loading.isTrue)
return CircularLoadingWidget(height: 300);
else {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Visibility(
visible: false,
maintainState: true,
child: TextFieldWidget(
labelText: "Email Address".tr,
hintText: "johndoe#gmail.com".tr,
initialValue: 'salon#demo.com',
onSaved: (input) =>
controller.currentUser.value.email = input,
validator: (input) => !input.contains('#')
? "Should be a valid email".tr
: null,
iconData: Icons.alternate_email,
),
),
Obx(() {
return Visibility(
visible: false,
maintainState: true,
child: TextFieldWidget(
labelText: "Password".tr,
hintText: "••••••••••••".tr,
initialValue: '123456',
onSaved: (input) =>
controller.currentUser.value.password = input,
validator: (input) => input.length < 3
? "Should be more than 3 characters".tr
: null,
),
);
}),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () {
Get.toNamed(Routes.FORGOT_PASSWORD);
},
child: Text("Forgot Password?".tr),
),
],
).paddingSymmetric(horizontal: 20),
BlockButtonWidget(
onPressed: () {
controller.login();
},
color: Get.theme.colorScheme.secondary,
text: Text(
"Login".tr,
style: Get.textTheme.headline6.merge(
TextStyle(color: Get.theme.primaryColor)),
),
).paddingSymmetric(vertical: 10, horizontal: 20),
TextButton(
onPressed: () {
//Get.toNamed(Routes.REGISTER);
},
child: Text("You don't have an account?".tr),
).paddingOnly(top: 20),
GestureDetector(
onTap: () {
Get.toNamed(Routes.SETTINGS_LANGUAGE);
},
child: Text(
Get.locale.toString().tr,
textAlign: TextAlign.center,
),
),
],
);
}
}),
],
),
),
),
),
);
}
}
THIS IS THE ORIGINAL WIDGET CODE
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../../routes/app_routes.dart';
import '../../../global_widgets/circular_loading_widget.dart';
import '../../../global_widgets/text_field_widget.dart';
import '../../controllers/auth_controller.dart';
import 'login_view.dart';
import 'pin_number.dart';
import 'keyboard_number.dart';
class PinScreen extends StatefulWidget {
const PinScreen({Key key}) : super(key: key);
#override
State<PinScreen> createState() => _PinScreenState();
}
class _PinScreenState extends State<PinScreen> {
List<String> currentPin = ["", "", "", ""];
TextEditingController pinOneController = TextEditingController();
TextEditingController pinTwoController = TextEditingController();
TextEditingController pinThreeController = TextEditingController();
TextEditingController pinFourController = TextEditingController();
var outlineInputBorder = OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.transparent),
);
int pinIndex = 0;
#override
Widget build(BuildContext context) {
final controller = Get.find<AuthController>();
controller.loginFormKey = new GlobalKey<FormState>();
return Form(
key: controller.loginFormKey,
child: SafeArea(
child: Column(
children: [
buildExitButton(),
Obx(() {
if (controller.loading.isTrue)
return CircularLoadingWidget(height: 300);
else {
return Expanded(
child: Container(
alignment: Alignment(0, 0.5),
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
buildSecurityText(),
SizedBox(height: 20.0),
buildPinRow(),
SizedBox(height: 10.0),
buildNumberPad(),
SizedBox(height: 20.0),
Visibility(
visible: false,
maintainState: true,
child: TextFieldWidget(
labelText: "Email Address".tr,
hintText: "johndoe#gmail.com".tr,
initialValue: 'salon#demo.com',
validator: (input) => !input.contains('#')
? "Should be a valid email".tr
: null,
iconData: Icons.alternate_email,
),
),
Obx(() {
return Visibility(
visible: false,
maintainState: true,
child: TextFieldWidget(
labelText: "Password".tr,
hintText: "••••••••••••".tr,
initialValue: '123456',
validator: (input) => input.length < 3
? "Should be more than 3 characters".tr
: null,
iconData: Icons.lock_outline,
keyboardType: TextInputType.visiblePassword,
suffixIcon: IconButton(
onPressed: () {
controller.hidePassword.value =
!controller.hidePassword.value;
},
color: Theme.of(context).focusColor,
icon: Icon(controller.hidePassword.value
? Icons.visibility_outlined
: Icons.visibility_off_outlined),
),
),
);
}),
Container(
child: new RichText(
text: new TextSpan(
children: [
new TextSpan(
recognizer: TapGestureRecognizer()
..onTap = () {
// Get.toNamed(Routes.REGISTER);
},
text: 'Forgot Pin ?',
style: new TextStyle(
color: Color(0xff3498DB),
fontSize: 14,
fontWeight: FontWeight.w500),
),
],
),
),
),
SizedBox(height: 20.0),
MaterialButton(
onPressed: () {
controller.login();
},
color: Color(0xff34495E),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.18),
),
padding: EdgeInsets.symmetric(
horizontal: 30, vertical: 10),
minWidth: double.infinity,
child: Text(
'Next',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w600),
),
),
SizedBox(height: 32.0),
],
),
),
);
}
})
],
),
),
);
}
buildNumberPad() {
return Expanded(
child: Container(
alignment: Alignment.bottomCenter,
child: Padding(
padding: const EdgeInsets.only(bottom: 12),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
KeyboardNumber(
n: 1,
onPressed: () {
pinIndexSetup("1");
},
),
KeyboardNumber(
n: 2,
onPressed: () {
pinIndexSetup("2");
},
),
KeyboardNumber(
n: 3,
onPressed: () {
pinIndexSetup("3");
},
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
KeyboardNumber(
n: 4,
onPressed: () {
pinIndexSetup("4");
},
),
KeyboardNumber(
n: 5,
onPressed: () {
pinIndexSetup("5");
},
),
KeyboardNumber(
n: 6,
onPressed: () {
pinIndexSetup("6");
},
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
KeyboardNumber(
n: 7,
onPressed: () {
pinIndexSetup("7");
},
),
KeyboardNumber(
n: 8,
onPressed: () {
pinIndexSetup("8");
},
),
KeyboardNumber(
n: 9,
onPressed: () {
pinIndexSetup("9");
},
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
width: 60.0,
child: MaterialButton(
onPressed: null,
child: SizedBox(),
),
),
KeyboardNumber(
n: 0,
onPressed: () {
pinIndexSetup("0");
},
),
Container(
width: 60.0,
child: MaterialButton(
onPressed: () {
clearPin();
},
height: 60.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(60.0),
),
child: Image.asset(
'assets/icon/clear-symbol.png',
),
),
)
],
),
],
),
),
),
);
}
clearPin() {
if (pinIndex == 0)
pinIndex = 0;
else if (pinIndex == 4) {
setPin(pinIndex, "");
currentPin[pinIndex - 1] = "";
pinIndex--;
} else {
setPin(pinIndex, "");
currentPin[pinIndex - 1] = "";
pinIndex--;
}
}
pinIndexSetup(String text) {
if (pinIndex == 0)
pinIndex = 1;
else if (pinIndex < 4) pinIndex++;
setPin(pinIndex, text);
currentPin[pinIndex - 1] = text;
String strPin = "";
currentPin.forEach((e) {
strPin += e;
});
if (pinIndex == 4) print(strPin);
}
setPin(int n, String text) {
switch (n) {
case 1:
pinOneController.text = text;
break;
case 2:
pinTwoController.text = text;
break;
case 3:
pinThreeController.text = text;
break;
case 4:
pinFourController.text = text;
break;
}
}
buildExitButton() {
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: MaterialButton(
onPressed: () {
Navigator.pop(context);
},
height: 50.0,
minWidth: 50.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50.0),
),
child: Icon(
Icons.clear,
color: Colors.black54,
),
),
),
],
);
}
buildSecurityText() {
return Column(
children: [
Align(
alignment: Alignment.topLeft,
child: Text(
'Enter PIN',
style: TextStyle(
color: Color(0xff151515),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
SizedBox(
height: 12,
),
Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(right: 80),
child: Text(
'Enter 4 digit PIN to access your account ',
style: TextStyle(
color: Color(0xff151515),
fontSize: 14,
fontWeight: FontWeight.w500,
fontStyle: FontStyle.normal,
),
),
),
),
],
);
}
buildPinRow() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
PINNumber(
outlineInputBorder: outlineInputBorder,
textEditingController: pinOneController,
),
PINNumber(
outlineInputBorder: outlineInputBorder,
textEditingController: pinTwoController,
),
PINNumber(
outlineInputBorder: outlineInputBorder,
textEditingController: pinThreeController,
),
PINNumber(
outlineInputBorder: outlineInputBorder,
textEditingController: pinFourController,
),
],
);
}
}
THIS IS MY CUSTOMIZED WIDGET TREE/CODE

Text overflow flutter

I have the next widget, which is rendered with overflow. I have tried to solve, but i don't know. Can anyone help me? The aim is to do a custom card inside listview.
I have tried to wrap with expanded buth then, the error is referenced with constraints.
import 'package:flutter/material.dart';
import '../../shared/AppTheme.dart';
class ComandaScreen extends StatefulWidget {
const ComandaScreen({Key? key}) : super(key: key);
#override
State<ComandaScreen> createState() => _ComandaScreenState();
}
class _ComandaScreenState extends State<ComandaScreen> {
bool expanded = false;
int unidades = 0;
final List<Map<String, dynamic>> _items = List.generate(
10, (index) => {'id': index, 'Nombre': 'Nuggets $index',
'isExpanded': false, "unidades": 8});
#override
Widget build(BuildContext context) {
final ButtonStyle flatButtonStyle = TextButton.styleFrom(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(4.0)),
),
);
return Scaffold(
appBar: AppBar(
title: const Text('Comanda'),
backgroundColor: AppTheme.backgroundColor,
foregroundColor: AppTheme.primaryTextColor,
elevation: 0,
),
body: SingleChildScrollView(
child: ExpansionPanelList(
elevation: 3,
// expandedHeaderPadding: const EdgeInsets.all(10),
expansionCallback: (index, isExpanded) {
setState(() {
_items[index]['isExpanded'] = !isExpanded;
});
},
animationDuration: const Duration(milliseconds: 200),
children: _items
.map(
(item) => ExpansionPanel(
canTapOnHeader: true,
// backgroundColor: item['isExpanded'] == true ? Colors.cyan[100] : Colors.white,
headerBuilder: (context, isExpanded) {
return Container(
margin: const EdgeInsets.all(10),
child: Row(children: [
const CircleAvatar(
child: Text(
'1',
textAlign: TextAlign.center,
)),
const SizedBox(
width: 10,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Nuggets',
style: TextStyle(color: Colors.black, fontWeight: FontWeight.w600),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: const [
Text(
'Unidades: ${7}',
style: TextStyle(color: Colors.black),
),
Text(
'Pendientes: 400',
style: TextStyle(color: Colors.black),
),
],
),
const SizedBox(
width: 20,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(
'Precio: 10 €',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(color: Colors.black),
),
Text(
'Total: 70 €',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(color: Colors.black),
),
],
),
],
),
],
),
),
]),
);
},
body: ButtonBar(
alignment: MainAxisAlignment.spaceAround,
buttonHeight: 52.0,
buttonMinWidth: 90.0,
children: <Widget>[
TextButton(
style: flatButtonStyle,
onPressed: () {
setState(() {
item['unidades'] += 1;
});
},
child: Column(
children: const <Widget>[
Icon(
Icons.add,
color: AppTheme.grismedio,
),
// Padding(
// padding: EdgeInsets.symmetric(vertical: 2.0),
// ),
// Text('Más'),
],
),
),
TextButton(
style: flatButtonStyle,
onPressed: () {
setState(() {
item['unidades'] -= 1;
});
},
child: Column(
children: const <Widget>[
Icon(
Icons.remove,
color: AppTheme.grismedio,
),
// Padding(
// padding: EdgeInsets.symmetric(vertical: 2.0),
// ),
// Text('Menos'),
],
),
),
TextButton(
style: flatButtonStyle,
onPressed: () {},
child: Column(
children: const <Widget>[
Icon(
Icons.edit_outlined,
color: AppTheme.grismedio,
),
// Padding(
// padding: EdgeInsets.symmetric(vertical: 2.0),
// ),
// Text('Editar'),
],
),
),
TextButton(
style: flatButtonStyle,
onPressed: () {},
child: Column(
children: const <Widget>[
Icon(
Icons.delete_outline_outlined,
color: AppTheme.grismedio,
),
// Padding(
// padding: EdgeInsets.symmetric(vertical: 2.0),
// ),
// Text('Eliminar'),
],
),
),
TextButton(
style: flatButtonStyle,
onPressed: () {},
child: Column(
children: const <Widget>[
Icon(
Icons.card_giftcard_outlined,
color: AppTheme.grismedio,
),
// Padding(
// padding: EdgeInsets.symmetric(vertical: 2.0),
// ),
// Text('Invitar'),
],
),
)
],
),
isExpanded: item['isExpanded'],
),
)
.toList(),
// Card_lineaComanda(flatButtonStyle),
),
),
);
}
}
I 've edited the code to show all screen widget.
Image of result of code before:
For desktop applications, you can prevent the resize with breakpoint, so the error won't happen. In the pubsec.yaml file, add the following dependency.
window_size:
git:
url: https://github.com/google/flutter-desktop-embedding.git
path: plugins/window_size
And in your main method before runapp add this code with min-width and min-height below which the app won't resize.
const double desktopMinWidth = 800.0;
const double desktopMinHeight = 600.0;
if (Platform.isMacOS || Platform.isWindows) {
setWindowMinSize(const Size(desktopMinWidth, desktopMinHeight));
setWindowMaxSize(Size.infinite);
}
Note: Once done restart your app.
For mobile, it is entirely a different case. You might need to restructure the design

How to Get the Number of Pages in Pageview to be used in a line indicator in Flutter?

May i ask for help on how to get the number of pages inside a pageview,
similar to listview you can get the number of list via listview.length, but for pageview there is no pageview.length property that i can use,
i tried using pageview.builder but i couldnt initiate the data as a list showig an issue that i need to initiate it as an initializers?,
please help me figure it out
i need the data inside the pageview to be used inside the _lineprogressindicator, to show how many are the questionaires inside to make an indicator
here is my code
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:survey/content/thankyou.dart';
import 'package:survey/widgets/animations.dart';
import 'package:survey/widgets/buttonstyle.dart';
import 'package:survey/widgets/widgetlist.dart';
class questionaires extends StatefulWidget {
#override
_questionairesState createState() => _questionairesState();
}
class _questionairesState extends State<questionaires> {
TextStyle conqueststyle = TextStyle(
fontSize: 15, fontWeight: FontWeight.bold, color: Colors.indigo);
TextStyle questionstyle = TextStyle(
fontSize: 17,
fontWeight: FontWeight.bold,
);
String titletop = 'Post Visit Patient Satisfaction';
String q1 = "Sample Question HERE";
String q2 = "Sample Question HERE";
String q3 = "Sample Question HERE";
String q4 = "Sample Question HERE";
int percentagenum = 0;
int _currValue = 1;
bool _loading;
double _progress;
final _texteditingcontroller = TextEditingController();
final _pageController = PageController(initialPage: 0, keepPage: true);
var _currentpage = 0;
List answernumbers = ["5", "4", "3", "2", "1"];
List currentselectedvalue = [];
List usingCollection1 = [
"Excellent",
"Very Good",
"Good",
"Fair",
"Poor",
];
#override
void dispose() {
super.dispose();
_texteditingcontroller.dispose();
_loading = false;
_progress = 0.0;
percentagenum = 0;
_currValue = 0;
usingTimes1 = '';
usingTimes = '';
usingTimes2 = '';
}
void initState() {
super.initState();
usingTimes1 = '';
usingTimes = '';
usingTimes2 = '';
_loading = false;
_progress = 0.0;
percentagenum = 0;
_texteditingcontroller.clear();
_currValue = 0;
}
void pageChanged(int index) {
setState(() {
_currentpage = index;
});
}
void _selectedanswers(data1, data2) {
if (_progress.toStringAsFixed(1) == '1.0') {
print(data1);
print(data2);
_texteditingcontroller.text;
}
}
void _updateProgress() {
setState(() {
_progress += 0.25;
percentagenum += 25;
if (_progress.toStringAsFixed(1) == '1.0') {
_loading = false;
_progress = 0;
percentagenum = 0;
Navigator.push(context, FadeRoute(page: thankyou()));
return;
}
});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Colors.white,
resizeToAvoidBottomPadding: false,
body: Padding(
padding: EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: 100,
height: 60,
child: Image.asset(imgtit),
),
Stack(
children: <Widget>[
Container(
child: Text(
titletop,
style: conqueststyle,
maxLines: 1,
),
),
_buildPageView(),
_lineprogressindicator()
],
)
],
),
),
),
);
}
_buildPageView() {
return Container(
height: MediaQuery.of(context).size.height / 1.25,
child: PageView(
controller: _pageController,
onPageChanged: (index) {
pageChanged(index);
},
children: <Widget>[
_emojiquestions(q1),
_selectedutton(q2),
_numberrating(q3),
_textboxquestion(q4),
],
));
}
_lineprogressindicator() {
return Positioned(
left: 0.0,
right: 0.0,
bottom: 0.0,
child: Column(
children: <Widget>[
RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(50.0),
),
color: Colors.indigo,
onPressed: () {
_pageController.nextPage(
duration: kTabScrollDuration, curve: Curves.ease);
_loading = !_loading;
_updateProgress();
},
child: Icon(
Icons.check,
color: Colors.white,
size: 50,
),
),
SizedBox(
height: 10,
),
Text('%$percentagenum'),
LinearProgressIndicator(
value: _progress,
),
],
),
);
}
_emojiquestions(String quest1) {
final using = usingCollection1[index];
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text(
'Question 1',
style: conqueststyle,
textAlign: TextAlign.right,
),
SizedBox(
height: 20,
),
TextField(
decoration: InputDecoration.collapsed(hintText: quest1),
maxLines: 5,
style: conqueststyle,
),
Expanded(
child: Center(
child: Container(
height: 300,
child: ListView.separated(
separatorBuilder: (context, index) => SizedBox(height: 10),
itemCount: usingCollection1.length,
itemBuilder: (context, index) => GestureDetector(
onTapUp: (index) {
_selectedanswers(index, null);
},
child: Card(
color: usingTimes == usingCollection1[index]
? Colors.blue.withAlpha(100)
: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
SizedBox(
height: 50,
width: 70,
child: Image.asset(emojiimage[index]),
),
Text(usingCollection1[index])
],
),
Divider(
height: index < usingCollection1.length ? 1.0 : 0.0,
),
],
),
),
),
)),
),
)
],
);
}
_selectedutton(String quest1) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text(
'Question 1',
style: conqueststyle,
textAlign: TextAlign.right,
),
SizedBox(
height: 20,
),
TextField(
decoration: InputDecoration.collapsed(hintText: quest1),
maxLines: 5,
style: conqueststyle,
),
Expanded(
child: Center(
child: Container(
height: 300,
child: Column(
children: List.generate(usingCollection1.length, (int index) {
final using = usingCollection1[index];
return GestureDetector(
onTap: () {
setState(() {
_currValue = index;
_selectedanswers(index, null);
usingTimes = using.identifier;
});
},
child: Card(
color: usingTimes == using.identifier
? Colors.blue.withAlpha(100)
: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Radio(
value: index,
groupValue: _currValue,
onChanged: (val) =>
setState(() => _currValue = val),
),
Text(using.displayContent)
],
),
Divider(
height:
index < usingCollection1.length ? 1.0 : 0.0,
),
],
),
));
}),
),
),
),
)
],
);
}
_numberrating(quest) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text(
'Question 2',
style: conqueststyle,
textAlign: TextAlign.right,
),
SizedBox(
height: 20,
),
TextField(
decoration: InputDecoration.collapsed(hintText: quest),
maxLines: 5,
style: conqueststyle,
),
Text("**5 is the highest"),
Container(
height: MediaQuery.of(context).size.height / 12.0,
width: MediaQuery.of(context).size.width,
child: ListView.builder(
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.horizontal,
itemCount: usingCollection1.length,
itemBuilder: (context, index) {
final using = usingCollection1[index];
return GestureDetector(
onTapUp: (index) {
setState(() {
_selectedanswers(null, index);
usingTimes = using.identifier;
});
},
child: Card(
color: usingTimes == using.identifier
? Colors.blue.withAlpha(100)
: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
side: BorderSide(color: Colors.indigoAccent)),
child: Column(
children: <Widget>[
SizedBox(
height: 50,
width: 50,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
answernumbers[index],
textAlign: TextAlign.center,
style: conqueststyle,
),
],
)),
),
],
),
),
);
},
),
)
],
);
}
_textboxquestion(quest) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text(
'Question 2',
style: conqueststyle,
textAlign: TextAlign.right,
),
SizedBox(
height: 20,
),
TextField(
decoration: InputDecoration.collapsed(hintText: quest),
maxLines: 5,
style: conqueststyle,
),
TextFormField(
decoration: InputDecoration(
hintText: "Your FeedBack Here",
border: OutlineInputBorder(),
),
controller: _texteditingcontroller,
maxLines: 7,
style: conqueststyle,
)
],
);
}
}
For your case were the number of elements is known beforehand, I would suggest that you store your pages in a local variable and then call length on it. A small snippet would look something like this:
class MyState extends State<MyWidget> {
List<Widget> _pages = [
Container(color: Colors.blue,),
Container(color: Colors.amber,),
];
#override
Widget build(BuildContext context) {
return MyComplexWidgetTree(
child: PageView(
controller: PageController(),
children: _pages,
),
);
}
void _myMethodThatRequiresNumberOfPages() {
int numberOfPages = pages.length;
}
}

Flutter: Using Expanded

I have a function that returns a list of Widget like this:
buildCaption() {
List<String> splittedCaption = caption.split(' ');
List<Widget> mergedCaption = new List<Widget>();
for (String captionSplit in splittedCaption) {
print(captionSplit);
if (captionSplit.contains('#')) {
mergedCaption.add(Text(
'$captionSplit ',
style: TextStyle(color: Colors.blue)
));
} else {
mergedCaption.add(Text('$captionSplit '));
}
}
return mergedCaption;
}
Then, I have a Row Widget that looks like this:
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(child: Row(children: buildCaption())
]
)
However, the Expanded doesn't prevent the row from overflowing the screen size. Please how do I display the List of Widgets returned from the buildCaption method while still preventing it from overflowing the screen size?
Whole code:
buildPostFooter() {
return Column(
children: <Widget>[
mediaUrl.length > 1 ? Row(
mainAxisAlignment: MainAxisAlignment.center,
children: map<Widget>(
mediaUrl,
(index, media) {
return Container(
width: 8.0,
height: 8.0,
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 2.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: currentMedia == index
? Theme.of(context).primaryColor
: Color.fromRGBO(0, 0, 0, 0.4)
)
);
}
)
) : Text(''),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(padding: EdgeInsets.only(top: 40.0, left: 15.0)),
GestureDetector(
onTap: handleLikePost,
child: Icon(
isLiked ? Icons.favorite : Icons.favorite_border,
size: 28.0,
color: Colors.pink
)
),
Padding(padding: EdgeInsets.only(right: 5.0)),
Text(
'$likeCount likes',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold
)
),
Padding(padding: EdgeInsets.only(right: 20.0)),
GestureDetector(
onTap: () => showComments(
context,
postId: postId,
ownerId: ownerId,
mediaUrl: mediaUrl
),
child: Icon(
Icons.chat,
size: 28.0,
color: Colors.blue[900]
)
),
Padding(padding: EdgeInsets.only(right: 5.0)),
Text(
'$commentCount comments',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold
)
)
],
),
Padding(
padding: EdgeInsets.only(
top: mediaUrl.length > 0 && caption.isNotEmpty ? 10.0 : 0.0
)
),
mediaUrl.length > 0 && caption.isNotEmpty ? Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: EdgeInsets.only(left: 20.0),
child: Text(
'$username ',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold
)
)
),
Expanded(child: Row(children: buildCaption()))
],
) : timeWidget(),
mediaUrl.length > 0 && caption.isNotEmpty ? timeWidget() : Text('')
],
);
}
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: RichText(
text: TextSpan(
children: caption.split(' ').map(
(item) {
if (item.contains('#')) {
return TextSpan(
text: '$item ',
recognizer: new TapGestureRecognizer()
..onTap = () => print('hashtag$item'),
style: TextStyle(color: Colors.blue),
);
} else if (item.contains('.')) {
return TextSpan(
text: '$item ',
recognizer: new TapGestureRecognizer()
..onTap = () => print('https://www.$item'),
style: TextStyle(color: Colors.blue),
);
} else {
return TextSpan(
text: '$item ',
);
}
},
).toList(),
),
),
)
]
)
you can`t use row for multiple text widget and expect line breaks
you should use Rich Text for multiple style in one text
try below code:
buildCaption() {
List<String> splittedCaption = caption.split(' ');
List<TextSpan> mergedCaption = List<TextSpan>();
for (String captionSplit in splittedCaption) {
print(captionSplit);
if (captionSplit.contains('#')) {
mergedCaption.add(TextSpan(
text: '$captionSplit ',
style: TextStyle(color: Colors.blue)
));
} else {
mergedCaption.add(TextSpan(text: '$captionSplit '));
}
}
return mergedCaption;
}
 
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: RichText(
text: new TextSpan(
style: new TextStyle(
fontSize: 14.0,
color: Colors.black,
),
children: buildCaption(),
),
))
]
)
Try using SingleChildScrollView instead of Expanded
I dont know what you are trying to do, but here you have a horizontal scrollable list. If you want to use row I will suggest using the Wrap. widget.
final List<Widget> widgetList = buildCaption();
#override
Widget build(BuildContext context) {
return ListView.builder(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.all(8),
itemCount: widgetList.length,
itemBuilder: (BuildContext context, int index) {
return index;
}
);
}
suggestion: Regarding the overflow you can use a Container instead of Expanded, and set width: MediaQuery.of(context).size.width*0.5 on the Container, this is eqvivalent to 50% of screen width.
suggestion: You can use Grid-list and set crossAxisCount: widgetList().length if you want everything to be in one line, se example here:
https://flutter.dev/docs/cookbook/lists/grid-lists