You've already forked flutter-rp-example
First commit
This commit is contained in:
97
lib/widgets/components/reflex_alert.dart
Normal file
97
lib/widgets/components/reflex_alert.dart
Normal file
@@ -0,0 +1,97 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sampleapp/widgets/components/reflex_box.dart';
|
||||
|
||||
import '../../globals.dart';
|
||||
|
||||
class ReflexAlert extends StatefulWidget {
|
||||
final String? title;
|
||||
final String text;
|
||||
final IconData icon;
|
||||
final bool? bigIcon;
|
||||
final Color? color;
|
||||
|
||||
const ReflexAlert(
|
||||
{Key? key,
|
||||
required this.text,
|
||||
required this.icon,
|
||||
this.color,
|
||||
bigIcon,
|
||||
this.title})
|
||||
: bigIcon = bigIcon ?? false,
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
_ReflexAlertState createState() => _ReflexAlertState();
|
||||
}
|
||||
|
||||
class _ReflexAlertState extends State<ReflexAlert> {
|
||||
_buildColumnAlert() {
|
||||
return Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
|
||||
Icon(
|
||||
widget.icon,
|
||||
color: Colors.white,
|
||||
size: 40,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
if (widget.title != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: Text(
|
||||
widget.title ?? "",
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold),
|
||||
softWrap: true,
|
||||
)),
|
||||
Text(
|
||||
widget.text,
|
||||
style: const TextStyle(color: Colors.white),
|
||||
softWrap: true,
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
Widget _buildRowAlert() {
|
||||
return Row(children: [
|
||||
Flexible(
|
||||
flex: 0,
|
||||
child: Icon(
|
||||
widget.icon,
|
||||
color: Colors.white,
|
||||
)),
|
||||
Flexible(flex: 0, child: const SizedBox(width: 10)),
|
||||
Expanded(
|
||||
child:
|
||||
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
if (widget.title != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: Text(
|
||||
widget.title ?? "",
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold),
|
||||
softWrap: true,
|
||||
)),
|
||||
Text(
|
||||
widget.text,
|
||||
style: const TextStyle(color: Colors.white),
|
||||
softWrap: true,
|
||||
),
|
||||
]))
|
||||
]);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ReflexBox(
|
||||
color: widget.color ?? Globals.RP_PRIMARY_COLOR,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: widget.bigIcon == true
|
||||
? _buildColumnAlert()
|
||||
: _buildRowAlert()));
|
||||
}
|
||||
}
|
||||
33
lib/widgets/components/reflex_app_bar.dart
Normal file
33
lib/widgets/components/reflex_app_bar.dart
Normal file
@@ -0,0 +1,33 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../globals.dart';
|
||||
|
||||
class ReflexAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
final Function()? onBackCallback;
|
||||
|
||||
const ReflexAppBar({Key? key, required this.actions, this.onBackCallback})
|
||||
: super(key: key);
|
||||
|
||||
final List<Widget> actions;
|
||||
final webHeight = 200;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppBar(
|
||||
leading: onBackCallback != null
|
||||
? IconButton(
|
||||
icon: const Icon(Icons.arrow_back_ios, color: Colors.white),
|
||||
onPressed: onBackCallback,
|
||||
)
|
||||
: null,
|
||||
backgroundColor: Globals.RP_PRIMARY_COLOR,
|
||||
centerTitle: false,
|
||||
actions: actions,
|
||||
title: const Text('Reflex Platform', style: TextStyle(color: Colors.white)),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Size get preferredSize => Size.fromHeight(kToolbarHeight);
|
||||
}
|
||||
27
lib/widgets/components/reflex_box.dart
Normal file
27
lib/widgets/components/reflex_box.dart
Normal file
@@ -0,0 +1,27 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../globals.dart';
|
||||
|
||||
class ReflexBox extends StatefulWidget {
|
||||
final Widget child;
|
||||
final Color? color;
|
||||
|
||||
const ReflexBox({Key? key, this.color, required this.child})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_ReflexBoxState createState() => _ReflexBoxState();
|
||||
}
|
||||
|
||||
class _ReflexBoxState extends State<ReflexBox> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Material(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(5.0))),
|
||||
//backgrround
|
||||
color: widget.color ?? Globals.RP_BG_DARK_COLOR,
|
||||
child: widget.child);
|
||||
}
|
||||
}
|
||||
44
lib/widgets/components/reflex_button.dart
Normal file
44
lib/widgets/components/reflex_button.dart
Normal file
@@ -0,0 +1,44 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../globals.dart';
|
||||
|
||||
class ReflexButton extends StatelessWidget implements PreferredSizeWidget {
|
||||
final Function()? onPressed;
|
||||
final String text;
|
||||
final bool? isFullWidth;
|
||||
final Color? color;
|
||||
final Color? textColor;
|
||||
|
||||
const ReflexButton(
|
||||
{Key? key,
|
||||
this.onPressed,
|
||||
required this.text,
|
||||
this.isFullWidth,
|
||||
this.color,
|
||||
this.textColor})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
minimumSize: isFullWidth == true
|
||||
? const Size.fromHeight(36)
|
||||
: const Size(0, 36),
|
||||
backgroundColor: color ?? Globals.RP_PRIMARY_COLOR,
|
||||
foregroundColor: textColor ?? Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(5.0),
|
||||
),
|
||||
),
|
||||
onPressed: onPressed,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(text),
|
||||
));
|
||||
}
|
||||
|
||||
@override
|
||||
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
|
||||
}
|
||||
30
lib/widgets/components/reflex_circular_progress.dart
Normal file
30
lib/widgets/components/reflex_circular_progress.dart
Normal file
@@ -0,0 +1,30 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../globals.dart';
|
||||
|
||||
class ReflexCircularProgress extends StatefulWidget {
|
||||
final Color? color;
|
||||
final double? size;
|
||||
|
||||
const ReflexCircularProgress({Key? key, this.color, this.size})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_ReflexCircularProgressState createState() => _ReflexCircularProgressState();
|
||||
}
|
||||
|
||||
class _ReflexCircularProgressState extends State<ReflexCircularProgress> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: SizedBox(
|
||||
width: widget.size ?? 50.0,
|
||||
height: widget.size ?? 50.0,
|
||||
child: CircularProgressIndicator(
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
widget.color ?? Globals.RP_PRIMARY_COLOR),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sampleapp/globals.dart';
|
||||
|
||||
class ReflexDropdownButtonFormField<T> extends StatefulWidget {
|
||||
final List<DropdownMenuItem<T>> items;
|
||||
final T? value;
|
||||
final ValueChanged<T?>? onChanged;
|
||||
final String? label;
|
||||
final Widget? hint;
|
||||
final Widget? disabledHint;
|
||||
final ValueChanged<T?>? onSaved;
|
||||
final FormFieldValidator<T>? validator;
|
||||
final bool isExpanded;
|
||||
final bool isDense;
|
||||
final double? iconSize;
|
||||
final Color? iconEnabledColor;
|
||||
final Color? iconDisabledColor;
|
||||
final Color? dropdownColor;
|
||||
|
||||
const ReflexDropdownButtonFormField({
|
||||
Key? key,
|
||||
required this.items,
|
||||
this.value,
|
||||
this.onChanged,
|
||||
this.label,
|
||||
this.hint,
|
||||
this.disabledHint,
|
||||
this.onSaved,
|
||||
this.validator,
|
||||
this.isExpanded = false,
|
||||
this.isDense = false,
|
||||
this.iconSize,
|
||||
this.iconEnabledColor,
|
||||
this.iconDisabledColor,
|
||||
this.dropdownColor,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ReflexDropdownButtonFormFieldState<T> createState() => _ReflexDropdownButtonFormFieldState<T>();
|
||||
}
|
||||
|
||||
class _ReflexDropdownButtonFormFieldState<T> extends State<ReflexDropdownButtonFormField<T>> {
|
||||
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_focusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _requestFocus(){
|
||||
setState(() {
|
||||
FocusScope.of(context).requestFocus(_focusNode);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DropdownButtonFormField<T>(
|
||||
onTap: _requestFocus,
|
||||
focusNode: _focusNode,
|
||||
items: widget.items,
|
||||
value: widget.value,
|
||||
onChanged: widget.onChanged,
|
||||
decoration: InputDecoration(
|
||||
focusedBorder: const UnderlineInputBorder(
|
||||
borderSide: BorderSide(color: Globals.RP_PRIMARY_COLOR, width: 2.0),
|
||||
),
|
||||
labelText: widget.label,
|
||||
labelStyle: TextStyle(
|
||||
color: _focusNode.hasFocus ? Globals.RP_PRIMARY_COLOR : Colors.grey,
|
||||
),
|
||||
),
|
||||
hint: widget.hint,
|
||||
disabledHint: widget.disabledHint,
|
||||
onSaved: widget.onSaved,
|
||||
validator: widget.validator,
|
||||
isExpanded: widget.isExpanded,
|
||||
isDense: widget.isDense,
|
||||
iconSize: widget.iconSize ?? 24.0,
|
||||
iconEnabledColor: widget.iconEnabledColor,
|
||||
iconDisabledColor: widget.iconDisabledColor,
|
||||
dropdownColor: widget.dropdownColor,
|
||||
);
|
||||
}
|
||||
}
|
||||
195
lib/widgets/components/reflex_hu_info.dart
Normal file
195
lib/widgets/components/reflex_hu_info.dart
Normal file
@@ -0,0 +1,195 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:dart_core_sdk/handlingunit.pb.dart';
|
||||
import 'package:sampleapp/globals.dart';
|
||||
import 'package:sampleapp/widgets/components/reflex_alert.dart';
|
||||
import 'package:sampleapp/widgets/components/reflex_button.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
import 'reflex_box.dart';
|
||||
|
||||
class ReflexHUInfo extends StatefulWidget {
|
||||
final Handlingunit hu;
|
||||
final bool showArticles;
|
||||
|
||||
const ReflexHUInfo({super.key, required this.hu, required this.showArticles});
|
||||
|
||||
@override
|
||||
_ReflexHUInfoState createState() => _ReflexHUInfoState();
|
||||
}
|
||||
|
||||
class _ReflexHUInfoState extends State<ReflexHUInfo> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
String _translateUnit(String unit) {
|
||||
switch (unit) {
|
||||
case "KILOGRAM":
|
||||
return "kg";
|
||||
case "CENTIMETER":
|
||||
return "cm";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _copyToClipboard(String key, String value) {
|
||||
return Clipboard.setData(ClipboardData(text: value)).then((_) =>
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(SnackBar(content: Text("$key ${AppLocalizations.of(context)!.copied}"))));
|
||||
}
|
||||
|
||||
List<Widget> _buildArticles() {
|
||||
return [
|
||||
const SizedBox(height: 20),
|
||||
Text(AppLocalizations.of(context)!.items,
|
||||
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 5),
|
||||
Expanded(
|
||||
child: ReflexBox(
|
||||
child: Scrollbar(
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
shrinkWrap: true,
|
||||
children: [
|
||||
...widget.hu.payload.preparedContents.map((e) => Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: TextField(
|
||||
enabled: false,
|
||||
style: const TextStyle(
|
||||
color: Colors.black,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
labelText: AppLocalizations.of(context)!.itemId,
|
||||
),
|
||||
controller:
|
||||
TextEditingController(text: e.goods.itemID),
|
||||
)),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: TextField(
|
||||
enabled: false,
|
||||
style: const TextStyle(
|
||||
color: Colors.black,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
labelText: AppLocalizations.of(context)!.quantity,
|
||||
),
|
||||
controller: TextEditingController(
|
||||
text: e.quantity.value!.toString()),
|
||||
)),
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
)),
|
||||
];
|
||||
}
|
||||
|
||||
Widget _buildHU() {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(AppLocalizations.of(context)!.informations,
|
||||
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 5),
|
||||
ReflexBox(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Column(children: [
|
||||
TextField(
|
||||
enabled: false,
|
||||
style: const TextStyle(
|
||||
fontSize: 24,
|
||||
color: Colors.black,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
labelText: AppLocalizations.of(context)!.handlingUnitIdentifier,
|
||||
),
|
||||
controller: TextEditingController(text: widget.hu.iD.refID),
|
||||
),
|
||||
TextField(
|
||||
readOnly: true,
|
||||
style: const TextStyle(
|
||||
color: Colors.black,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
suffixIcon: IconButton(
|
||||
onPressed: () => _copyToClipboard(AppLocalizations.of(context)!.trackingNumber,
|
||||
widget.hu.payload.currentTrackingSummary.trackingID),
|
||||
icon: const Icon(Icons.copy)),
|
||||
border: InputBorder.none,
|
||||
labelText: AppLocalizations.of(context)!.trackingNumber,
|
||||
labelStyle: const TextStyle(color: Colors.grey),
|
||||
),
|
||||
controller: TextEditingController(
|
||||
text: widget.hu.payload.currentTrackingSummary.trackingID),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Flexible(
|
||||
flex: 2,
|
||||
child: TextField(
|
||||
enabled: false,
|
||||
style: const TextStyle(
|
||||
color: Colors.black,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
labelText: AppLocalizations.of(context)!.handlingUnitType,
|
||||
),
|
||||
controller: TextEditingController(
|
||||
text: widget.hu.payload.information.containerType),
|
||||
)),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: TextField(
|
||||
enabled: false,
|
||||
style: const TextStyle(
|
||||
color: Colors.black,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
labelText: AppLocalizations.of(context)!.dimensions,
|
||||
),
|
||||
controller: TextEditingController(
|
||||
text:
|
||||
"${widget.hu.payload.information.height.value} x ${widget.hu.payload.information.width.value} x ${widget.hu.payload.information.length!.value} ${_translateUnit(widget.hu.payload.information.length.unit.name)}"),
|
||||
)),
|
||||
Flexible(
|
||||
child: TextField(
|
||||
enabled: false,
|
||||
style: const TextStyle(
|
||||
color: Colors.black,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
labelText: AppLocalizations.of(context)!.weight
|
||||
),
|
||||
controller: TextEditingController(
|
||||
text:
|
||||
"${widget.hu.payload.information.weight.value} ${_translateUnit(widget.hu.payload.information.weight.unit.name)}"),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
]),
|
||||
)),
|
||||
if (widget.showArticles) ..._buildArticles(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _buildHU();
|
||||
}
|
||||
}
|
||||
69
lib/widgets/components/reflex_signature.dart
Normal file
69
lib/widgets/components/reflex_signature.dart
Normal file
@@ -0,0 +1,69 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncfusion_flutter_signaturepad/signaturepad.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import '../../globals.dart';
|
||||
|
||||
class ReflexSignature extends StatefulWidget {
|
||||
final GlobalKey<SfSignaturePadState> signaturePadKey;
|
||||
|
||||
ReflexSignature({Key? key, required this.signaturePadKey}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ReflexSignatureState createState() => _ReflexSignatureState();
|
||||
}
|
||||
|
||||
class _ReflexSignatureState extends State<ReflexSignature> {
|
||||
bool isInputFocused = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InputDecorator(
|
||||
isFocused: isInputFocused,
|
||||
decoration: InputDecoration(
|
||||
focusColor: Globals.RP_PRIMARY_COLOR,
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide:
|
||||
const BorderSide(color: Globals.RP_PRIMARY_COLOR, width: 2.0),
|
||||
borderRadius: BorderRadius.circular(10.0),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide:
|
||||
const BorderSide(color: Globals.RP_LIGHT_COLOR, width: 1.0),
|
||||
borderRadius: BorderRadius.circular(10.0),
|
||||
),
|
||||
labelText: AppLocalizations.of(context)!.signature,
|
||||
),
|
||||
child: Stack(children: [
|
||||
SfSignaturePad(
|
||||
key: widget.signaturePadKey,
|
||||
minimumStrokeWidth: 2,
|
||||
maximumStrokeWidth: 2,
|
||||
strokeColor: Colors.black,
|
||||
onDrawStart: () {
|
||||
setState(() {
|
||||
isInputFocused = true;
|
||||
});
|
||||
return false;
|
||||
},
|
||||
onDrawEnd: () {
|
||||
setState(() {
|
||||
isInputFocused = false;
|
||||
});
|
||||
},
|
||||
),
|
||||
Positioned(
|
||||
right: 0,
|
||||
top: 0,
|
||||
child: CircleAvatar(
|
||||
backgroundColor: Globals.RP_BG_DARK_COLOR,
|
||||
child: IconButton(
|
||||
color: Colors.black,
|
||||
onPressed: () {
|
||||
widget.signaturePadKey.currentState!.clear();
|
||||
},
|
||||
icon: const Icon(Icons.clear))),
|
||||
)
|
||||
]));
|
||||
}
|
||||
}
|
||||
74
lib/widgets/components/reflex_text_form_field.dart
Normal file
74
lib/widgets/components/reflex_text_form_field.dart
Normal file
@@ -0,0 +1,74 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../globals.dart';
|
||||
|
||||
class ReflexTextFormField extends StatefulWidget {
|
||||
final String? initialValue;
|
||||
final ValueChanged<String>? onChanged;
|
||||
final FormFieldValidator<String>? validator;
|
||||
final bool obscureText;
|
||||
final TextInputType keyboardType;
|
||||
final String? label;
|
||||
final TextEditingController? controller;
|
||||
|
||||
const ReflexTextFormField({
|
||||
Key? key,
|
||||
this.initialValue,
|
||||
this.onChanged,
|
||||
this.validator,
|
||||
this.obscureText = false,
|
||||
this.keyboardType = TextInputType.text,
|
||||
this.label,
|
||||
this.controller,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ReflexTextFormFieldState createState() => _ReflexTextFormFieldState();
|
||||
}
|
||||
|
||||
class _ReflexTextFormFieldState extends State<ReflexTextFormField> {
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
late TextEditingController _controller;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = widget.controller ?? TextEditingController(text: widget.initialValue);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_focusNode.dispose();
|
||||
if (widget.controller == null) {
|
||||
_controller.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _requestFocus() {
|
||||
setState(() {
|
||||
FocusScope.of(context).requestFocus(_focusNode);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextFormField(
|
||||
controller: _controller,
|
||||
focusNode: _focusNode,
|
||||
onTap: _requestFocus,
|
||||
onChanged: widget.onChanged,
|
||||
obscureText: widget.obscureText,
|
||||
keyboardType: widget.keyboardType,
|
||||
validator: widget.validator,
|
||||
decoration: InputDecoration(
|
||||
focusedBorder: const UnderlineInputBorder(
|
||||
borderSide: BorderSide(color: Globals.RP_PRIMARY_COLOR, width: 2.0),
|
||||
),
|
||||
labelText: widget.label,
|
||||
labelStyle: TextStyle(color:
|
||||
_focusNode.hasFocus ? Globals.RP_PRIMARY_COLOR : Colors.black
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user