Flutter数量输入插件input_quantity的使用
Flutter数量输入插件input_quantity的使用
Input Quantity
Flutter的数量输入插件input_quantity
允许用户通过点击按钮来增加或减少输入值,同时也支持手动输入。此插件具有灵活配置输入限制、自定义外观和行为以及多种样式选项等功能。
功能特性
- 简单易用
- 高度可定制
- 支持输出类型:
int
、double
或num
- 提供经典样式、按钮在左侧或右侧的样式
- 支持点击更新值、长按连续更新值或手动输入值
- 可添加表单验证或自定义消息构建器
安装
在您的pubspec.yaml
文件中添加input_quantity
作为依赖项:
dependencies:
input_quantity: ^2.5.0
然后运行flutter pub get
安装该包。
使用方法
基本用法
import 'package:input_quantity/input_quantity.dart';
InputQty(
maxVal: 100,
initVal: 0,
minVal: -100,
steps: 10,
onQtyChanged: (val) {
print(val);
},
)
禁止手动输入
如果您希望阻止用户手动输入,可以禁用enableTyping
属性:
InputQty(
qtyFormProps: QtyFormProps(enableTyping: false),
...
)
指定输出类型
默认情况下,输出类型为num
。要指定为int
或double
,请使用InputQty.int
或InputQty.double
构造函数:
// 输出类型为 int
InputQty.int(
onQtyChanged: (val) {
print(val.runtimeType); // int
},
)
// 输出类型为 double
InputQty.double(
onQtyChanged: (val) {
print(val.runtimeType); // double
},
)
自定义外观与行为
您可以使用QtyFormProps
来自定义输入框的外观和行为,如文本对齐方式、字体样式、光标颜色等:
InputQty(
qtyFormProps: QtyFormProps(
textAlign: TextAlign.center,
style: TextStyle(fontWeight: FontWeight.bold),
cursorColor: Colors.red,
enableTyping: true,
),
)
您还可以使用QtyDecorationProps
来自定义输入框的装饰,如边框形状、按钮颜色、填充颜色等:
InputQty(
decoration: QtyDecorationProps(
borderShape: BorderShapeBtn.circle,
btnColor: Colors.blue,
fillColor: Colors.grey[200],
isBordered: true,
),
)
表单验证
您可以通过validator
属性对输入值进行验证:
InputQty(
validator: (value) {
if (value == null) {
return "Required field";
} else if (value >= 200) {
return "More than available quantity";
}
return null;
},
)
自定义消息
使用messageBuilder
属性显示基于输入值的自定义消息:
InputQty(
messageBuilder: (minVal, maxVal, value) {
if (value == null) return null;
if (value < -20) {
return Text(
"Reach my limit",
style: TextStyle(color: Colors.red),
textAlign: TextAlign.center,
);
} else if (value > 20) {
return Text(
"Reach my limit",
style: TextStyle(color: Colors.red),
textAlign: TextAlign.center,
);
} else {
return Text("Value : $value", textAlign: TextAlign.center);
}
},
)
程序控制输入值
使用TextEditingController
来程序化地控制输入值:
final TextEditingController _controller = TextEditingController();
InputQty(
qtyFormProps: QtyFormProps(
controller: _controller,
),
)
按钮方向
更改按钮的方向:
InputQty(
decoration: QtyDecorationProps(
orientation: ButtonOrientation.horizontal,
),
)
按钮位置
更改按钮的位置:
InputQty(
decoration: QtyDecorationProps(
qtyStyle: QtyStyle.btnOnRight,
),
)
示例代码
以下是一个完整的示例代码,展示了如何在项目中使用input_quantity
插件:
import 'package:flutter/material.dart';
import 'package:input_quantity/input_quantity.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Input Quantity Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Input Quantity'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _formKey = GlobalKey<FormState>();
final TextEditingController _controller = TextEditingController();
int qtyInt = 123;
double qtyDouble = 12.0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
body: SingleChildScrollView(
child: Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Padding(
padding: EdgeInsets.all(8.0),
child: Text(
'INPUT QUANTITY',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.w500),
),
),
const Padding(
padding: EdgeInsets.all(14.0),
child: Text(
'by: pmatatias.dev',
style: TextStyle(fontSize: 14, color: Colors.blue),
),
),
const Divider(),
const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
InputQty(
maxVal: 50,
initVal: 10,
steps: 10,
minVal: -50,
qtyFormProps: QtyFormProps(enableTyping: false),
decoration: QtyDecorationProps(
isBordered: false,
minusBtn: Icon(
Icons.flight_land_rounded,
color: Colors.purple,
),
plusBtn: Icon(Icons.flight_takeoff, color: Colors.indigo),
),
),
SizedBox(width: 30),
Expanded(
child: Text(
"- Output: int,double, num\n- initVal, maxVal, minVal, steps \n- Custom: icon,decoration,etc"),
)
],
),
const Divider(height: 30),
const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
InputQty(
decoration: QtyDecorationProps(
isBordered: false,
borderShape: BorderShapeBtn.circle,
width: 12)),
SizedBox(width: 30),
Expanded(
child: Text(
"- Ontap\n- Longpress \n- Typing input Manually"))
],
),
const Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
InputQty(
qtyFormProps: QtyFormProps(
controller: _controller,
),
),
const SizedBox(width: 30),
const Expanded(
child: Text("use controller to get value (string)"),
)
],
),
const Divider(height: 50),
InputQty(
maxVal: 100,
qtyFormProps: QtyFormProps(
controller: _controller,
),
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
children: [
const Padding(
padding: EdgeInsets.all(8.0),
child: Text('Use validator')),
InputQty(
initVal: 0,
steps: 10,
minVal: -100,
maxVal: 100,
validator: (value) {
if (value == null) {
return "Required field";
} else if (value >= 200) {
return "More than available quantity";
}
return null;
},
),
],
),
const Center(
child: Text(
"OR",
style: TextStyle(fontSize: 20, color: Colors.black),
)),
Column(
children: [
const Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Text(
'Message builder',
),
),
InputQty(
initVal: 0,
minVal: -100,
maxVal: 100,
steps: 2,
messageBuilder: (minVal, maxVal, value) {
if (value == null) return null;
if (value < -20) {
return const Text(
"Reach my limit",
style: TextStyle(color: Colors.red),
textAlign: TextAlign.center,
);
} else if (value > 20) {
return const Text(
"Reach my limit",
style: TextStyle(color: Colors.red),
textAlign: TextAlign.center,
);
} else {
return Text("Value : $value",
textAlign: TextAlign.center);
}
},
),
],
),
],
),
const Divider(height: 50),
const Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
children: [
Padding(
padding: EdgeInsets.all(8.0),
child: Text('integer')),
InputQty.int(
initVal: 0,
steps: 10,
minVal: -100,
),
],
),
Center(
child: Text(
"OR",
style: TextStyle(
fontSize: 20,
color: Colors.black,
),
)),
Column(
children: [
Padding(
padding: EdgeInsets.all(8.0),
child: Text(
'double',
),
),
InputQty(
initVal: 0.0,
minVal: -100.0,
maxVal: 100.0,
steps: 0.1,
),
],
),
],
),
const SizedBox(height: 30),
const Divider(),
const Text("Custom Border:"),
const SizedBox(height: 12),
ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 200),
child: InputQty(
isIntrinsicWidth: false,
qtyFormProps: const QtyFormProps(),
decoration: QtyDecorationProps(
qtyStyle: QtyStyle.btnOnRight,
border: OutlineInputBorder(
borderSide:
const BorderSide(width: 5, color: Colors.green),
borderRadius: BorderRadius.circular(6)),
minusBtn: const Padding(
padding: EdgeInsets.symmetric(horizontal: 8.0),
child: Icon(Icons.keyboard_arrow_down_sharp,
color: Colors.blue),
),
plusBtn: const Padding(
padding: EdgeInsets.symmetric(horizontal: 8.0),
child: Icon(
Icons.keyboard_arrow_up,
color: Colors.blue,
),
)),
onQtyChanged: (val) {},
),
),
const Divider(height: 30),
const Text("Style options:"),
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
InputQty.int(
messageBuilder: (minVal, maxVal, value) =>
const Text("Button on Left", textAlign: TextAlign.center),
decoration: const QtyDecorationProps(
qtyStyle: QtyStyle.btnOnLeft,
width: 12,
fillColor: Colors.black12,
isBordered: false,
borderShape: BorderShapeBtn.square),
),
InputQty.int(
messageBuilder: (minVal, maxVal, value) =>
const Text("Button on Right", textAlign: TextAlign.center),
qtyFormProps: const QtyFormProps(cursorColor: Colors.amber),
decoration: const QtyDecorationProps(
qtyStyle: QtyStyle.btnOnRight,
width: 12,
fillColor: Colors.black12,
isBordered: false,
borderShape: BorderShapeBtn.square),
),
],
),
const SizedBox(height: 30),
InputQty.int(
messageBuilder: (minVal, maxVal, value) =>
const Text("Classic", textAlign: TextAlign.center),
decoration: const QtyDecorationProps(
qtyStyle: QtyStyle.classic,
width: 12,
fillColor: Colors.black12,
isBordered: false,
borderShape: BorderShapeBtn.none),
),
const SizedBox(height: 30),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
InputQty.int(
messageBuilder: (minVal, maxVal, value) =>
const Text("Button on Right Horizontal", textAlign: TextAlign.center),
qtyFormProps: const QtyFormProps(cursorColor: Colors.amber),
decoration: const QtyDecorationProps(
qtyStyle: QtyStyle.btnOnLeft,
width: 12,
orientation: ButtonOrientation.horizontal,
isBordered: false,
borderShape: BorderShapeBtn.square),
),
InputQty.int(
messageBuilder: (minVal, maxVal, value) =>
const Text("Button on Right Horizontal", textAlign: TextAlign.center),
qtyFormProps: const QtyFormProps(cursorColor: Colors.amber),
decoration: const QtyDecorationProps(
qtyStyle: QtyStyle.btnOnRight,
width: 12,
orientation: ButtonOrientation.horizontal,
isBordered: false,
borderShape: BorderShapeBtn.square),
),
],
),
],
),
),
),
),
);
}
}
以上是关于input_quantity
插件的详细说明和完整示例代码,希望能够帮助您更好地理解和使用这个插件。如果您有任何问题或需要进一步的帮助,请随时提问!
更多关于Flutter数量输入插件input_quantity的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter数量输入插件input_quantity的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,我可以为你提供一个关于如何在Flutter项目中使用input_quantity
插件的示例代码。input_quantity
是一个用于数量输入的Flutter插件,它允许用户通过滑动或点击来增加或减少数量。
首先,你需要在你的pubspec.yaml
文件中添加这个插件的依赖:
dependencies:
flutter:
sdk: flutter
input_quantity: ^x.y.z # 请替换为最新版本号
然后运行flutter pub get
来获取依赖。
接下来,在你的Flutter项目中,你可以按照以下方式使用这个插件:
import 'package:flutter/material.dart';
import 'package:input_quantity/input_quantity.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: QuantityInputScreen(),
);
}
}
class QuantityInputScreen extends StatefulWidget {
@override
_QuantityInputScreenState createState() => _QuantityInputScreenState();
}
class _QuantityInputScreenState extends State<QuantityInputScreen> {
int _quantity = 1;
void _onQuantityChanged(int quantity) {
setState(() {
_quantity = quantity;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Quantity Input Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Selected Quantity: $_quantity'),
SizedBox(height: 20),
QuantityInput(
initialValue: _quantity,
minValue: 1,
maxValue: 100,
step: 1,
onQuantityChanged: _onQuantityChanged,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Quantity',
suffixIcon: Icon(Icons.arrow_drop_down),
),
),
],
),
),
);
}
}
代码解释:
-
依赖导入:
import 'package:input_quantity/input_quantity.dart';
-
主应用结构:
MyApp
是一个无状态小部件,它包含了一个MaterialApp
,并设置了主题和主页面。QuantityInputScreen
是一个有状态小部件,用于管理数量输入的状态。
-
状态管理:
- 使用
_quantity
变量来存储当前的数量。 - 使用
_onQuantityChanged
方法来更新数量。
- 使用
-
UI布局:
- 使用
Scaffold
来创建页面的基本结构。 - 在
body
中,使用Center
和Column
来排列文本和数量输入控件。 QuantityInput
控件用于数量输入,设置初始值、最小值、最大值、步长以及数量变化时的回调函数。
- 使用
这个示例展示了如何在Flutter中使用input_quantity
插件来创建一个简单的数量输入界面。你可以根据需要调整最小值、最大值、步长和其他参数。