#dart #flutter
#dart #flutter
Вопрос:
У меня есть нижняя навигация в родительском виджете и несколько текстовых полей в дочернем виджете. Когда пользователь нажимает на вкладку навигации, и если одно из текстовых полей пусто, он установит фокус на определенные текстовые поля.
Я использую метод конструктора, которому научился у одного из разработчиков, однако я не смог заставить его работать. Похоже, я неправильно передал контекст. Я не уверен.
Кто-нибудь может заметить мои ошибки или посоветовать другие методы, которые могут достичь того же результата?
login.dart
class Login extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return _LoginState();
}
}
class _LoginState extends State<Login> {
FocusNode focusNode;
Page1 focus;
@override
void initState() {
super.initState();
focusNode = new FocusNode();
focus = new Page1(focusNode: focusNode);
}
int currentBottomNavIndex = 0;
List<Widget> bottomNav = [
Page1(),
Page2(),
];
onTapped(int index) {
//if(textfield not empty) {
//setState(() {
//currentBottomNavIndex = index;
//});
//}else {
focus.setFocus(context);
//}
}
@override
Widget build(BuildContext context){
return new Scaffold(
appBar: new AppBar(
title: Text('Login Page'),
),
body: bottomNav[currentBottomNavIndex],
bottomNavigationBar: BottomNavigationBar(
onTap: onTapped,
//onTap: requestFocus(context),
currentIndex: currentBottomNavIndex,
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text("Page1"),
),
BottomNavigationBarItem(
icon: Icon(Icons.mail),
title: Text('Page2'),
),
],
),
);
}
}
страница 1.dart
class Page1 extends StatefulWidget {
final FocusNode focusNode;
const Page1({Key key, this.focusNode}) : super(key: key);
void setFocus(BuildContext context) {
print("$focusNode requestFocus...");
FocusScope.of(context).requestFocus(focusNode);
}
@override
State<StatefulWidget> createState() {
return _Page1State();
}
}
class _Page1State extends State<Page1> {
TextEditingController name1 = TextEditingController();
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
body: SingleChildScrollView(
child: Column(
children: <Widget>[
nameApp(),
],
)
)
);
}
Widget nameApp(){
return Container(
margin: EdgeInsets.all(50.0),
//width: 185,
child: Center(
child: Row(
children: [
Container(
child: Text("Name :", style: TextStyle(fontSize: 15), ),
),
Container(
child: Flexible(
child: TextField(
focusNode: widget.focusNode,
controller: name1,
onTap: (){
name1.clear();
},
onChanged: (String str){
},
textAlign: TextAlign.center,
decoration: InputDecoration(
contentPadding: EdgeInsets.symmetric(vertical: 5),
hintText: "Full Name",
hintStyle: TextStyle(fontSize: 14),
),
),
),
),
]
)
)
);
}
}
Когда пользователь нажимает на нижнюю вкладку, я ожидаю увидеть, что текстовое поле находится в фокусе, однако ничего не происходит.
Я заметил, что метод в дочернем виджете был вызван:
флаттер: запрос фокусного узла #419f4 на фокусировку … флаттер: запрос фокусного узла #419f4 (СФОКУСИРОВАННЫЙ) на фокусировку…
однако текстовое поле по-прежнему не в фокусе.
Комментарии:
1. Я попробовал «распечатать (context.hashcode)» для родительского и дочернего виджетов. Разные значения. Есть ли способ вызвать дочерний контекст из родительского виджета?
2. Я решил проблему, я неправильно передал параметр дочернему виджету. Поместите приведенный ниже код в разделе Сборка виджета в родительском виджете и отредактируйте список параметров страницы 1<Виджет> bottomNav = [ Страница 1(focusNode: focusNode), Страница 2(), ];
Ответ №1:
Я создал простой пример проекта для этого, и у меня он работает просто отлично. Пожалуйста, ознакомьтесь с моим решением:
Домашняя страница:
import 'package:flutter/material.dart';
import 'package:focus_node/widgets/MyInputWidget.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
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> {
FocusNode field1FocusNode = FocusNode(); //Create first FocusNode
FocusNode field2FocusNode = FocusNode(); //Create second FocusNode
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 35),
child: MyInputWidget(
focusNode: field1FocusNode, //Provide the first FocusNode in the constructor
hint: "Email",
onEditCompleted: (){
FocusScope.of(context).requestFocus(field2FocusNode); //Request focus
},
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 35),
child: MyInputWidget(
focusNode: field2FocusNode, //Provide the second FocusNode
hint: "Password",
onEditCompleted: (){
FocusScope.of(context).requestFocus(field1FocusNode); //Request focus
},
),
)
],
),
),
);
}
}
Пользовательский виджет требовал фокусировки:
class MyInputWidget extends StatefulWidget {
final FocusNode focusNode;
final String hint;
final VoidCallback onEditCompleted;
MyInputWidget({this.focusNode, this.hint, this.onEditCompleted});
@override
_MyInputWidgetState createState() => _MyInputWidgetState();
}
class _MyInputWidgetState extends State<MyInputWidget> {
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(8),
child: TextField(
focusNode: widget.focusNode, //The FocusNode provided by the parent widget
decoration: InputDecoration(
hintText: widget.hint
),
onEditingComplete: widget.onEditCompleted,
),
);
}
}
Надеюсь, это поможет.
Комментарии:
1. Привет, Моти, после просмотра твоего кода я понимаю, что неправильно передал параметры. Я решил проблему, разместив приведенный ниже код в разделе Сборка виджета в родительском виджете и отредактировав список параметров страницы 1<Виджет> bottomNav = [Страница 1 (focusNode: focusNode), страница 2(), ]; Спасибо за помощь!!
2. Правильно! пропустил это .. Ура! Однако в следующий раз добавьте аннотацию @required к полям конструктора, это избавит вас от забывания параметров!