gpt4 book ai didi

Flutter 出现 The method 'findRenderObject' was called on null

转载 作者:行者123 更新时间:2023-12-03 03:22:55 34 4
gpt4 key购买 nike

最近有个需求,需要测量sliver中的子元素到top的距离,但是总是提示findrendereobject为空。我什至无法尝试 widgetsbinding.instance.addpostframecallback
控制台错误:

════════ Exception caught by scheduler library═════════════════════════════════════════════════════
The followingNoSuchMethodError was thrown during a scheduler callback: The method'findRenderObject' was called on null. Receiver: null Tried calling:findRenderObject()

请大家看看是怎么回事,为什么测不了高度~万分感谢!!!我的代码:

class GoodsDetailPage extends StatefulWidget {
final IndexVOS bean;
GoodsDetailPage(this.bean);
@override
_GoodsDetailPageState createState() => _GoodsDetailPageState();
}

class _GoodsDetailPageState extends State<GoodsDetailPage> with SingleTickerProviderStateMixin{
int productId;
int areaId;
String serviceTime;
ProductInfoBean productInfoBean;
String _selectName;
Norms norms;
double screenWidth;
bool _isShow = false;
TabController _tabController;
List<String> tabList;
ScrollController _scrollController = ScrollController();
var globalKeyOne = GlobalKey();
var globalKeyTwo = GlobalKey();
var globalKeyThree = GlobalKey();
var oneY = 0.0;
var twoY = 0.0;
var threeY = 0.0;

ProductModel model = ProductModel();
GoodsSpecModel _specModel = GoodsSpecModel();


@override
void initState() {
productId = widget.bean.productId;
areaId = widget.bean.areaId;
serviceTime = widget.bean.serviceTimeBegin;
tabList = [
"商品",
"评价",
"详情",
];
_tabController = TabController(
length: tabList.length,
vsync: this,
);
_scrollController.addListener(() {
var of = _scrollController.offset;
setState(() {
_isShow = of >= screenWidth-50;
});
if (of > threeY - oneY) {
_tabController.animateTo(2);
}else if (of > twoY - oneY) {
_tabController.animateTo(1);
} else {
_tabController.animateTo(0);
}
print("滚动了$of one=${twoY - oneY}=two=${threeY - oneY}");
});
WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
super.initState();
}

//等待界面渲染完成
void _afterLayout(_){
oneY = getY(globalKeyOne.currentContext);
twoY = getY(globalKeyTwo.currentContext);
threeY = getY(globalKeyThree.currentContext);
}

static double getY(BuildContext buildContext) {
final RenderBox box = buildContext.findRenderObject();
//final size = box.size;
final topLeftPosition = box.localToGlobal(Offset.zero);
return topLeftPosition.dy;
}

Future _request() async{
model.requestGoodsDetail(productId: productId,areaId: areaId,serviceTime: serviceTime);
}

@override
Widget build(BuildContext context) {
screenWidth = MediaQuery.of(context).size.width;
return Scaffold(
body: Container(
width: double.infinity,
height: double.infinity,
child: ProviderWidget<ProductModel>(
model: model,
onModelReady: (model) => model.requestGoodsDetail(productId: productId,areaId: areaId,serviceTime: serviceTime),
builder: (context, model, child) {
if (model.busy) {
return ViewStateBusyWidget();
}
if (model.error) {
return ViewStateErrorWidget(error: model.viewStateError, onPressed: _request);
}
return Column(
children: <Widget>[
Expanded(child: _body()),
_bottom()
],
);
}
),
)
);
}

Widget _body(){
var _normalBack = Image.asset(ImagePath.normalBack,height: dp40,width: dp40);
var _detailBack = Image.asset(ImagePath.detailBack,height: dp60,width: dp60);
var _normalShare = Image.asset(ImagePath.detailShareSmall,height: dp40,width: dp60);
var _detailShare = Image.asset(ImagePath.detailShare,height: dp60,width: dp140);
var _normalDot = Image.asset(ImagePath.threeDot,height: dp40,width: dp40);
var _detailDot = Image.asset(ImagePath.detailDot,height: dp60,width: dp60);
return CustomScrollView(
controller: _scrollController,
slivers: <Widget>[
SliverAppBar(
key: globalKeyOne,
title: _isShow?_topTabTitle():Container(),
centerTitle: true,
expandedHeight: screenWidth,
floating: false,
pinned: true,
snap: false,
elevation: 0.5,
leading: IconButton(
icon: _isShow?_normalBack:_detailBack,
onPressed: () => pop(),
),
actions: <Widget>[
GestureDetector(
child: _isShow?_normalShare:_detailShare,
onTap: (){
print("分享");
},
),
SizedBox(width: dp24),
GestureDetector(
child: _isShow?_normalDot:_detailDot,
onTap: _showPopup,
),
SizedBox(width: dp30),
],
flexibleSpace: FlexibleSpaceBar(
background: GoodsDetailBannerWidget(model),
),
),
SliverList(
delegate: SliverChildListDelegate([
_activityImage(),
GoodsDetailInfoWidget(model),
gap20,
GoodsDetailOtherWidget(model,serviceTime),
GoodsDetailCategoryWidget(click: _clickSpec,name: _selectName),
gap20,
Column(
key: globalKeyTwo,
children: <Widget>[
GoodsDetailCommentWidget(model),
gap20,
],
),
Container(
key: globalKeyThree,
child: GoodsDetailDescWidget(model),
)
]),
),
],
);
}

Widget _bottom(){
return GoodsDetailBottomWidget(
clickBuy: (){
if(_selectName == null){
_clickSpec();
return;
}
routePush(ConfirmOrderPage(productInfoBean: model.productInfoBean,norms: norms,count: _specModel.countNumber));
},
);
}

Widget _activityImage(){
return Container(
width: double.infinity,
height: dp80,
child: Image.asset(ImagePath.goodsActivity),
);
}

Widget _topTabTitle(){
return Container(
height: dp60,
child: TabBar(
controller: _tabController,
labelColor: ColorConfig.themeGreen,
unselectedLabelColor: ColorConfig.C09,
labelStyle: StyleConfig.green_36Style,
unselectedLabelStyle: StyleConfig.normalTitle36Style,
indicatorColor: ColorConfig.themeGreen,
indicatorSize: TabBarIndicatorSize.label,
indicatorWeight: 2,
isScrollable: true,
labelPadding: EdgeInsets.symmetric(horizontal: dp20),
tabs: tabList.map((item) {
return Tab(
text: item,
);
}).toList(),
onTap: (index){
switch(index){
case 0:
_scrollController.jumpTo(0);
_tabController.animateTo(0);
break;
case 1:
_scrollController.jumpTo(twoY - oneY);
_tabController.animateTo(1);
break;
case 2:
_scrollController.jumpTo(threeY - oneY);
_tabController.animateTo(2);
break;
}
},
),
);
}

void _showPopup(){
showPopupWindow(
context,
gravity: KumiPopupGravity.rightTop,
underStatusBar: true,
underAppBar: true,
offsetX: -dp30,
offsetY: -dp20,
childFun: (pop){
return Container(
key: GlobalKey(),
child: GoodsDetailPopupMenuWidget(),
);
}
);
}


void _clickSpec(){
_specModel.initData(model.normInfoBean.norms);
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (BuildContext context) {
return GoodsSpecSelectDialog(
model: _specModel,
onSelected: (bean, count) {
norms = bean;
setState(() {
_selectName = "已选:"+bean.normName + ",数量:" + count.toString();
});
},
);
},
);
}

@override
void dispose() {
_specModel.dispose();
_scrollController.dispose();
_tabController.dispose();
super.dispose();
}

}

最佳答案

您的全局键附加到 _body() 方法中的小部件,但此方法仅在 model.busy = false 和 model.error = false 时调用。这意味着当 model.busy = true || 时,globalKeyOne.currentContext 将为空模型.error = true。您的 _afterLayout(...) 在所有情况下都会被调用,这就是它因 NPE 而失败的原因。

关于Flutter 出现 The method 'findRenderObject' was called on null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61241536/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com