mirror of
https://github.com/venera-app/venera.git
synced 2025-09-27 07:47:24 +00:00
Improve changing chapter gesture with continuous mode.
This commit is contained in:
@@ -361,7 +361,9 @@
|
|||||||
"Last Reading: @epName Page @page": "上次阅读: @epName 第 @page 页",
|
"Last Reading: @epName Page @page": "上次阅读: @epName 第 @page 页",
|
||||||
"WebDAV Auto Sync": "WebDAV 自动同步",
|
"WebDAV Auto Sync": "WebDAV 自动同步",
|
||||||
"Mark all as read": "全部标记为已读",
|
"Mark all as read": "全部标记为已读",
|
||||||
"Do you want to mark all as read?" : "您要全部标记为已读吗?"
|
"Do you want to mark all as read?" : "您要全部标记为已读吗?",
|
||||||
|
"Swipe down for previous chapter": "向下滑动查看上一章",
|
||||||
|
"Swipe up for next chapter": "向上滑动查看下一章"
|
||||||
},
|
},
|
||||||
"zh_TW": {
|
"zh_TW": {
|
||||||
"Home": "首頁",
|
"Home": "首頁",
|
||||||
@@ -725,6 +727,8 @@
|
|||||||
"Last Reading: @epName Page @page": "上次閱讀: @epName 第 @page 頁",
|
"Last Reading: @epName Page @page": "上次閱讀: @epName 第 @page 頁",
|
||||||
"WebDAV Auto Sync": "WebDAV 自動同步",
|
"WebDAV Auto Sync": "WebDAV 自動同步",
|
||||||
"Mark all as read": "全部標記為已讀",
|
"Mark all as read": "全部標記為已讀",
|
||||||
"Do you want to mark all as read?" : "您要全部標記為已讀嗎?"
|
"Do you want to mark all as read?" : "您要全部標記為已讀嗎?",
|
||||||
|
"Swipe down for previous chapter": "向下滑動查看上一章",
|
||||||
|
"Swipe up for next chapter": "向上滑動查看下一章"
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -154,7 +154,6 @@ class _GalleryModeState extends State<_GalleryMode>
|
|||||||
builder: (BuildContext context, int index) {
|
builder: (BuildContext context, int index) {
|
||||||
if (index == 0 || index == totalPages + 1) {
|
if (index == 0 || index == totalPages + 1) {
|
||||||
return PhotoViewGalleryPageOptions.customChild(
|
return PhotoViewGalleryPageOptions.customChild(
|
||||||
scaleStateController: PhotoViewScaleStateController(),
|
|
||||||
child: const SizedBox(),
|
child: const SizedBox(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -168,7 +167,7 @@ class _GalleryModeState extends State<_GalleryMode>
|
|||||||
cached[index] = true;
|
cached[index] = true;
|
||||||
cache(index);
|
cache(index);
|
||||||
|
|
||||||
photoViewControllers[index] = PhotoViewController();
|
photoViewControllers[index] ??= PhotoViewController();
|
||||||
|
|
||||||
if (reader.imagesPerPage == 1) {
|
if (reader.imagesPerPage == 1) {
|
||||||
return PhotoViewGalleryPageOptions(
|
return PhotoViewGalleryPageOptions(
|
||||||
@@ -350,6 +349,8 @@ const Set<PointerDeviceKind> _kTouchLikeDeviceTypes = <PointerDeviceKind>{
|
|||||||
PointerDeviceKind.unknown
|
PointerDeviceKind.unknown
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const double _kChangeChapterOffset = 200;
|
||||||
|
|
||||||
class _ContinuousMode extends StatefulWidget {
|
class _ContinuousMode extends StatefulWidget {
|
||||||
const _ContinuousMode({super.key});
|
const _ContinuousMode({super.key});
|
||||||
|
|
||||||
@@ -364,7 +365,9 @@ class _ContinuousModeState extends State<_ContinuousMode>
|
|||||||
var itemScrollController = ItemScrollController();
|
var itemScrollController = ItemScrollController();
|
||||||
var itemPositionsListener = ItemPositionsListener.create();
|
var itemPositionsListener = ItemPositionsListener.create();
|
||||||
var photoViewController = PhotoViewController();
|
var photoViewController = PhotoViewController();
|
||||||
late ScrollController scrollController;
|
ScrollController? _scrollController;
|
||||||
|
|
||||||
|
ScrollController get scrollController => _scrollController!;
|
||||||
|
|
||||||
var isCTRLPressed = false;
|
var isCTRLPressed = false;
|
||||||
static var _isMouseScrolling = false;
|
static var _isMouseScrolling = false;
|
||||||
@@ -372,6 +375,7 @@ class _ContinuousModeState extends State<_ContinuousMode>
|
|||||||
bool disableScroll = false;
|
bool disableScroll = false;
|
||||||
|
|
||||||
late List<bool> cached;
|
late List<bool> cached;
|
||||||
|
|
||||||
int get preCacheCount => appdata.settings["preloadImageCount"];
|
int get preCacheCount => appdata.settings["preloadImageCount"];
|
||||||
|
|
||||||
/// Whether the user was scrolling the page.
|
/// Whether the user was scrolling the page.
|
||||||
@@ -386,6 +390,11 @@ class _ContinuousModeState extends State<_ContinuousMode>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool prepareToPrevChapter = false;
|
||||||
|
bool prepareToNextChapter = false;
|
||||||
|
bool jumpToNextChapter = false;
|
||||||
|
bool jumpToPrevChapter = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
reader = context.reader;
|
reader = context.reader;
|
||||||
@@ -464,6 +473,18 @@ class _ContinuousModeState extends State<_ContinuousMode>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onScroll() {
|
||||||
|
if (prepareToPrevChapter) {
|
||||||
|
jumpToNextChapter = false;
|
||||||
|
jumpToPrevChapter = scrollController.offset <
|
||||||
|
scrollController.position.minScrollExtent - _kChangeChapterOffset;
|
||||||
|
} else if (prepareToNextChapter) {
|
||||||
|
jumpToNextChapter = scrollController.offset >
|
||||||
|
scrollController.position.maxScrollExtent + _kChangeChapterOffset;
|
||||||
|
jumpToPrevChapter = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Widget widget = ScrollablePositionedList.builder(
|
Widget widget = ScrollablePositionedList.builder(
|
||||||
@@ -471,7 +492,11 @@ class _ContinuousModeState extends State<_ContinuousMode>
|
|||||||
itemScrollController: itemScrollController,
|
itemScrollController: itemScrollController,
|
||||||
itemPositionsListener: itemPositionsListener,
|
itemPositionsListener: itemPositionsListener,
|
||||||
scrollControllerCallback: (scrollController) {
|
scrollControllerCallback: (scrollController) {
|
||||||
this.scrollController = scrollController;
|
if (_scrollController != null) {
|
||||||
|
_scrollController!.removeListener(onScroll);
|
||||||
|
}
|
||||||
|
_scrollController = scrollController;
|
||||||
|
_scrollController!.addListener(onScroll);
|
||||||
},
|
},
|
||||||
itemCount: reader.maxPage + 2,
|
itemCount: reader.maxPage + 2,
|
||||||
addSemanticIndexes: false,
|
addSemanticIndexes: false,
|
||||||
@@ -481,7 +506,7 @@ class _ContinuousModeState extends State<_ContinuousMode>
|
|||||||
reverse: reader.mode == ReaderMode.continuousRightToLeft,
|
reverse: reader.mode == ReaderMode.continuousRightToLeft,
|
||||||
physics: isCTRLPressed || _isMouseScrolling || disableScroll
|
physics: isCTRLPressed || _isMouseScrolling || disableScroll
|
||||||
? const NeverScrollableScrollPhysics()
|
? const NeverScrollableScrollPhysics()
|
||||||
: const ClampingScrollPhysics(),
|
: const BouncingScrollPhysics(),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
if (index == 0 || index == reader.maxPage + 1) {
|
if (index == 0 || index == reader.maxPage + 1) {
|
||||||
return const SizedBox();
|
return const SizedBox();
|
||||||
@@ -496,18 +521,28 @@ class _ContinuousModeState extends State<_ContinuousMode>
|
|||||||
|
|
||||||
ImageProvider image = _createImageProvider(index, context);
|
ImageProvider image = _createImageProvider(index, context);
|
||||||
|
|
||||||
return ComicImage(
|
return ColoredBox(
|
||||||
filterQuality: FilterQuality.medium,
|
color: context.colorScheme.surface,
|
||||||
image: image,
|
child: ComicImage(
|
||||||
width: width,
|
filterQuality: FilterQuality.medium,
|
||||||
height: height,
|
image: image,
|
||||||
fit: BoxFit.contain,
|
width: width,
|
||||||
|
height: height,
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
scrollBehavior: const MaterialScrollBehavior()
|
scrollBehavior: const MaterialScrollBehavior()
|
||||||
.copyWith(scrollbars: false, dragDevices: _kTouchLikeDeviceTypes),
|
.copyWith(scrollbars: false, dragDevices: _kTouchLikeDeviceTypes),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
widget = Stack(
|
||||||
|
children: [
|
||||||
|
Positioned.fill(child: buildBackground(context)),
|
||||||
|
Positioned.fill(child: widget),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
widget = Listener(
|
widget = Listener(
|
||||||
onPointerDown: (event) {
|
onPointerDown: (event) {
|
||||||
fingers++;
|
fingers++;
|
||||||
@@ -530,6 +565,13 @@ class _ContinuousModeState extends State<_ContinuousMode>
|
|||||||
disableScroll = false;
|
disableScroll = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (fingers == 0) {
|
||||||
|
if (jumpToPrevChapter) {
|
||||||
|
reader.toPrevChapter();
|
||||||
|
} else if (jumpToNextChapter) {
|
||||||
|
reader.toNextChapter();
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onPointerCancel: (event) {
|
onPointerCancel: (event) {
|
||||||
fingers--;
|
fingers--;
|
||||||
@@ -577,15 +619,37 @@ class _ContinuousModeState extends State<_ContinuousMode>
|
|||||||
if (notification is ScrollUpdateNotification) {
|
if (notification is ScrollUpdateNotification) {
|
||||||
if (!scrollController.hasClients) return false;
|
if (!scrollController.hasClients) return false;
|
||||||
if (scrollController.position.pixels <=
|
if (scrollController.position.pixels <=
|
||||||
scrollController.position.minScrollExtent &&
|
scrollController.position.minScrollExtent &&
|
||||||
!reader.isFirstChapterOfGroup) {
|
!reader.isFirstChapterOfGroup) {
|
||||||
context.readerScaffold.setFloatingButton(-1);
|
if (!prepareToPrevChapter) {
|
||||||
|
jumpToPrevChapter = false;
|
||||||
|
jumpToNextChapter = false;
|
||||||
|
context.readerScaffold.setFloatingButton(-1);
|
||||||
|
setState(() {
|
||||||
|
prepareToPrevChapter = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
} else if (scrollController.position.pixels >=
|
} else if (scrollController.position.pixels >=
|
||||||
scrollController.position.maxScrollExtent &&
|
scrollController.position.maxScrollExtent &&
|
||||||
!reader.isLastChapterOfGroup) {
|
!reader.isLastChapterOfGroup) {
|
||||||
context.readerScaffold.setFloatingButton(1);
|
if (!prepareToNextChapter) {
|
||||||
|
jumpToPrevChapter = false;
|
||||||
|
jumpToNextChapter = false;
|
||||||
|
context.readerScaffold.setFloatingButton(1);
|
||||||
|
setState(() {
|
||||||
|
prepareToNextChapter = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
context.readerScaffold.setFloatingButton(0);
|
context.readerScaffold.setFloatingButton(0);
|
||||||
|
if (prepareToPrevChapter || prepareToNextChapter) {
|
||||||
|
jumpToPrevChapter = false;
|
||||||
|
jumpToNextChapter = false;
|
||||||
|
setState(() {
|
||||||
|
prepareToPrevChapter = false;
|
||||||
|
prepareToNextChapter = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -618,6 +682,26 @@ class _ContinuousModeState extends State<_ContinuousMode>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget buildBackground(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
SizedBox(height: context.padding.top + 16),
|
||||||
|
if (prepareToPrevChapter)
|
||||||
|
_SwipeChangeChapterProgress(
|
||||||
|
controller: scrollController,
|
||||||
|
isPrev: true,
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
if (prepareToNextChapter)
|
||||||
|
_SwipeChangeChapterProgress(
|
||||||
|
controller: scrollController,
|
||||||
|
isPrev: false,
|
||||||
|
),
|
||||||
|
SizedBox(height: context.padding.bottom + 16),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> animateToPage(int page) {
|
Future<void> animateToPage(int page) {
|
||||||
return itemScrollController.scrollTo(
|
return itemScrollController.scrollTo(
|
||||||
@@ -758,3 +842,127 @@ void _precacheImage(int page, BuildContext context) {
|
|||||||
context,
|
context,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _SwipeChangeChapterProgress extends StatefulWidget {
|
||||||
|
const _SwipeChangeChapterProgress({
|
||||||
|
this.controller,
|
||||||
|
required this.isPrev,
|
||||||
|
});
|
||||||
|
|
||||||
|
final ScrollController? controller;
|
||||||
|
|
||||||
|
final bool isPrev;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_SwipeChangeChapterProgress> createState() =>
|
||||||
|
_SwipeChangeChapterProgressState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SwipeChangeChapterProgressState
|
||||||
|
extends State<_SwipeChangeChapterProgress> {
|
||||||
|
double value = 0;
|
||||||
|
|
||||||
|
late final isPrev = widget.isPrev;
|
||||||
|
|
||||||
|
ScrollController? controller;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
if (widget.controller != null) {
|
||||||
|
controller = widget.controller;
|
||||||
|
controller!.addListener(onScroll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(covariant _SwipeChangeChapterProgress oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
if (oldWidget.controller != widget.controller) {
|
||||||
|
controller?.removeListener(onScroll);
|
||||||
|
controller = widget.controller;
|
||||||
|
controller?.addListener(onScroll);
|
||||||
|
if (value != 0) {
|
||||||
|
setState(() {
|
||||||
|
value = 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
controller?.removeListener(onScroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onScroll() {
|
||||||
|
var position = controller!.position.pixels;
|
||||||
|
var offset = isPrev
|
||||||
|
? controller!.position.minScrollExtent - position
|
||||||
|
: position - controller!.position.maxScrollExtent;
|
||||||
|
var newValue = offset / _kChangeChapterOffset;
|
||||||
|
newValue = newValue.clamp(0.0, 1.0);
|
||||||
|
if (newValue != value) {
|
||||||
|
setState(() {
|
||||||
|
value = newValue;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final msg = widget.isPrev
|
||||||
|
? "Swipe down for previous chapter".tl
|
||||||
|
: "Swipe up for next chapter".tl;
|
||||||
|
|
||||||
|
return CustomPaint(
|
||||||
|
painter: _ProgressPainter(
|
||||||
|
value: value,
|
||||||
|
backgroundColor: context.colorScheme.surfaceContainer,
|
||||||
|
color: context.colorScheme.primaryContainer,
|
||||||
|
),
|
||||||
|
child: Text(msg).paddingVertical(4).paddingHorizontal(16),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ProgressPainter extends CustomPainter {
|
||||||
|
final double value;
|
||||||
|
|
||||||
|
final Color backgroundColor;
|
||||||
|
|
||||||
|
final Color color;
|
||||||
|
|
||||||
|
const _ProgressPainter({
|
||||||
|
required this.value,
|
||||||
|
required this.backgroundColor,
|
||||||
|
required this.color,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
final paint = Paint()
|
||||||
|
..color = backgroundColor
|
||||||
|
..style = PaintingStyle.fill;
|
||||||
|
canvas.drawRRect(
|
||||||
|
RRect.fromLTRBR(0, 0, size.width, size.height, Radius.circular(16)),
|
||||||
|
paint,
|
||||||
|
);
|
||||||
|
|
||||||
|
paint.color = color;
|
||||||
|
canvas.drawRRect(
|
||||||
|
RRect.fromLTRBR(
|
||||||
|
0, 0, size.width * value, size.height, Radius.circular(16)),
|
||||||
|
paint,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(covariant CustomPainter oldDelegate) {
|
||||||
|
return oldDelegate is! _ProgressPainter ||
|
||||||
|
oldDelegate.value != value ||
|
||||||
|
oldDelegate.backgroundColor != backgroundColor ||
|
||||||
|
oldDelegate.color != color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -26,73 +26,21 @@ class _ReaderScaffoldState extends State<_ReaderScaffold> {
|
|||||||
|
|
||||||
var lastValue = 0;
|
var lastValue = 0;
|
||||||
|
|
||||||
var fABValue = ValueNotifier<double>(0);
|
|
||||||
|
|
||||||
_ReaderGestureDetectorState? _gestureDetectorState;
|
_ReaderGestureDetectorState? _gestureDetectorState;
|
||||||
|
|
||||||
_DragListener? _floatingButtonDragListener;
|
|
||||||
|
|
||||||
void setFloatingButton(int value) {
|
void setFloatingButton(int value) {
|
||||||
lastValue = showFloatingButtonValue;
|
lastValue = showFloatingButtonValue;
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
if (showFloatingButtonValue != 0) {
|
if (showFloatingButtonValue != 0) {
|
||||||
showFloatingButtonValue = 0;
|
showFloatingButtonValue = 0;
|
||||||
fABValue.value = 0;
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
if (_floatingButtonDragListener != null) {
|
|
||||||
_gestureDetectorState!.removeDragListener(_floatingButtonDragListener!);
|
|
||||||
_floatingButtonDragListener = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
var readerMode = context.reader.mode;
|
|
||||||
if (value == 1 && showFloatingButtonValue == 0) {
|
if (value == 1 && showFloatingButtonValue == 0) {
|
||||||
showFloatingButtonValue = 1;
|
showFloatingButtonValue = 1;
|
||||||
_floatingButtonDragListener = _DragListener(
|
|
||||||
onMove: (offset) {
|
|
||||||
if (readerMode == ReaderMode.continuousTopToBottom) {
|
|
||||||
fABValue.value -= offset.dy;
|
|
||||||
} else if (readerMode == ReaderMode.continuousLeftToRight) {
|
|
||||||
fABValue.value -= offset.dx;
|
|
||||||
} else if (readerMode == ReaderMode.continuousRightToLeft) {
|
|
||||||
fABValue.value += offset.dx;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onEnd: () {
|
|
||||||
if (fABValue.value.abs() > 58 * 3) {
|
|
||||||
setState(() {
|
|
||||||
showFloatingButtonValue = 0;
|
|
||||||
});
|
|
||||||
context.reader.toNextChapter();
|
|
||||||
}
|
|
||||||
fABValue.value = 0;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
_gestureDetectorState!.addDragListener(_floatingButtonDragListener!);
|
|
||||||
update();
|
update();
|
||||||
} else if (value == -1 && showFloatingButtonValue == 0) {
|
} else if (value == -1 && showFloatingButtonValue == 0) {
|
||||||
showFloatingButtonValue = -1;
|
showFloatingButtonValue = -1;
|
||||||
_floatingButtonDragListener = _DragListener(
|
|
||||||
onMove: (offset) {
|
|
||||||
if (readerMode == ReaderMode.continuousTopToBottom) {
|
|
||||||
fABValue.value += offset.dy;
|
|
||||||
} else if (readerMode == ReaderMode.continuousLeftToRight) {
|
|
||||||
fABValue.value += offset.dx;
|
|
||||||
} else if (readerMode == ReaderMode.continuousRightToLeft) {
|
|
||||||
fABValue.value -= offset.dx;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onEnd: () {
|
|
||||||
if (fABValue.value.abs() > 58 * 3) {
|
|
||||||
setState(() {
|
|
||||||
showFloatingButtonValue = 0;
|
|
||||||
});
|
|
||||||
context.reader.toPrevChapter();
|
|
||||||
}
|
|
||||||
fABValue.value = 0;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
_gestureDetectorState!.addDragListener(_floatingButtonDragListener!);
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -778,62 +726,35 @@ class _ReaderScaffoldState extends State<_ReaderScaffold> {
|
|||||||
);
|
);
|
||||||
case -1:
|
case -1:
|
||||||
case 1:
|
case 1:
|
||||||
return Container(
|
return SizedBox(
|
||||||
width: 58,
|
width: 58,
|
||||||
height: 58,
|
height: 58,
|
||||||
clipBehavior: Clip.antiAlias,
|
child: Material(
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context).colorScheme.primaryContainer,
|
color: Theme.of(context).colorScheme.primaryContainer,
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
),
|
elevation: 2,
|
||||||
child: ValueListenableBuilder(
|
child: InkWell(
|
||||||
valueListenable: fABValue,
|
onTap: () {
|
||||||
builder: (context, value, child) {
|
if (showFloatingButtonValue == 1) {
|
||||||
return Stack(
|
context.reader.toNextChapter();
|
||||||
children: [
|
} else if (showFloatingButtonValue == -1) {
|
||||||
Positioned.fill(
|
context.reader.toPrevChapter();
|
||||||
child: Material(
|
}
|
||||||
color: Colors.transparent,
|
setFloatingButton(0);
|
||||||
child: InkWell(
|
},
|
||||||
onTap: () {
|
borderRadius: BorderRadius.circular(16),
|
||||||
if (showFloatingButtonValue == 1) {
|
child: Center(
|
||||||
context.reader.toNextChapter();
|
child: Icon(
|
||||||
} else if (showFloatingButtonValue == -1) {
|
showFloatingButtonValue == 1
|
||||||
context.reader.toPrevChapter();
|
? Icons.arrow_forward_ios
|
||||||
}
|
: Icons.arrow_back_ios_outlined,
|
||||||
setFloatingButton(0);
|
size: 24,
|
||||||
},
|
color: Theme.of(context)
|
||||||
borderRadius: BorderRadius.circular(16),
|
.colorScheme
|
||||||
child: Center(
|
.onPrimaryContainer,
|
||||||
child: Icon(
|
),
|
||||||
showFloatingButtonValue == 1
|
),
|
||||||
? Icons.arrow_forward_ios
|
),
|
||||||
: Icons.arrow_back_ios_outlined,
|
|
||||||
size: 24,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.onPrimaryContainer,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Positioned(
|
|
||||||
bottom: 0,
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
height: value.clamp(0, 58 * 3) / 3,
|
|
||||||
child: ColoredBox(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.surfaceTint
|
|
||||||
.toOpacity(0.2),
|
|
||||||
child: const SizedBox.expand(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user