Skip to content
This repository was archived by the owner on Apr 29, 2021. It is now read-only.

Commit 39adc50

Browse files
authored
Merge pull request #178 from UnityTech/yczhang
Text Form Field
2 parents c2e54c7 + be255cf commit 39adc50

File tree

4 files changed

+181
-14
lines changed

4 files changed

+181
-14
lines changed

Runtime/material/text_field.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ public override void debugFillProperties(DiagnosticPropertiesBuilder properties)
161161
properties.add(new EnumProperty<TextCapitalization>("textCapitalization", this.textCapitalization, defaultValue: TextCapitalization.none));
162162
properties.add(new EnumProperty<TextAlign>("textAlign", this.textAlign, defaultValue: TextAlign.left));
163163
properties.add(new EnumProperty<TextDirection>("textDirection", this.textDirection, defaultValue: null));
164-
properties.add(new FloatProperty("cursorWidth", this.cursorWidth, defaultValue: 2.0));
164+
properties.add(new FloatProperty("cursorWidth", this.cursorWidth, defaultValue: 2.0f));
165165
properties.add(new DiagnosticsProperty<Radius>("cursorRadius", this.cursorRadius, defaultValue: null));
166166
properties.add(new DiagnosticsProperty<Color>("cursorColor", this.cursorColor, defaultValue: null));
167167
properties.add(new DiagnosticsProperty<Brightness?>("keyboardAppearance", this.keyboardAppearance, defaultValue: null));

Runtime/material/text_form_field.cs

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
using System.Collections.Generic;
2+
using Unity.UIWidgets.foundation;
3+
using Unity.UIWidgets.material;
4+
using Unity.UIWidgets.painting;
5+
using Unity.UIWidgets.service;
6+
using Unity.UIWidgets.ui;
7+
using Unity.UIWidgets.widgets;
8+
using TextStyle = Unity.UIWidgets.painting.TextStyle;
9+
10+
namespace UIWidgets.Runtime.material {
11+
public class TextFormField : FormField<string> {
12+
public TextFormField(
13+
Key key = null,
14+
TextEditingController controller = null,
15+
string initialValue = null,
16+
FocusNode focusNode = null,
17+
InputDecoration decoration = null,
18+
TextInputType keyboardType = null,
19+
TextCapitalization textCapitalization = TextCapitalization.none,
20+
TextInputAction? textInputAction = null,
21+
TextStyle style = null,
22+
TextDirection? textDirection = null,
23+
TextAlign textAlign = TextAlign.left,
24+
bool autofocus = false,
25+
bool obscureText = false,
26+
bool autocorrect = true,
27+
bool autovalidate = false,
28+
bool maxLengthEnforced = true,
29+
int maxLines = 1,
30+
int? maxLength = null,
31+
VoidCallback onEditingComplete = null,
32+
ValueChanged<string> onFieldSubmitted = null,
33+
FormFieldSetter<string> onSaved = null,
34+
FormFieldValidator<string> validator = null,
35+
List<TextInputFormatter> inputFormatters = null,
36+
bool enabled = true,
37+
float cursorWidth = 2.0f,
38+
Radius cursorRadius = null,
39+
Color cursorColor = null,
40+
Brightness? keyboardAppearance = null,
41+
EdgeInsets scrollPadding = null,
42+
bool enableInteractiveSelection = true,
43+
InputCounterWidgetBuilder buildCounter = null
44+
) : base(
45+
key: key,
46+
initialValue: controller != null ? controller.text : (initialValue ?? ""),
47+
onSaved: onSaved,
48+
validator: validator,
49+
autovalidate: autovalidate,
50+
enabled: enabled,
51+
builder: (FormFieldState<string> field) => {
52+
_TextFormFieldState state = (_TextFormFieldState) field;
53+
InputDecoration effectiveDecoration = (decoration ?? new InputDecoration())
54+
.applyDefaults(Theme.of(field.context).inputDecorationTheme);
55+
return new TextField(
56+
controller: state._effectiveController,
57+
focusNode: focusNode,
58+
decoration: effectiveDecoration.copyWith(errorText: field.errorText),
59+
keyboardType: keyboardType,
60+
textInputAction: textInputAction,
61+
style: style,
62+
textAlign: textAlign,
63+
textDirection: textDirection ?? TextDirection.ltr,
64+
textCapitalization: textCapitalization,
65+
autofocus: autofocus,
66+
obscureText: obscureText,
67+
autocorrect: autocorrect,
68+
maxLengthEnforced: maxLengthEnforced,
69+
maxLines: maxLines,
70+
maxLength: maxLength,
71+
onChanged: field.didChange,
72+
onEditingComplete: onEditingComplete,
73+
onSubmitted: onFieldSubmitted,
74+
inputFormatters: inputFormatters,
75+
enabled: enabled,
76+
cursorWidth: cursorWidth,
77+
cursorRadius: cursorRadius,
78+
cursorColor: cursorColor,
79+
scrollPadding: scrollPadding ?? EdgeInsets.all(20.0f),
80+
keyboardAppearance: keyboardAppearance,
81+
enableInteractiveSelection: enableInteractiveSelection,
82+
buildCounter: buildCounter
83+
);
84+
}
85+
) {
86+
D.assert(initialValue == null || controller == null);
87+
D.assert(maxLines > 0);
88+
D.assert(maxLength == null || maxLength > 0);
89+
this.controller = controller;
90+
}
91+
92+
public readonly TextEditingController controller;
93+
94+
public override State createState() {
95+
return new _TextFormFieldState();
96+
}
97+
}
98+
99+
class _TextFormFieldState : FormFieldState<string> {
100+
TextEditingController _controller;
101+
102+
public TextEditingController _effectiveController {
103+
get { return this.widget.controller ?? this._controller; }
104+
}
105+
106+
public new TextFormField widget {
107+
get { return (TextFormField) base.widget; }
108+
}
109+
110+
public override void initState() {
111+
base.initState();
112+
if (this.widget.controller == null) {
113+
this._controller = new TextEditingController(text: this.widget.initialValue);
114+
}
115+
else {
116+
this.widget.controller.addListener(this._handleControllerChanged);
117+
}
118+
}
119+
120+
public override void didUpdateWidget(StatefulWidget _oldWidget) {
121+
TextFormField oldWidget = _oldWidget as TextFormField;
122+
base.didUpdateWidget(oldWidget);
123+
if (this.widget.controller != oldWidget.controller) {
124+
oldWidget.controller?.removeListener(this._handleControllerChanged);
125+
this.widget.controller?.addListener(this._handleControllerChanged);
126+
127+
if (oldWidget.controller != null && this.widget.controller == null) {
128+
this._controller = TextEditingController.fromValue(oldWidget.controller.value);
129+
}
130+
131+
if (this.widget.controller != null) {
132+
this.setValue(this.widget.controller.text);
133+
if (oldWidget.controller == null) {
134+
this._controller = null;
135+
}
136+
}
137+
}
138+
}
139+
140+
public override void dispose() {
141+
this.widget.controller?.removeListener(this._handleControllerChanged);
142+
base.dispose();
143+
}
144+
145+
public override void reset() {
146+
base.reset();
147+
this.setState(() => { this._effectiveController.text = (string) this.widget.initialValue; });
148+
}
149+
150+
void _handleControllerChanged() {
151+
if (this._effectiveController.text != this.value) {
152+
this.didChange(this._effectiveController.text);
153+
}
154+
}
155+
}
156+
}

Runtime/material/text_form_field.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/widgets/form.cs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public override State createState() {
3838

3939
public class FormState : State<Form> {
4040
int _generation = 0;
41-
public readonly HashSet<FormFieldState<dynamic>> _fields = new HashSet<FormFieldState<dynamic>>();
41+
readonly HashSet<FormFieldState> _fields = new HashSet<FormFieldState>();
4242

4343
public FormState() {
4444
}
@@ -55,11 +55,11 @@ void _forceRebuild() {
5555
this.setState(() => { ++this._generation; });
5656
}
5757

58-
public void _register(FormFieldState<dynamic> field) {
58+
public void _register(FormFieldState field) {
5959
this._fields.Add(field);
6060
}
6161

62-
public void _unregister(FormFieldState<dynamic> field) {
62+
public void _unregister(FormFieldState field) {
6363
this._fields.Remove(field);
6464
}
6565

@@ -78,28 +78,28 @@ public override Widget build(BuildContext context) {
7878
);
7979
}
8080

81-
void save() {
82-
foreach (FormFieldState<dynamic> field in this._fields) {
81+
public void save() {
82+
foreach (FormFieldState field in this._fields) {
8383
field.save();
8484
}
8585
}
8686

87-
void reset() {
88-
foreach (FormFieldState<dynamic> field in this._fields) {
87+
public void reset() {
88+
foreach (FormFieldState field in this._fields) {
8989
field.reset();
9090
}
9191

9292
this._fieldDidChange();
9393
}
9494

95-
bool validate() {
95+
public bool validate() {
9696
this._forceRebuild();
9797
return this._validate();
9898
}
9999

100100
bool _validate() {
101101
bool hasError = false;
102-
foreach (FormFieldState<dynamic> field in this._fields) {
102+
foreach (FormFieldState field in this._fields) {
103103
hasError = !field.validate() || hasError;
104104
}
105105

@@ -175,7 +175,15 @@ public override State createState() {
175175
}
176176
}
177177

178-
public class FormFieldState<T> : State<FormField<T>> where T : class {
178+
public interface FormFieldState {
179+
void save();
180+
181+
bool validate();
182+
183+
void reset();
184+
}
185+
186+
public class FormFieldState<T> : State<FormField<T>>, FormFieldState where T : class {
179187
T _value;
180188
string _errorText;
181189

@@ -197,7 +205,7 @@ public void save() {
197205
}
198206
}
199207

200-
public void reset() {
208+
public virtual void reset() {
201209
this.setState(() => {
202210
this._value = this.widget.initialValue;
203211
this._errorText = null;
@@ -232,7 +240,7 @@ public override void initState() {
232240
}
233241

234242
public override void deactivate() {
235-
Form.of(this.context)?._unregister(this as FormFieldState<dynamic>);
243+
Form.of(this.context)?._unregister(this);
236244
base.deactivate();
237245
}
238246

@@ -241,7 +249,7 @@ public override Widget build(BuildContext context) {
241249
this._validate();
242250
}
243251

244-
Form.of(context)?._register(this as FormFieldState<dynamic>);
252+
Form.of(context)?._register(this);
245253
return this.widget.builder(this);
246254
}
247255
}

0 commit comments

Comments
 (0)