flutter_easy_refresh
flutter_easy_refresh copied to clipboard
当SecondaryBuilderHeader和NestedScrollView整合使用的时候,无法关闭已经打开了的二楼页面
版本为: easy_refresh: ^3.4.0
出现的现象: 打开二楼后,页面往下滑动后,二楼的页面并没有被关闭,从主页面往上滑动的时候,并未出现再次刷新的情况,如下所示。并且打开二楼后,发现日志就一直在输出 mode state: IndicatorMode.secondaryOpen, page: Opacity-[GlobalKey#554a6](opacity: 1.0)
,感觉发生bug的场景跟这个应该是差不多的 #713
核心代码如下所示:
_buildMain(MediaQueryData mediaQuery, Size size) {
return EasyRefresh.builder(
scrollController: _scrollController,
controller: _refreshController,
header: SecondaryBuilderHeader(
header: buildClassicHeader(
backgroundColor: HiColors.home_bg,
mainAxisAlignment: MainAxisAlignment.end,
position: IndicatorPosition.locator,
clipBehavior: Clip.none,
safeArea: true,
clamping: true,
),
secondaryTriggerOffset: 120,
secondaryDimension: size.height,
listenable: _listenable,
builder: (context, state, header) {
final mode = state.mode;
final offset = state.offset;
final actualSecondaryTriggerOffset =
state.actualSecondaryTriggerOffset!;
final actualTriggerOffset = state.actualTriggerOffset;
double scale = 1;
if (state.offset > state.actualTriggerOffset) {
scale = math.max(
0.0,
(actualSecondaryTriggerOffset - offset) /
(actualSecondaryTriggerOffset - actualTriggerOffset));
}
return Stack(
clipBehavior: Clip.none,
children: [
SizedBox(
height: state.offset,
width: double.infinity,
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: SizedBox(
height: size.height,
width: double.infinity,
child: Builder(
builder: (context) {
Widget secondaryPage = Opacity(
key: _secondaryPageKey,
opacity: 1 - scale,
child: const Stack(
children: [
Center(
child: Text('测试二楼页面'),
)
],
));
if (mode == IndicatorMode.secondaryOpen ||
mode == IndicatorMode.secondaryClosing) {
logger.d(
'mode state: $mode, page: $secondaryPage',
);
WidgetsBinding.instance.addPostFrameCallback((_) {
configProvider.openHomeSecondaryPage = true;
});
return PopScope(
canPop: false,
onPopInvoked: (_) {
_refreshController.closeHeaderSecondary();
},
child: secondaryPage,
);
}
return secondaryPage;
},
),
),
),
Positioned(
bottom: 24,
left: 0,
right: 0,
child: Center(
child: AnimatedOpacity(
opacity: mode == IndicatorMode.secondaryArmed ? 1 : 0,
duration: const Duration(milliseconds: 200),
child: Text('打开维权日历'),
),
),
),
Opacity(
opacity: (mode == IndicatorMode.secondaryReady ||
mode == IndicatorMode.secondaryOpen ||
mode == IndicatorMode.secondaryClosing)
? 0
: scale,
child: header.build(context, state),
),
],
);
},
),
childBuilder: (context, physics) {
return _buildBody(context, physics);
},
onRefresh: () async {
await Future.delayed(const Duration(seconds: 2));
if (!mounted) {
return;
}
_refreshController.finishRefresh();
_refreshController.resetFooter();
});
_buildBody(BuildContext context, ScrollPhysics physics) {
return NestedScrollView(
physics: physics,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return [
const HeaderLocator.sliver(
clearExtent: false,
),
ValueListenableBuilder<IndicatorState?>(
valueListenable: _listenable,
builder: (context, state, child) {
double scale = 1;
if (state != null) {
if (state.offset > state.actualTriggerOffset) {
scale = math.max(
0.0,
(state.actualSecondaryTriggerOffset! - state.offset) /
(state.actualSecondaryTriggerOffset! -
state.actualTriggerOffset));
}
}
return SliverOpacity(
opacity: scale,
sliver: _buildAppBar(),
);
},
),
// _buildAppBar(),
_topBoxContainer(),
_orderActionBoxContainer(),
_briefReportContainer(),
_secondaryActionBoxContainer(),
_bannerBoxContainer(),
_recommendedLawyerContainer(),
_specialtyActionContainer(),
_tabBarContainer(),
];
},
controller: _scrollController,
body: _buildTabView(context, physics));
}
}
/// 构建ClassicHeade
ClassicHeader buildClassicHeader({
TextStyle? loadingTextStyle,
String noMoreText = "没有更多数据了",
IndicatorPosition position = IndicatorPosition.above,
clipBehavior = Clip.hardEdge,
Color? backgroundColor,
bool hasError = false,
bool clamping = false,
bool safeArea = true,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.center,
}) {
DateTime now = DateTime.now();
String formattedTime = DateFormat('HH:mm:ss').format(now);
TextStyle defaultLoadingTextStyle = loadingTextStyle ??
TextStyle(
color: Colors.black.withOpacity(0.4),
fontSize: 12.px,
fontWeight: FontWeight.w400,
fontFamily: 'PingFang SC');
return ClassicHeader(
backgroundColor: backgroundColor,
safeArea: safeArea,
clipBehavior: clipBehavior,
clamping: clamping,
position: position,
mainAxisAlignment: mainAxisAlignment,
dragText: '下拉刷新',
armedText: '释放开始',
readyText: '正在刷新...',
processingText: '正在刷新...',
processedText: '刷新完成',
failedText: '刷新失败',
textStyle: defaultLoadingTextStyle,
messageStyle: defaultLoadingTextStyle,
noMoreText: noMoreText,
messageText: '更新于 $formattedTime',
pullIconBuilder: (context, state, animation) {
return _buildPullIcon(context, state, animation, hasError);
});
}