TRYING TO GET interger from TexteditingController to build a M - flutter

i want to make a dodging (Multiplication) Table...and wanna take input from user from TexteditingController, but i am not able to take the integer value from the Text Editing controller. looking forward if someone would look into it,
TextEditingController num = TextEditingController();
void table() {
print('enter the number $num');
for (var i = 1; i <= 10; i++) {
print('$num*$i = ${num * i}'); //<error>(The operator '*' isn't defined for the type,,'')
}
}
Scaffold(
body: Column(
children: [
TextFormField(
controller: TextEditingController(),
),
Container(
height: 400,
width: 400,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(20),
),
child: ElevatedButton(
onPressed: table,
child: Text('')),
),
],
));
}
}

The error comes from the fact that you access the TextEditingController directly instead of grabbing the text it contains.
Correct would be:
TextEditingController controller = TextEditingController();
void table() {
var enteredText = controller.text;
var enteredNumber = int.parse(enteredText)
for (var i = 1; i <= 10; i++) {
print('$enteredNumber*$i = ${enteredNumber * i}');
}
}

Related

Deleting item from list cause range error

I have this document :
for (var i = 0; i < ligneDocuments.length; i++) {
if (ligneDocuments[i]['id_doc'] == widget.ligneDocumentId) {
setState(() {
TextEditingController idController = new TextEditingController();
widget.controllers.add(idController);
idController.text = ligneDocuments[i]['id'].toString();
TextEditingController refController = new TextEditingController();
widget.controllers.add(refController);
refController.text = ligneDocuments[i]['refProd'].toString();
TextEditingController nomController = new TextEditingController();
widget.controllers.add(nomController);
nomController.text = ligneDocuments[i]['nomProd'].toString();
TextEditingController qteController = new TextEditingController();
widget.controllers.add(qteController);
qteController.text = ligneDocuments[i]['qteProd'].toString();
TextEditingController prixController = new TextEditingController();
widget.controllers.add(prixController);
prixController.text = ligneDocuments[i]['prixProd'].toString();
TextEditingController totalProdController =
new TextEditingController();
totalProdController.text = (double.parse(prixController.text) *
double.parse(qteController.text))
.toString();
print(kk);
kk++;
print(kk);
_cardList.add(InputRefNomProduit(
index:kk,
totalDoc: totalDoc,
totalDocument: totalDocument,
total: total,
controllers: widget.controllers,
label: 'Référence',
label2: 'Nom du produit',
label3: 'Quantité',
label4: 'Prix',
label5: 'Total par Produit',
fieldController: refController,
fieldController2: nomController,
fieldController3: qteController,
fieldController4: prixController,
fieldController5: totalProdController,
delete: (index){
print(index);
setState(() {
_cardList.removeAt(index);
});
},
));
});
}
This is how I'm printing my _cardList :
SizedBox(
height: 450,
width: 1200,
child: ListView.builder(
itemCount: _cardList.length,
itemBuilder: (context, index) {
return Padding(padding:
EdgeInsets.symmetric(vertical: 5),child: _cardList[index],);
},
),
),
class _InputRefNomProduitState extends State<InputRefNomProduit> {
bool hasFocus = false;
String nomProduit;
String selectedProduit;
int produitId;
List produits = [];
List<String> refProduits = [];
#override
void initState() {
super.initState();
this.fetchProduits();
}
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return Row(
children: <Widget>[
Expanded(
flex: 2,
child: Container(
child: Text(
"${widget.label}",
textAlign: TextAlign.left,
style: TextStyle(
fontWeight: FontWeight.w900,
color: Color.fromARGB(255, 255, 255, 255),
),
),
),
),
// more Expanded inputs
IconButton(onPressed: (){
widget.delete(widget.index);
}, icon: Icon(Icons.close)),
],
);
},
);
}
}
at the top , I'm trying to check if some inputs are == to what exists in my BD .
Then , print the items with a Icon Button with remove function .
I'm facing the problem that when I delete an item , I'm getting different counter for the _cardList length , and the index of item that I want to delete.
After deleting 1 item, I'm getting error like this :
Another exception was thrown: RangeError: Value not in range: 3.
The card list length went from 4 to 3 and the item I'm trying to delete is still index=3.
I tried without the index[kk] variable using just removeAt[index] , and it didn't work.
these are one of two options you can try.
1.
_cardList.removeAt(index);
setState(() {
});
//outside of loop
void refresh(){
setState((){});
}
//then inside loop
_cardList.removeAt(index);
refresh();
The 1. answer is how I solved my issue which is dervied from this stackoverflow post.
Flutter , index out of range when i try to delete an item from a list

Flutter: TextField auto add a dot when input multiple spaces

I just implement a simple TextField, but when I input multiple spaces, it auto add a dot before that.
my-custom-flutter-textfield
Here is my custom TextField widget
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(5),
child: Column(children: [
Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(bottom: 5),
child: Text(
title,
),
)),
TextField(
controller: _controller,
autocorrect: false,
decoration: InputDecoration(
isDense: true,
contentPadding: const EdgeInsets.all(10),
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: Colors.black,
width: 2,
),
borderRadius: BorderRadius.circular(5),
),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: Colors.orange,
width: 2,
),
borderRadius: BorderRadius.circular(5),
),
))
]));
}
This is a standard function of the iOS keyboard and most Android keyboards. I don't think you can control that from Flutter.
I don't think that has anything to do with the app itself, but the phone. You'd need to disable that from the phone's settings.
Although, if you really need to be able to type double spaces, here is how I'd implement it.
final TextEditingController controller = TextEditingController();
TextSelection? cursor;
int length = 0;
String lastChar = '';
String currentChar = '';
String replaceCharAt(String oldString, int index, String newChar) {
// function from https://stackoverflow.com/questions/52083836/how-to-replace-only-one-character-in-a-string-in-dart
return oldString.substring(0, index) +
newChar +
oldString.substring(index + 1);
}
void removeDotOnSpace(String input) {
//save the position of the cursor
cursor = controller.selection;
lastChar = currentChar;
// if the input isn't empty and if you're not removing text
if (input.isNotEmpty && input.length > length) {
currentChar = input[input.length - 1];
// if it has at least two characters, the second to last being a dot and the "lastChar" variable not being a dot
if (input.length >= 2 &&
input[input.length - 2] == '.' &&
lastChar != '.') {
// replace the dot and set state. Because setstate resests cursor position we need to save it and give it back.
setState(() {
controller.text = replaceCharAt(input, input.length - 2, ' ');
controller.selection = cursor!;
});
}
} else {
currentChar = '';
lastChar = '';
}
length = input.length;
}
Put this inside a stateful widget and use it inside the onchanged function
TextFormField(
controller: controller,
onChanged: (value) {
removeDotOnSpace(value);
},
),
PS: Unless it's essential for your textfields to be able to have double spaces, you should just let it be.
try textCapitalization: TextCapitalization.words,
put this function onBlur in form inputs:
const handleTrimDataAndRemoveDot = () => {
const trimmedData = formData.trim();
let validatedData;
if (trimmedData.charAt(trimmedData.length - 1) === ".") {
validatedData = trimmedData.replace(
trimmedData.charAt(trimmedData.length - 1),
""
);
} else {
validatedData = trimmedData;
}
setFormData(validatedData);
};

I can't change the hinttext in the dropdownButton

This is my code, and i dont know why the hint doesnt change, when i click the options, obviously all this code is inside a class, I tried to use a for loop to identify the list positions , and if they were right, it would appear on the screen.
final listgenre = ["Masc", "Fem", "Não Binário"];
var listgenre_value;
String newValue = "";
var valueChoose;
String hintValue = "";
Padding(
padding: EdgeInsets.all(16),
child: Container(
padding: EdgeInsets.only(left: 16, top: 10, right: 15),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey, width: 2),
borderRadius: BorderRadius.circular(20)),
child: DropdownButton<String>(
hint: Text("Genero :$hintValue"),
dropdownColor: Colors.white,
icon: Icon(Icons.arrow_drop_down),
iconSize: 36,
iconEnabledColor: Colors.black,
isExpanded: true,
style: TextStyle(fontSize: 17, color: Colors.black),
value: valueChoose,
underline: SizedBox(
width: 320,
height: 200,
),
items: listgenre.map((valueitem) {
return DropdownMenuItem(
value: valueitem,
child: Text(valueitem),
);
}).toList(),
onChanged: (newValue) {
setState(() {
for (int i = 0; i <= listgenre.length; i++) {
if (listgenre[i] != newValue) {
listgenre_value = i + 1;
} else {
hintValue = "$newValue";
// ignore: void_checks
return listgenre_value;
}
}
Object? valueChoose = newValue;
String valueChoosen = valueChoose.toString();
});
},
))),
As per your comments, the same code doesn't give the expected output.
It is only possible if you are also initialising the variables inside the build method, which shouldn't be the case.
Incorrect Code
#override
Widget build(BuildContext context) {
// ---- your variables INSIDE build method
final listgenre = ["Masc", "Fem", "Não Binário"];
var listgenre_value;
String newValue = "";
var valueChoose;
String hintValue = "";
// ------- rest of the code continued
Correct Code
final listgenre = ["Masc", "Fem", "Não Binário"];
var listgenre_value;
String newValue = "";
var valueChoose;
String hintValue = "";
#override
Widget build(BuildContext context) {
// ------- rest of the code continued
As the build method is called every time setState is called, hintValue was being initialised to "" i.e empty string.
The correct way to fix this error is abdev's comment. It will help if you put the variables used by the DropdownButton widget above the build method.
I hope it was helpful!

Show counter to number of elements hidden when overflow occurs in flutter row widget

Can anyone please help to implement this feature of Gmail that shows the counter to number of emails hidden when the email list becomes large ? I want to implement this in row widget where instead of being scrollable extra elements count is shown when overflow occurs.Gmail shows +15 counter for hidden emails
I was Curious to give a try to achieve the same effect, as asked.
Just in case, If anyone want a start for writing a custom one, then below code may help.
Here is my Code, Feel free to give any suggestions,
(For Now delete button in chips is not working bcoz of some logic problem, I will make it work another day)
import 'package:flutter/material.dart';
class Demo3 extends StatefulWidget {
#override
_Demo3State createState() => _Demo3State();
}
class _Demo3State extends State<Demo3> {
String temp = "";
bool showChips = false;
List<Widget> chipsList = new List();
TextEditingController textEditingController = new TextEditingController();
final _focusNode = FocusNode();
int countChipsToDeleteLater = 0;
#override
void initState() {
super.initState();
_focusNode.addListener(() {
print("Has focus: ${_focusNode.hasFocus}");
if (!_focusNode.hasFocus) {
showChips = false;
setState(() {});
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: new Container(
height: 500,
child: new Center(
child: Container(
width: 300,
child: !showChips
? Row(
children: [
buildTextField(),
showNumberWidgetIfAny(),
],
)
: Center(
child: Wrap(
children: [
Wrap(
children: buildChips(),
),
buildTextField(),
],
),
),
),
),
),
),
);
}
buildChips() {
return chipsList;
}
buildTextField() {
return Container(
width: 200,
child: new TextField(
showCursor: true,
focusNode: _focusNode,
autofocus: true,
cursorColor: Colors.black,
style: new TextStyle(fontSize: 22.0, color: Colors.black),
controller: textEditingController,
// decoration: InputDecoration.collapsed(
// hintText: "",
// ),
onChanged: (value) {
if (value.contains(" ")) {
checkWhatToStoreInChips(value, countChipsToDeleteLater);
textEditingController.clear();
setState(() {
showChips = true;
});
countChipsToDeleteLater++;
}
},
),
);
}
checkWhatToStoreInChips(String val, int chipsIndex) {
temp = "";
for (int i = 0; i < val.length; i++) {
if (val[i] == " ") {
break;
}
temp = temp + val[i];
}
addToChips(temp, chipsIndex);
}
addToChips(String tmp, int chipsIndex) {
chipsList.add(Chip(
// onDeleted: () {
// if (chipsList.length == 0) {
// countChipsToDeleteLater = 0;
// }
// chipsList.removeAt(chipsIndex);
// print(chipsList.length);
// print(chipsIndex);
// setState(() {});
// },
avatar: CircleAvatar(
backgroundColor: Colors.grey.shade800,
child: Text(tmp[0]),
),
label: Text(temp),
));
}
showNumberWidgetIfAny() {
int len = chipsList.length;
if (len >= 1) {
return GestureDetector(
onTap: () {
showChips = true;
setState(() {});
},
child: new Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.blue,
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: new Text(
"${chipsList.length.toString()} ",
style: new TextStyle(color: Colors.white, fontSize: 22),
),
),
),
);
}
return Container();
}
}
How it works:
Write something in text field, then press space, showChips boolean will become true
onChanged will detect the space and will send the string to a function.
That function will extract the string before space and then will add the string to a chip,
Finally the chip will be added to a chipslist.
We will have a boolean variable to check if the textfield is in focus and when to show the textfield and numberwidget (a widget which will keep count of the total chips, same like you asked in your question) or when to show the chipslist and textfield wraped in a wrap widget.
You can play around by changing the decoration of textfield to collapsed, to it look like the same as gmail.
Check this package, if you want to use custom package for ease.
I was facing a similar issue. I found a way to implement the Overflow count text.
Sample image
You basically have to paint the overflow text, and get its width like below
final TextPainter textPainter = TextPainter(
text: TextSpan(text: text, style: style),
textDirection: TextDirection.ltr,
textScaleFactor: WidgetsBinding.instance.window.textScaleFactor,
)..layout();
var textSize = textPainter.size;
textSize.width;
Then subtract that from the width available. Lets call it x.
Then create a sum of width for each row item(using TextPainter.layout() method mentioned above), till its value is less than x.
This way you'll know how many items can be shown in the row.
I have created a Flutter library to help with this.

A RenderFlex overflowed by 265 pixels on the right

I'm trying to get weather data from the network and show only five indexes of the 5days/3hours API on openweathermap. It works fine when i first run the app but then when i click the Iconbutton button and call the updateUI again it gives me all the data instead of five. Here's my code :
List<String timeStringData = [];
List<String> hourlyTemp =[];
void updateUI(dynamic weatherData, dynamic hourlyData) {
setState(() {
temperature = weatherData['main']['temp'].toInt();
description = weatherData['weather'][0]['description'];
cityName = weatherData['name'];
for (int i = 1; i < 6; i++) {
timeStringData.add(hourlyData['list'][i]['dt_txt']);
hourlyTemp.add(hourlyData['list'][i]['main']['temp']);
parsing();
}
});
}
Row parsing() {
List<HourInfo> hourTexts = [];
for (int i = 0; i <= timeStringData.length - 1; i++) {
var parsedDate = DateTime.parse(timeStringData[i]);
String formatted = formatting(parsedDate);
String onlyTemp = hourlyTemp[i].toStringAsFixed(0);
setState(() {
hourTexts.add(
HourInfo(
onlyHour: formatted,
onlyTemp: onlyTemp,
),
);
});
}
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: hourTexts,
);
}
build method:
IconButton(
icon: Icon(
Icons.near_me,
color: Colors.white,
size: 35.0,
),
onPressed: () async {
var weatherData = await weather.getLocationWeather();
var hourlyData = await weather.get3HoursWeather();
updateUI(weatherData, hourlyData);
},
),
Container(
width: double.infinity,
height: 100.0,
child: parsing(),
),
I think you are mixing preparing the data with building the widget tree.
Just remove the parsing(); call from the updateUI() method. parsing(); will be called by the library when building the tree.