目前的滚动模式有两种:水平和垂直,考虑到切换过程中边距等样式或者itemBuilder中额外信息的构建需要自定义,由用户根据scrollType切换ReadView也可行。
水平滚动模式有两种效果,分别是覆盖和水平滑动,这个的切换可以是动态的。
以下给出动态切换的一种方案,由于我的代码做了部其他修改,这里直接使用issue的方式给出:
将代码定位到read_page_view.dart文件的282行:
// Overlay swipe
// 覆盖滑动
class _FillViewportRenderObjectWidget extends SliverMultiBoxAdaptorWidget {
final ScrollType scrollType;
const _FillViewportRenderObjectWidget({
required this.scrollType,
required super.delegate,
});
@override
void updateRenderObject(
BuildContext context,
_DynamicRenderSliver renderObject,
) {
renderObject.scrollType = scrollType; // 动态更新模式
}
@override
RenderSliverMultiBoxAdaptor createRenderObject(BuildContext context) {
return _DynamicRenderSliver(
scrollType: scrollType,
childManager: context as SliverMultiBoxAdaptorElement);
}
}
class _DynamicRenderSliver extends RenderSliverFixedExtentBoxAdaptor {
ScrollType _scrollType;
_DynamicRenderSliver({
required ScrollType scrollType,
required super.childManager,
}) : _scrollType = scrollType;
set scrollType(ScrollType newType) {
if (_scrollType != newType) {
_scrollType = newType;
markNeedsLayout(); // 触发重新布局
}
}
@override
double get itemExtent => constraints.viewportMainAxisExtent;
@override
void paint(PaintingContext context, Offset offset) {
if (_scrollType == ScrollType.smooth) {
super.paint(context, offset);
return;
}
if (firstChild == null) {
return;
}
const Offset mainAxisUnit = Offset(1.0, 0.0);
const Offset crossAxisUnit = Offset(0.0, 1.0);
final Offset originOffset = offset;
void draw(RenderBox child) {
final double mainAxisDelta = childMainAxisPosition(child);
final double crossAxisDelta = childCrossAxisPosition(child);
Offset childOffset = Offset(
originOffset.dx +
mainAxisUnit.dx * mainAxisDelta +
crossAxisUnit.dx * crossAxisDelta,
originOffset.dy +
mainAxisUnit.dy * mainAxisDelta +
crossAxisUnit.dy * crossAxisDelta,
);
if (child != firstChild) {
childOffset = Offset.zero;
}
if (mainAxisDelta < constraints.remainingPaintExtent &&
mainAxisDelta + paintExtentOf(child) > 0) {
context.paintChild(child, childOffset);
}
}
RenderBox child = firstChild!;
RenderBox? next = childAfter(child);
if (next != null) {
draw(next);
}
draw(child);
}
}
目前的滚动模式有两种:水平和垂直,考虑到切换过程中边距等样式或者itemBuilder中额外信息的构建需要自定义,由用户根据scrollType切换ReadView也可行。
水平滚动模式有两种效果,分别是覆盖和水平滑动,这个的切换可以是动态的。
以下给出动态切换的一种方案,由于我的代码做了部其他修改,这里直接使用issue的方式给出:
将代码定位到
read_page_view.dart文件的282行: