每当我关闭键盘时,我在
TextField
中写入的文本就会被重置/清空。
在试图找出导致此行为的问题时,我开始了解到打开和关闭 TextField
会导致应用程序重建。
这是我遇到问题的代码:
part of quizui;
class ShowDescription extends StatefulWidget {
const ShowDescription({Key? key,required this.descriptionAsString,required this.isItForFB,required this.isForResult}) : super(key: key);
final bool isForResult;
final bool isItForFB;
final String descriptionAsString;
@override
State<ShowDescription> createState() => _ShowDescriptionState();
}
class _ShowDescriptionState extends State<ShowDescription> {
List<dynamic> descriptionData = [];
int tempIndex = 0;
late InAppWebViewController webView;
InAppWebViewGroupOptions options = InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
useShouldOverrideUrlLoading: true,
mediaPlaybackRequiresUserGesture: false,
),
android: AndroidInAppWebViewOptions(
useHybridComposition: true,
),
ios: IOSInAppWebViewOptions(
allowsInlineMediaPlayback: true,
),
);
List <TextEditingController> textControllers = [];
@override
void initState(){
super.initState();
WidgetsBinding.instance?.addPostFrameCallback((_) {
FillInTheBlankWidgetState.callBackDescription = (){
textControllerListForFB.clear();
print("description callback running");
for(TextEditingController i in textControllers){
textControllerListForFB.add(i.text);
}
};
});
}
@override
void dispose() {
for (var controller in textControllers) {
controller.dispose();
}
super.dispose();
}
@override
Widget build(BuildContext context) {
print("Rebuilding Show Description-----");
if (widget.descriptionAsString != "") {
descriptionData = jsonDecode(widget.descriptionAsString);
}
// textControllers.clear();
tempIndex = 0;
return Container(
padding: EdgeInsets.symmetric(vertical: 5,horizontal: 8),
alignment: Alignment.centerLeft,
// color: Colors.grey.shade200,
width: MediaQuery.of(context).size.width,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: descriptionData.map<Widget>((item) {
switch (item['type']) {
case 'text':
if(widget.isItForFB){
String src = item['data']['src'];
List<String> parts = src.split('##');
List<InlineSpan> children = [];
for (int i = 0; i < parts.length; i++) {
if (i % 2 == 0) {
// Text outside the ##
children.add(
TextSpan(text: parseFragment(parts[i]).text)
);
} else {
// TextField inside the ##
TextEditingController controller = TextEditingController(text: (widget.isForResult)?(selectedAnswerOfFB!=[])?selectedAnswerOfFB[tempIndex].toString():"":"");
// TextEditingController controller = TextEditingController(text: (widget.isForResult)? selectedAnswerOfFB[tempIndex].toString():"");
tempIndex++;
textControllers.add(controller);
children.add(
WidgetSpan(
child: SizedBox(
width: 110,
height: 40,
child: TextField(
controller: controller,
enabled: (!widget.isForResult),
decoration: InputDecoration(
// border: OutlineInputBorder(),
),style: TextStyle(fontSize: 14),
),
),
));
}
}
return Padding(
padding: const EdgeInsets.all(0.0),
child: RichText(
text: TextSpan(children: children,style: TextStyle(color: Colors.black)),
),
);
}
else{
return Padding(
padding: const EdgeInsets.all(5.0),
child:
Html(
data: item['data']['src'],
),
// Text(
// item['data']['src']
// .replaceAll(RegExp('<p>|<\/p>'), '\n').replaceAll(RegExp('amp;'), ''),
// ),
);
}
case 'image':
return Image.network(
item['data']['rootUrl'] + '/' + item['data']['src'],
);
case 'embed':
String htmlString = item["data"]["src"].toString();
var regExp = RegExp('src="([^"]+)"');
var match = regExp.firstMatch(htmlString);
if (match != null) {
var srcUrl = match.group(1);
return customWebViewWIdget(context, srcUrl);
} else {
print('No match found.');
return Container();
}
default:
return Container();
}
}).toList(),
),
);
}
Container customWebViewWIdget(BuildContext context, URL) {
return Container(
padding: EdgeInsets.all(10),
height: MediaQuery.of(context).size.width,
width: MediaQuery.of(context).size.width,
child: InAppWebView(
initialOptions: options,
shouldOverrideUrlLoading: (controller, navigationAction) async {
if (navigationAction.request.url == "url"){
print("if loop running");
return NavigationActionPolicy.CANCEL;
}
return NavigationActionPolicy.ALLOW;
},
androidOnPermissionRequest: (controller, origin, resources) async {
return PermissionRequestResponse(
resources: resources,
action: PermissionRequestResponseAction.GRANT,
);
},
initialUrlRequest: URLRequest(url: Uri.parse(URL)),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
),
);
}
}
这里 isItForFB 为 true,isFor result 为 false,唯一重要的部分是 textField 的相关位置。 我对 flutter 很陌生,之前也遇到过这个问题,我想我应该使用 globalKey ,但不知道具体如何以及在哪里。
是的,这是 Flutter 应用程序中的常见问题。当键盘打开或关闭时,MediaQuery.of(context) 值发生变化,从而触发 widget 树的重建。这可能会消耗性能,尤其是当您的应用程序有很多小部件时。
有几种方法可以防止键盘打开或关闭时重建小部件树。一种方法是使用 MediaQueryData.viewInsets 属性获取键盘的插入,然后使用此信息相应地更新小部件的布局。另一种方法是使用 InheritedWidget 模式与应用程序中的所有小部件共享键盘插入。
请参阅此相关问题:问题它将帮助您
有时使用时会发生这种情况
MediaQuery.of(context)
在 drawerEdgeDragWidth
中的
scaffold
争论