Skip to content

Instantly share code, notes, and snippets.

@jaumard
Last active November 23, 2020 12:46
Show Gist options
  • Save jaumard/c3f1f2188882317c1ddd46a604de0dae to your computer and use it in GitHub Desktop.
Save jaumard/c3f1f2188882317c1ddd46a604de0dae to your computer and use it in GitHub Desktop.
FocusScope bug
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class Bloc {
final StreamController<String> _name = StreamController.broadcast();
final StreamController<String> _firstName = StreamController.broadcast();
final StreamController<String> _secondaryName = StreamController.broadcast();
Stream<String> get name => _name.stream;
Stream<String> get firstName => _firstName.stream;
Stream<String> get secondaryName => _secondaryName.stream;
Sink<String> get updateName => _name.sink;
Sink<String> get updateFirstName => _firstName.sink;
Sink<String> get updateSecondaryName => _secondaryName.sink;
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _bloc = Bloc();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: FocusTraversalGroup(
policy: OrderedTraversalPolicy(),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_CustomTextField(
order: 1,
stream: _bloc.firstName,
sink: _bloc.updateFirstName,
label: 'firstNameField',
),
_CustomTextField(
order: 2,
stream: _bloc.name,
sink: _bloc.updateName,
label: 'nameField',
),
_CustomTextField(
order: 3,
stream: _bloc.secondaryName,
sink: _bloc.updateSecondaryName,
label: 'secondaryLastNameField',
),
],
),
),
);
}
}
class _CustomTextField extends StatelessWidget {
final Stream<String> stream;
final Sink<String> sink;
final String label;
final TextInputAction textInputAction;
final double order;
_CustomTextField({this.order, this.label, this.textInputAction, this.stream, this.sink, Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return FocusTraversalOrder(
order: NumericFocusOrder(order),
child: StreamBuilder(
stream: stream,
builder: (_, snapshot) {
final text = snapshot;
return TextField(
decoration: InputDecoration(
labelText: label,
// ignore: avoid_as
errorText: (text.error)?.toString(),
),
textInputAction: textInputAction ?? TextInputAction.next,
onSubmitted: (_) {
print('submitted order $order');
if (textInputAction == TextInputAction.done) {
FocusScope.of(context).unfocus();
} else {
FocusScope.of(context).nextFocus();
}
},
);
},
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment