在Flutter中,function setState 不更新变量。

huangapple go评论71阅读模式
英文:

function setState in flutter is not updating variable

问题

以下是您提供的代码的翻译部分:

好的,我有一个页面,根据之前按下的按钮,会显示一组幻灯片。如果这组幻灯片尚未解锁,那么将显示一个带有TextFormField的幻灯片。如果在其中输入代码,它将检查是否在数据库中。我唯一需要的是,当代码不在数据库中时,TextFormField的边框应该变成红色

问题是,setState()未更新边框条件。我测试过了,变量已更新,但页面没有重建。

以下是代码页面的代码:

class _BreathingSlidesState extends State< BreathingSlides > {
  int _currentIndex = 0;
  late List< Widget > slideContent;
  List< String > premium = ['Inhalation', 'Procedures'];
  final _formKey = GlobalKey< FormState > ();
  TextEditingController _textFieldController = TextEditingController();
  bool ? goodCode;

  void updateDoneValue(bool value) {
    final breathingWidget = context.findAncestorStateOfType< _BreathingState > ();
    if (breathingWidget != null) {
      setState(() {
        widget.updateDone(value);
      });
    }
  }

  void dispose() {
    _textFieldController.dispose();
    super.dispose();
  }

  Future< bool > fetchData(String value) async {
    List< String > dataList = [];

    final querySnapshot = await FirebaseFirestore.instance.collection('uCodes').get();

    querySnapshot.docs.forEach((doc) {
      var fieldValue = doc.data()['1'].toString();
      dataList.add(fieldValue);
    });

    return dataList.contains(value);
  }

  @override
  void initState() {
    super.initState();
    if (premium.contains(widget.buttonContext)) {
      slideContent = [
        Column(
          children: [
            const Padding(
              padding: EdgeInsets.only(top: 80.0, left: 20, right: 20, bottom: 20),
              child: Align(alignment: Alignment.center, child: Text("You haven't unlocked this lesson yet", textAlign: TextAlign.center, style: TextStyle(fontSize: 30, color: Colors.black, fontWeight: FontWeight.bold),)),
            ),
            Form(
              key: _formKey,
              child: Column(
                children: [
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 60, vertical: 20),
                    child: Builder(
                      builder: (context) {
                        return TextFormField(
                          controller: _textFieldController,
                          onFieldSubmitted: (value) async {
                            _textFieldController.clear();
                            if (await fetchData(value)) {
                              goodCode = true;
                              setState(() {
                                print("jj");
                                goodCode = true;
                              });
                            } else {
                              goodCode = false;
                              setState(() {
                                print("nn");
                                goodCode = false; // 如果检测到不良输入,则将标志设置为false
                              });
                              print(goodCode);
                            }
                          },
                          textAlign: TextAlign.center,
                          decoration: InputDecoration(
                            contentPadding: const EdgeInsets.all(1),
                            enabledBorder: OutlineInputBorder(
                              borderSide: BorderSide(
                                color: goodCode == null ? Colors.grey : Colors.red, // 根据验证结果设置边框颜色
                                width: 2, // 设置边框宽度
                              ),
                            ),
                            label: const Center(child: Text("Enter your uCode"), ),
                            floatingLabelStyle: const TextStyle(color: Color.fromARGB(255, 78, 125, 79), fontSize: 20),
                            focusedBorder: const OutlineInputBorder(
                              borderSide: BorderSide(color: Color.fromARGB(255, 115, 171, 117), width: 4)
                            )
                          ),
                        );
                      }
                    ),
                  ),
                ]
              )
              //odkaz do shopu
            ),
          ]
        )
      ];
    }
  }
}

在这里应用了幻灯片:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      backgroundColor: const Color.fromARGB(255, 78, 125, 79),
      title: const Text('x XP', style: TextStyle(fontSize: 25)),
      centerTitle: true
    ),
    body: Column(
      children: [
        Expanded(
          child: PageView.builder(
            itemCount: slideContent.length,
            itemBuilder: (context, index) {
              return Center(
                child: slideContent[index],
              );
            },
            onPageChanged: (index) {
              setState(() {
                _currentIndex = index;
              });
            },
          ),
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            for (int i = 0; i < slideContent.length; i++)
              _buildDot(i == _currentIndex),
          ],
        ),
      ],
    ),
  );
}

希望这能帮助您解决问题。如有其他疑问,请随时提出。

英文:

Okay so I have a page where according to button pressed beforehand a group of slides is shown. If the group of slides is not unlocked yet, instead, one slide with TextFormField will appear. If a code i written into it it will check if its in a database. The only thing I need is, that when the code is not in the database, the border of the TextFormField should turn red.

Problem is, the setState() is not updating the border conditions. I tested it out, the variable is updated, but the page is not rebuilded.

Here's the code of the code page:

class _BreathingSlidesState extends State&lt;BreathingSlides&gt; {
int _currentIndex = 0;
late List&lt;Widget&gt; slideContent;
List&lt;String&gt; premium = [&#39;Inhalation&#39;, &#39;Procedures&#39;];
final _formKey = GlobalKey&lt;FormState&gt;();
TextEditingController _textFieldController = TextEditingController();
bool? goodCode;
void updateDoneValue(bool value) {
final breathingWidget = context.findAncestorStateOfType&lt;_BreathingState&gt;();
if (breathingWidget != null) {
setState(() {
widget.updateDone(value);
});
}
}
void dispose() {
_textFieldController.dispose();
super.dispose();
}
Future&lt;bool&gt; fetchData(String value) async {
List&lt;String&gt; dataList = [];
final querySnapshot = await FirebaseFirestore.instance.collection(&#39;uCodes&#39;).get();
querySnapshot.docs.forEach((doc) {
var fieldValue = doc.data()[&#39;1&#39;].toString();
dataList.add(fieldValue);
});
return dataList.contains(value);
}
@override
void initState() {
super.initState();
if(premium.contains(widget.buttonContext))
{
slideContent = [
Column(
children: [
const Padding(
padding: EdgeInsets.only(top: 80.0, left: 20, right: 20, bottom: 20),
child: Align(alignment: Alignment.center, child: Text(&quot;You haven&#39;t unlocked this lesson yet&quot;,textAlign: TextAlign.center, style: TextStyle(fontSize: 30, color: Colors.black, fontWeight: FontWeight.bold),)),
),
Form(
key: _formKey,
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 60, vertical: 20),
child: Builder(
builder: (context) {
return TextFormField(
controller: _textFieldController,
onFieldSubmitted: (value) async {
_textFieldController.clear();
if (await fetchData(value)) {
goodCode = true;
setState(() {
print(&quot;jj&quot;);
goodCode = true;  
});
}
else{
goodCode = false;
setState(() {
print(&quot;nn&quot;);
goodCode = false; // Set the flag to false if a bad input is detected
});
print(goodCode);
}
},
textAlign: TextAlign.center,
decoration: InputDecoration(
contentPadding: const EdgeInsets.all(1),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: goodCode == null ? Colors.grey : Colors.red, // Set border color based on validation result
width: 2, // Set border width
),
),
label: const Center(child: Text(&quot;Enter your uCode&quot;),),
floatingLabelStyle: const TextStyle(color: Color.fromARGB(255, 78, 125, 79), fontSize: 20),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Color.fromARGB(255, 115, 171, 117), width: 4)
)
),
);
}
),
),
]
)
//odkaz do shopu
),
])];
}

Here the slides are applied:

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: const Color.fromARGB(255, 78, 125, 79),
title: const Text(&#39;x XP&#39;, style: TextStyle(fontSize: 25)),
centerTitle: true
),
body: Column(
children: [
Expanded(
child: PageView.builder(
itemCount: slideContent.length,
itemBuilder: (context, index) {
return Center(
child: slideContent[index],
);
},
onPageChanged: (index) {
setState(() {
_currentIndex = index;
});
},
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
for (int i = 0; i &lt; slideContent.length; i++)
_buildDot(i == _currentIndex),
],
),
],
),
);
}

Any ideas are appreciated, thanks a lot.

答案1

得分: 1

好的,对于任何想知道的人,经过一些严格的调试,我发现 setState() 确实被正确调用了,但它没有被更新到 PageView.builder 中的 Center widget。
我找不到如何将变量传递给该小部件,但我了解了 StatefulBuilder()。它仅更新其中的小部件,并对此有所帮助。
我现在在想是否有类似的东西,但没有小部件,只有代码。
编码好运!

英文:

Okay so for anyone wondering, after some hardcore debugging xd i found that setState() is indeed called properly, but it's not updated to the Center widget in PageView.builder.
I couldn't find how to pass the variables to the widget, but i learned about StatefulBuilder(). It updates only the widgets in it, and that helped.
I am now wondering tho if there's something like this, but without widgets, only with code.
Good luck with coding!

huangapple
  • 本文由 发表于 2023年7月17日 23:30:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76706010.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定