Flutter自定义_widget _appBar无法访问widget.user,提示Undefined name 'widget'
解决Flutter中自定义AppBar无法访问ChatUser对象的问题
问题根源
你写的_appBar()是独立的顶层函数,不属于_ChatScreenState类的成员,而widget是Flutter State类的内置属性,只有State类的成员方法才能直接访问它,因此会触发Undefined name 'widget'的错误。
解决方案一:将_appBar改为State类的成员方法
这是最贴合Flutter StatefulWidget设计逻辑的方案,直接把_appBar()移到_ChatScreenState类内部,就能直接访问widget.user:
class _ChatScreenState extends State<ChatScreen> { @override Widget build(BuildContext context) { final mq = MediaQuery.of(context); // 先获取MediaQuery对象确保可用 return SafeArea( child: Scaffold( appBar: AppBar( automaticallyImplyLeading: false, flexibleSpace: _appBar(mq), ), ), ); } // 改为State类的成员方法 Widget _appBar(MediaQueryData mq) { return InkWell( onTap: () {}, child: Row( children: [ IconButton( onPressed: () => Navigator.pop(context), icon: const Icon(Icons.arrow_back_rounded, color: Colors.white), ), CachedNetworkImage( imageUrl: widget.user.imageUrl, // 直接访问widget.user imageBuilder: (context, imageProvider) => Container( width: mq.width * 0.1, height: mq.height * 0.1, decoration: BoxDecoration( shape: BoxShape.circle, image: DecorationImage(image: imageProvider, fit: BoxFit.cover), ), ), placeholder: (context, url) => const CircularProgressIndicator(), errorWidget: (context, url, error) => const Icon(Icons.error), ), const SizedBox(width: 10.0), Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget.user.name, // 成功读取user.name style: const TextStyle( fontSize: 16.0, color: Colors.white, fontWeight: FontWeight.bold, ), ), const Text( 'Online', style: TextStyle(fontSize: 12.0, color: Colors.white70), ), ], ), ], ), ); } }
解决方案二:给_appBar函数传入ChatUser参数
如果需要让_appBar()在多个页面复用,可以给它添加参数,把ChatUser对象传进去:
// 顶层函数接收ChatUser和MediaQueryData参数 Widget _appBar(ChatUser user, MediaQueryData mq) { return InkWell( onTap: () {}, child: Row( children: [ IconButton( onPressed: () => Navigator.pop(context), icon: const Icon(Icons.arrow_back_rounded, color: Colors.white), ), CachedNetworkImage( imageUrl: user.imageUrl, // 使用传入的user对象 imageBuilder: (context, imageProvider) => Container( width: mq.width * 0.1, height: mq.height * 0.1, decoration: BoxDecoration( shape: BoxShape.circle, image: DecorationImage(image: imageProvider, fit: BoxFit.cover), ), ), placeholder: (context, url) => const CircularProgressIndicator(), errorWidget: (context, url, error) => const Icon(Icons.error), ), const SizedBox(width: 10.0), Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( user.name, // 直接使用传入的user.name style: const TextStyle( fontSize: 16.0, color: Colors.white, fontWeight: FontWeight.bold, ), ), const Text( 'Online', style: TextStyle(fontSize: 12.0, color: Colors.white70), ), ], ), ], ), ); } // 在State的build方法中调用时传入参数 class _ChatScreenState extends State<ChatScreen> { @override Widget build(BuildContext context) { final mq = MediaQuery.of(context); return SafeArea( child: Scaffold( appBar: AppBar( automaticallyImplyLeading: false, flexibleSpace: _appBar(widget.user, mq), // 传入widget.user和mq ), ), ); } }
额外提示
原代码中的mq变量需要确保能被正确访问,建议在build方法中先通过MediaQuery.of(context)获取后再传递使用。
内容的提问来源于stack exchange,提问作者rookie9
相关产品推荐
相关产品推荐

