[英]Why does my widget rebuild when I use keyboard
I have this issue of rebuilding widget when The keyboards shows up.当键盘出现时,我遇到了重建小部件的问题。 I tried to use the sizer package but never could figure out how to get it to work when I go back from this screen everything in the previous screen will rebuild, Please note: If I don't click on the
typeaheadwidget
such that the keyboard doesn't show up the state is preserved in the previous screen but as soon as the keyboard pops up the widgets get rebuilt Could you please check?我尝试使用 sizer package,但是当我从该屏幕返回 go 时,我一直无法弄清楚如何让它工作,之前屏幕中的所有内容都将重建,请注意:如果我不单击
typeaheadwidget
,则键盘不会't show up state 保留在前一个屏幕中,但一旦弹出键盘,小部件就会重建 你能检查一下吗?
class SearchScreen extends StatefulWidget {
@override
_SearchScreenState createState() => _SearchScreenState();
}
class _SearchScreenState extends State<SearchScreen> {
TextEditingController pickUpTextEditingController = TextEditingController();
TextEditingController dropOffTextEditingController = TextEditingController();
@override
void initState() {
super.initState();
}
@override
@mustCallSuper
Widget build(BuildContext context) {
String placeAddress =
Provider.of<AppData>(context).pickUpLocation.placeName ?? "";
pickUpTextEditingController.text = placeAddress;
return Scaffold(
resizeToAvoidBottomInset: false,
body: Stack(
children: [
Container(
height: 250.0,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black,
blurRadius: 6.0,
spreadRadius: 0.5,
offset: Offset(0.7, 0.7),
)
],
),
child: Padding(
padding: EdgeInsets.only(
left: 25.0, top: 30.0, right: 25.0, bottom: 20.0),
child: Column(
children: [
SizedBox(height: 5.0),
Stack(
children: [
GestureDetector(
onTap: () {
Navigator.pop(
//send back data
context,
dropOffTextEditingController.text);
},
child: Icon(Icons.arrow_back)),
Center(
child: Text(
"Set Drop Off",
style: TextStyle(
fontSize: 18.0, fontFamily: "Brand-Bold"),
),
)
],
),
SizedBox(height: 16.0),
Row(
children: [
Image.asset("images/images/pickicon.png",
height: 16.0, width: 16.0),
SizedBox(width: 18.0),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.grey[400],
borderRadius: BorderRadius.circular(5.0),
),
child: Padding(
padding: EdgeInsets.all(3.0),
child: TextField(
controller: pickUpTextEditingController,
decoration: InputDecoration(
hintText: "PickUp Location",
fillColor: Colors.grey[400],
filled: true,
border: InputBorder.none,
isDense: true,
contentPadding: EdgeInsets.only(
left: 11.0, top: 8.0, bottom: 8.0),
),
),
),
))
],
),
SizedBox(height: 10.0),
Row(
children: [
Image.asset("images/images/desticon.png",
height: 16.0, width: 16.0),
SizedBox(width: 18.0),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.grey[400],
borderRadius: BorderRadius.circular(5.0),
),
child: Padding(
padding: EdgeInsets.all(3.0),
child: TypeAheadField(
itemBuilder: null,
onSuggestionSelected: null,
suggestionsCallback: null,
),
),
),
),
],
),
],
),
),
),
],
),
);
}
}
You should not try to control when the build
method is called.您不应该尝试控制何时调用
build
方法。 Flutter will call build
when it decides it needs to (eg keyboard appears, device rotated, parent rebuilds, etc). Flutter 将在需要时调用
build
(例如,键盘出现、设备旋转、父级重建等)。
Instead, you should make sure that your build method is a "pure" function.相反,您应该确保您的构建方法是“纯”函数。 In Flutter specifically, this means that you should not perform any action with "side-effects" (basically anything which modifies the state of the app).
特别是在 Flutter 中,这意味着您不应该执行任何带有“副作用”的操作(基本上是任何修改应用程序状态的操作)。
For example:例如:
Widget build(BuildContext context) {
final x = 2 + 3; // fine, nothing else is modified
final state = context.watch<MyModel>(); // also fine, only reading data
controller.text = "hello"; // BAD, modifies the state of the app
return ...;
}
Instead, you should move your logic with side effects into other lifecycle methods (eg initState()
, didChangeDepencencies()
, etc).相反,您应该将具有副作用的逻辑移至其他生命周期方法(例如
initState()
、 didChangeDepencencies()
等)。
For example, if you want to set your text field to a particular string when it first appears, you can use initState
:例如,如果您想在文本字段首次出现时将其设置为特定字符串,您可以使用
initState
:
class _SearchScreenState extends State<SearchScreen> {
@override
void initState() {
super.initState();
final data = context.read<AppData>();
controller.text = data.pickUpLocation.placeName ?? "";
}
Widget build(BuildContext context) {
// ...
}
}
Now build()
can be called whenever it has to be, without resetting the state of your text field.现在
build()
可以随时调用,而无需重置文本字段的状态。
Note that, even if there was some way to prevent your widget from being rebuilt, this is also likely not what you want, since the UI would not update to accommodate the keyboard.请注意,即使有某种方法可以防止您的小部件被重建,这也可能不是您想要的,因为 UI 不会更新以适应键盘。
the only reason why your widgets got rebuilds after keyboard pop up.键盘弹出后您的小部件重建的唯一原因。 is that one or more of your widgets size depends on MediaQuery.
是您的一个或多个小部件大小取决于 MediaQuery。
you can try to ge your screen size from LayoutBuilder as an alternative for MediaQuery.您可以尝试从 LayoutBuilder 获取屏幕大小作为 MediaQuery 的替代方案。
When you tap the TextField
widget, it makes the keyboard show up.当您点击
TextField
小部件时,它会显示键盘。 And when the keyboard shows up, your screen size changes.当键盘出现时,您的屏幕尺寸会发生变化。 This causes the rebuild
这导致重建
`give the textfield initial value like this: initvalue:Provider.of(context).pickUpLocation.placeName?? `像这样给文本字段初始值:initvalue:Provider.of(context).pickUpLocation.placeName?? ""
“”
and use onchange method in text feild instead of text editing controller like this: onchange(value){ Provider.of(context).pickUpLocation.placeName=value;}`并在文本字段中使用 onchange 方法,而不是像这样编辑 controller:onchange(value){ Provider.of(context).pickUpLocation.placeName=value;}`
I am also facing the same issue, My blocBuidler is getting rebuilt every time when click on textfield or keyboard is appear.我也面临同样的问题,每次单击文本字段或出现键盘时,我的 blocBuidler 都会重建。
In my case, I was calling the event in parent BlocBuilder so whenever I pressed on textfields the parent BlocBuilder is called the event, so it builds state of child BlocBuilder在我的例子中,我在父 BlocBuilder 中调用事件,所以每当我按下文本字段时,父 BlocBuilder 就被称为事件,因此它构建了子 BlocBuilder 的 state
Make sure you are also doing the same thing.确保你也在做同样的事情。 If you are doing the same thing please check the state whether it is already built or not.
如果您正在做同样的事情,请检查 state 是否已经构建。
(BlocProvider.of<YourBlocName>(context).state is YouBlocState) ? Print('do nothing'): BlocProvider.of<YourBlocName>(context).add(youBlocEvent);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.