我正在实现下面的代码以将数字数据保存到数据库。保存的数值数据将在将来用于算术运算。
该代码仍然是非常原生的,其中数字不是以千分隔的。通过这种做法,插入的值等于检索到的值。
我想给用户一种模仿物理计算器的体验。为了实现这一点,我尝试使用 pub.dev 中提供的 Masking Controller 或 Input Formatter Packages。到目前为止,我还没有得到我想要的结果。
在下面注释掉的代码中,我尝试在使用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,
height: 70,
margin: EdgeInsets.symmetric(horizontal: 15),
child: FormBuilderTextField(
attribute: 'value',
controller: savedValueController,
textAlign: TextAlign.start,
textAlignVertical: TextAlignVertical.bottom,
textInputAction: TextInputAction.next,
keyboardType: TextInputType.number,
inputFormatters: [
// CurrencyTextInputFormatter(
// decimalDigits: 2,
// ),
],
decoration: InputDecoration(
helperText: ' ',
hintText: 'Saved Value',
hintStyle: TextStyle(fontSize: 12),
prefixIcon: Padding(
padding: const EdgeInsets.only(right: 10.0),
child: Icon(
FontAwesomeIcons.save,
size: 20,
),
)),
onChanged: (val) {
setState(() {
value = num.parse(val);
_fbKey.currentState.fields['value'].currentState
.validate();
});
},
autovalidateMode: AutovalidateMode.onUserInteraction,
validators: [
FormBuilderValidators.required(
errorText: 'required',
),
],
),
),
SizedBox(height: 50),
RaisedButton(
child: Text('Save'),
onPressed: saveForm,
),
SizedBox(height: 40),
Container(
color: Colors.grey[200],
width: MediaQuery.of(context).size.width,
height: 70,
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;
}
},
),
),
Container(
width: MediaQuery.of(context).size.width,
height: 70,
margin: EdgeInsets.symmetric(horizontal: 15),
child: FormBuilderTextField(
attribute: 'retrieve_value',
controller: retrievedValueController,
textAlign: TextAlign.start,
textAlignVertical: TextAlignVertical.bottom,
textInputAction: TextInputAction.next,
keyboardType: TextInputType.number,
inputFormatters: [
// CurrencyTextInputFormatter(
// decimalDigits: 2,
// )
],
decoration: InputDecoration(
helperText: ' ',
hintText: 'Retrieved Value',
hintStyle: TextStyle(fontSize: 12),
prefixIcon: Padding(
padding: const EdgeInsets.only(right: 10.0),
child: Icon(
FontAwesomeIcons.list,
size: 20,
),
)),
onChanged: (val) {},
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
)
''');
}
}