Flutter中IconButton点击无响应,如何解决该问题?
我制作了一个IconButton,在Chrome上显示正常,但点击后没有任何反应。正在开发一款励志应用,原本希望点击按钮切换屏幕中间展示的名言,却无法实现该功能,不清楚问题所在。以下是我的代码:
主文件代码
import 'dart:convert'; import 'package:app/count_page.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: Colors.blue, splashColor: Colors.transparent, highlightColor: Colors.transparent, ), home:ChangeNotifierProvider( create: (BuildContext context) => CountPage() ,child: Quote() ,) ); } } class Quote extends StatelessWidget { Quote({Key? key}) : super(key: key); late CountPage _countPage; @override Widget build(BuildContext context) { _countPage = Provider.of<CountPage>(context,listen: false); String arrayText = '[{"author": "-공자-","message": "멈추지 않으면 얼마나 천천히 가는지는 문제가 되지 않느니라 " },' '{"author": "공자","message": "어디를 가든지 마음을 다해 가라" },' '{"author": "공자","message": "상처는 잊되, 은혜는 결코 잊지 말라" },' '{"author": "공자","message": "한 사람에게서 모든 덕을 구하지 말라" },' '{"author": "공자","message": "허물이 있다면, 버리기를 두려워 말라" },' '{"author": "공자","message": "절약하지 않는 자는 고통받게 될 것이니라" },' '{"author": "공자","message": "앞날을 결정짓고자 한다면 옛것을 공부하라" },' '{"author": "공자","message": "지나침은 모자람만 못하다" },' '{"author": "공자","message": "스스로 존경하면 다른 사람도 그대를 존경할 것이니라" },' '{"author": "공자","message": "흠 없는 조약돌보다는 흠 있는 금강석이 더 나으니라" },' '{"author": "나폴레옹","message": "내 사전에 불가능은 없다" },' '{"author": "바이런","message": "가장 뛰어난 예언자는 과거이다" },' '{"author": "나폴레옹","message": "내 비장의 무기는 아직 손안에 있다" },' '{"author": "소크라테스","message": "너 자신을 알라" },' '{"author": "아리스토텔레스","message": "많은 벗을 가진 사람은 한 사람의 진실한 벗을 가질 수 없다" },' '{"author": "솔론","message": "말은 행동의 거울이다." },' '{"author": "플랭클린","message": "백 년을 살 것처럼 일하고" },' '{"author": "아리스토텔레스","message": "불행은 진정한 친구가" },' '{"author": "생텍쥐베리","message": "사막이 아름다운 것은 어딘가에 샘을 숨기고 있기 때문이다" },' '{"author": "파스칼","message": "습관은 제2의 천성으로 제1의 천성을 파괴한다" }]'; List list = jsonDecode(arrayText); return Scaffold( body:Container( color: Colors.white, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Center(child: IconButton(onPressed:(){_countPage.page_down();} , icon:Icon(Icons.chevron_left))), Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Center( child: Container( color: Colors.deepOrange, height: 400, width: 250, child: Center(child: Text(list[_countPage.page]["message"],style: TextStyle(fontSize: 40,color: Colors.black),textAlign: TextAlign.center,)) ), ), Center(child: Text(list[_countPage.page]["author"],style: TextStyle(fontSize: 20,color: Colors.black),)), ], ), Center(child: IconButton(onPressed:(){_countPage.page_up();}, icon:Icon(Icons.chevron_right))), ], ), ) , bottomNavigationBar: BottomAppBar( color: Colors.blue, child: Container( height: 100, child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Center(child: IconButton(onPressed: copy, icon:Icon(Icons.settings))), Center(child: IconButton(onPressed: share, icon:Icon(Icons.content_copy))), Center(child: IconButton(onPressed: option, icon:Icon(Icons.share))), ], ), ), ), ); } void copy() { } void share() { } void option() { } }
CountPage文件代码
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class CountPage extends ChangeNotifier{ int _page = 0; int get page => _page; page_down() { _page --; notifyListeners(); } page_up() { _page ++; notifyListeners(); } }
这是我第一次在Stack Overflow提问,作为经验不足的开发者,若我的提问方式或代码存在问题,恳请各位不吝指正。
问题分析与修复方案
1. UI未监听状态变化
你的Quote组件是StatelessWidget,且获取CountPage时使用了listen: false,这意味着即使CountPage调用notifyListeners(),组件也不会重新构建,自然看不到名言切换的效果。
修复方式:使用Consumer包裹需要更新的UI部分(性能更优),同时调整按钮的状态调用逻辑:
// 替换Quote组件中Row里的Column部分 Consumer<CountPage>( builder: (context, countPage, child) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Center( child: Container( color: Colors.deepOrange, height: 400, width: 250, child: Center(child: Text(list[countPage.page]["message"],style: TextStyle(fontSize: 40,color: Colors.black),textAlign: TextAlign.center,)) ), ), Center(child: Text(list[countPage.page]["author"],style: TextStyle(fontSize: 20,color: Colors.black),)), ], ); }, )
移除Quote类中的late CountPage _countPage;和_countPage = Provider.of<CountPage>(context,listen: false);,修改左右按钮的点击事件:
// 左按钮 IconButton( onPressed:(){ Provider.of<CountPage>(context, listen: false).page_down(); }, icon:Icon(Icons.chevron_left) ), // 右按钮 IconButton( onPressed:(){ Provider.of<CountPage>(context, listen: false).page_up(); }, icon:Icon(Icons.chevron_right) ),
2. 数组越界风险
当前page_up和page_down方法没有边界判断,当page减到负数或者超过名言列表长度时,会触发数组越界错误。
修复方式:修改CountPage的方法,添加边界校验,同时在调用时传入列表长度:
// 修改CountPage类 class CountPage extends ChangeNotifier{ int _page = 0; int get page => _page; void page_down(int maxIndex) { if (_page > 0) { _page --; notifyListeners(); } } void page_up(int maxIndex) { if (_page < maxIndex - 1) { _page ++; notifyListeners(); } } }
更新按钮的调用逻辑:
// 左按钮 IconButton( onPressed:(){ Provider.of<CountPage>(context, listen: false).page_down(list.length); }, icon:Icon(Icons.chevron_left) ), // 右按钮 IconButton( onPressed:(){ Provider.of<CountPage>(context, listen: false).page_up(list.length); }, icon:Icon(Icons.chevron_right) ),
最终效果
修改后,点击左右按钮时,CountPage的page值会在合法范围内更新,Consumer监听状态变化后自动刷新名言内容,实现切换功能,同时避免数组越界错误。
内容的提问来源于stack exchange,提问作者GodHanmin
相关产品推荐
相关产品推荐

