问题描述
我正在实施以下代码以将数字数据保存到数据库。 保存的数值数据将在以后的算术运算中使用。
代码仍然非常原生,其中数字不以千位分隔。 通过这种做法,插入的值等于检索到的值。
我想给用户一种模拟物理计算器的体验。 为了实现这一点,我尝试使用 pub.dev 中提供的屏蔽控制器或输入格式化程序包。 到目前为止,我还没有得到我想要的结果。
在下面注释掉的代码中,是我在使用 currency_text_input_formatter 包插入和检索数字数据时尝试将这些数字按千位和小数分隔的示例实践之一。
在这种做法中,并非所有数字都保存到数据库中, 任何插入三位数以上的数字总是只能保存和检索三位数和两位小数。
Examples:
1. value inserted: 7000
print('value: $value')
the result was:
I/Flutter (12551): value: 700.0
2. value inserted: 12,345,678.90
print('value: $value')
the result was:
I/Flutter (12551): value: 123.45
有什么建议我应该实现哪个包或方法? 以及如何使包或方法的实现得到想要的结果?
我原来的原生代码如下图, 请取消注释注释掉的代码以重现我的问题。
任何帮助将不胜感激。
我的模型:
class Product {
int id;
String name;
num savedValue;
static const tblProduct = 'product';
static const colId = 'id';
static const colName = 'name';
static const colSavedValue = 'savedValue';
Product({
this.id,this.name,this.savedValue,});
Map<String,dynamic> toMap() {
var map = <String,dynamic>{
colName: name,colSavedValue: savedValue,};
if (id != null) map[colId] = id;
return map;
}
Product.fromMap(Map<String,dynamic> map) {
id = map[colId];
name = map[colName];
savedValue = map[colSavedValue];
}
}
我的用户界面:
import 'dart:ui';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import 'package:sqflite/sqflite.dart';
import 'package:Flutter/material.dart';
import 'package:Flutter/services.dart';
import 'package:Flutter_form_builder/Flutter_form_builder.dart';
import 'package:font_awesome_Flutter/font_awesome_Flutter.dart';
import 'package:currency_text_input_formatter/currency_text_input_formatter.dart';
class LossZero extends StatefulWidget {
@override
_LossZeroState createState() => _LossZeroState();
}
class _LossZeroState extends State<LossZero> {
DatabaseHelper dbHelper = DatabaseHelper.instance;
Product product = Product();
List<Product> products = [];
String name;
int id;
num value;
final _fbKey = GlobalKey<FormBuilderState>();
final itemController = TextEditingController();
final savedValueController = TextEditingController();
final retrievedValueController = TextEditingController();
final itemChosen = TextEditingController();
@override
void initState() {
super.initState();
dbHelper = DatabaseHelper.instance;
refreshItems();
}
@override
Widget build(BuildContext context) {
return Container(
child: SafeArea(
child: Scaffold(
body: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,mainAxisAlignment: MainAxisAlignment.center,children: [
FormBuilder(
key: _fbKey,child: Column(
children: [
Container(
width: MediaQuery.of(context).size.width,height: 70,margin: EdgeInsets.symmetric(horizontal: 15),child: FormBuilderTextField(
attribute: 'item',controller: itemController,autofocus: true,textAlign: TextAlign.start,textAlignVertical: TextAlignVertical.bottom,textInputAction: TextInputAction.next,keyboardType: TextInputType.name,inputFormatters: [],decoration: Inputdecoration(
helperText: ' ',hintText: 'Item',hintStyle: TextStyle(fontSize: 12),prefixIcon: Padding(
padding: const EdgeInsets.only(right: 10.0),child: Icon(
FontAwesomeIcons.shoppingBag,size: 20,),)),onChanged: (val) {
setState(() {
name = val;
_fbKey.currentState.fields['item'].currentState
.validate();
});
},autovalidateMode: AutovalidateMode.onUserInteraction,validators: [
FormBuilderValidators.required(
errorText: 'required',],Container(
width: MediaQuery.of(context).size.width,child: FormBuilderTextField(
attribute: 'value',controller: savedValueController,keyboardType: TextInputType.number,inputFormatters: [
// CurrencyTextInputFormatter(
// decimalDigits: 2,// ),hintText: 'Saved Value',child: Icon(
FontAwesomeIcons.save,onChanged: (val) {
setState(() {
value = num.parse(val);
_fbKey.currentState.fields['value'].currentState
.validate();
});
},SizedBox(height: 50),RaisedButton(
child: Text('Save'),onpressed: saveForm,SizedBox(height: 40),Container(
color: Colors.grey[200],width: MediaQuery.of(context).size.width,margin: EdgeInsets.symmetric(horizontal: 20),child: FormBuilderTypeAhead(
attribute: 'item_chosen',initialValue: product,getImmediateSuggestions: true,autoFlipDirection: true,controller: itemChosen,decoration: Inputdecoration(
border: InputBorder.none,hideOnLoading: true,onChanged: (val) {},itemBuilder: (context,Product product) {
return ListTile(
title: Text(product.name),subtitle: Text(product.savedValue.toString()),);
},selectionToTextTransformer: (Product ps) => ps.name,suggestionsCallback: (query) {
if (query.isNotEmpty) {
var lowercaseQuery = query.toLowerCase();
return products.where((product) {
return product.name
.toLowerCase()
.contains(lowercaseQuery);
}).toList(growable: false)
..sort((a,b) => a.name
.toLowerCase()
.indexOf(lowercaseQuery)
.compareto(b.name
.toLowerCase()
.indexOf(lowercaseQuery)));
} else {
return products;
}
},textFieldConfiguration: TextFieldConfiguration(
autofocus: true,style: DefaultTextStyle.of(context).style.copyWith(
fontSize: 24,letterSpacing: 1.2,color: Colors.black,fontWeight: FontWeight.w300,decoration: Textdecoration.none),noItemsFoundBuilder: (BuildContext context) {
return Text('not registered');
},onSuggestionSelected: (product) {
if (product != null) {
setState(() {
retrievedValueController.text =
product.savedValue.toString();
});
} else {
return products;
}
},child: FormBuilderTextField(
attribute: 'retrieve_value',controller: retrievedValueController,// )
],hintText: 'Retrieved Value',child: Icon(
FontAwesomeIcons.list,validators: [],);
}
saveForm() async {
if (_fbKey.currentState.validate()) {
_fbKey.currentState.save();
if (product.id == null) {
Product p = Product(
id: null,name: name,savedValue: value,);
await insertValue(p);
itemController.clear();
savedValueController.clear();
refreshItems();
Get.snackbar('Done','Item Saved');
print('value: $value');
} else {
Get.snackbar('Fail','Item saving Failed');
}
}
}
refreshItems() async {
List<Product> p = await getAllItems();
setState(() {
products = p;
});
}
Future<int> insertValue(Product prod) async {
Database db = await dbHelper.database;
return await db.insert(Product.tblProduct,prod.toMap());
}
Future<List<Product>> getAllItems() async {
Database db = await dbHelper.database;
List<Map> x = await db.query(Product.tblProduct);
return x.length == 0
? []
: x.map((e) => Product.fromMap(e)).toList();
}
}
我的数据库助手
import 'dart:io';
import 'dart:async';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
class DatabaseHelper {
static const _databaseVersion = 1;
static const _databaseName = 'product.db';
DatabaseHelper._();
static final DatabaseHelper instance = DatabaseHelper._();
Database _database;
Future<Database> get database async {
if (_database != null) return _database;
_database = await _initDatabase();
return _database;
}
_initDatabase() async {
Directory dataDirectory = await getApplicationDocumentsDirectory();
String dbPath = join(dataDirectory.path,_databaseName);
return await openDatabase(
dbPath,version: _databaseVersion,onCreate: _onCreateDB,);
}
_onCreateDB(Database db,int version) async {
await db.execute('''
-- P R O D U C T
CREATE TABLE ${Product.tblProduct}(
${Product.colId} INTEGER INCREMENT,${Product.colName} TEXT NOT NULL,${Product.colSavedValue} FLOA
)
''');
}
}
解决方法
在使用了许多人推荐的 this 软件包后,我终于得到了我想要的结果。
在上面的代码中,我修改了以下方法:
- 保存方法:
onChanged: (val) {
setState(() {
value =
savedValueController.numberValue.toDouble();
_fbKey.currentState.fields['value'].currentState
.validate();
});
},
- 检索数据方法:
onSuggestionSelected: (product) {
if (product != null) {
setState(() {
var x = product.savedValue;
retrievedValueController
.updateValue(x.toDouble());
});
} else {
return products;
}
},
- 修改控制器方法
modified TexEditingController:
final savedValueController =
MoneyMaskedTextController(decimalSeparator: '.',thousandSeparator: ',');
final retrievedValueController =
MoneyMaskedTextController(decimalSeparator: '.',');
- 将 inputFormatter 放入 FormBuilder:
inputFormatters: [],