先上效果图。
刷新功能实现
将刷新组件嵌入滑动组件中,因为聊天界面都是由下往上滑,所以ListView设置了reverse: true实现反转列表组件。组件itemCount的值设置消息数组长度+1,因为设置了reverse,所以需要将刷新加载组件放到当index == 消息长度的位置。
return index == _chatRecords.length ? LoadIndicator() : chatItemWidget(index);
判断是否出发刷新的逻辑也很简单,当_scrollController.position.pixels大于等于_scrollController.position.maxScrollExtent的时候触发刷新操作就可以了。
if (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent) {
if (_isLoading) return;
_isLoading = true;
onLoadMore();
}
界面优化
·优化列表滑动弹性效果
列表的physics使用了自己实现的ChatScrollPhysics。目的是为了实现下滑加载带弹性效果,上滑屏蔽弹性效果。(BouncingScrollPhysics是上下都有弹性效果)
重写applyBoundaryConditions方法
///base on BouncingScrollPhysics
///
class ChatScrollPhysics extends ScrollPhysics {
...
@override
double applyBoundaryConditions(ScrollMetrics position, double value) {
if (value < position.pixels && position.pixels <= position.minScrollExtent) // underscroll
return value - position.pixels;
if (value < position.minScrollExtent && position.minScrollExtent < position.pixels) // hit top edge
return value - position.minScrollExtent;
return 0.0;
}
...
}
同时修改 0.52的值可以实现这个系数从某个值开始,逐渐变得难以过度滚动。
double frictionFactor(double overscrollFraction) =>
0.52 * math.pow(1 - overscrollFraction, 2);
·关闭过度滚动产生的光晕
使用ScrollConfiguration包裹滑动组件behavior设置成自己实现的behavior。
ScrollConfiguration(
behavior: ChatScrollBehavior(),
child: yourScrollViewWidget,
),
class ChatScrollBehavior extends ScrollBehavior {
final bool showLeading;
final bool showTrailing;
ChatScrollBehavior({
this.showLeading: false,
this.showTrailing: false,
});
@override
Widget buildViewportChrome(BuildContext context, Widget child, AxisDirection axisDirection) {
return GlowingOverscrollIndicator(
showLeading: showLeading,
showTrailing: showTrailing,
child: child,
axisDirection: axisDirection,
color: Theme.of(context).primaryColor,
);
}
}