Reputation: 3592
I've create a custom widget for time picking.
The widget contains an icon which opens a TimePicker, and a TextFormField so the user can type the time value manually.
When the user types a value it immediately validated and also when the focus is off, it validate the value and update the field with correct time format.
For example, if the user types 8 and then clicks next widget, it will update to 8:00
Checkout the form image with 2 TimePickers:
What I want is that when user types StartTime, and then clicks the keyboard Next button, the focus will move to the EndTime picker. Then when the user clicks Next button on the EndTime Picker the focus will move to the next widget in the form
The problem is that the FocusNode is inside the TimePicker custom widget (which is StateFull) and I couldn't figure out how it can be exposed outside of it.
You can see the code for it here: https://github.com/moti0375/tikal_time_tracker/blob/develop/lib/ui/time_picker.dart
Any idea will be appreciated.
Upvotes: 2
Views: 10964
Reputation: 3592
Finally I've figured it out,
Instead of creating the FocusNode inside the picker widget (a child widget), I've created the FocusNode in the parent widget (the form) and provide it to the child widget in its constructor, by this the focus node created in the parent widget context.
Then, I've added a request focus method to the child widgets so the parent can call them and FocusScope.of(context).requestFocus(focusNode);
is called inside the child widgets but on the focusNode that provided by the parent widget.
Here is a portion of the code:
Child widget:
class TimeTrackerTimePicker extends StatefulWidget {
final FocusNode focusNode;
TimeTrackerTimePicker({ this.focusNode});
//This can be called from the parent widget with the parent context
void requestFocus(BuildContext context){
print("${this.pickerName} requestFocus...");
FocusScope.of(context).requestFocus(focusNode);
}
....
....
@override
State<StatefulWidget> createState() {
return TimePickerState();
}
}
State class:
class TimePickerState extends State<TimeTrackerTimePicker> {
@override
Widget build(BuildContext context) {
return Container(
....
child: new Flexible(
child: new TextFormField(
textInputAction: TextInputAction.next,
focusNode: widget.focusNode, //linking to the focusNode
onFieldSubmitted: onSubmitButtonClicked,
decoration: InputDecoration(
hintText: widget.hint != null ? widget.hint : "",
contentPadding:
EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0))),
maxLines: 1,
controller: pickerController))
)
}
}
Then in the parent widget when you need to set focus:
FocusNode focusNode;
TimeTrackerTimePicker timePicker;
@override
void initState() {
super.initState();
focusNode = new FocusNode();
timePicker = new TimeTrackerTimePicker(focusNode: focusNode);
}
.....
//request focus when required..
void requestPickerFocus(){
timePicker.requestFocus(context);
}
Upvotes: 7