Files
venera/lib/components/layout.dart

151 lines
4.6 KiB
Dart

part of 'components.dart';
class SliverGridViewWithFixedItemHeight extends StatelessWidget {
const SliverGridViewWithFixedItemHeight(
{required this.delegate,
required this.maxCrossAxisExtent,
required this.itemHeight,
super.key});
final SliverChildDelegate delegate;
final double maxCrossAxisExtent;
final double itemHeight;
@override
Widget build(BuildContext context) {
return SliverLayoutBuilder(
builder: (context, constraints) => SliverGrid(
delegate: delegate,
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: maxCrossAxisExtent,
childAspectRatio: calcChildAspectRatio(constraints.crossAxisExtent),
),
),
);
}
double calcChildAspectRatio(double width) {
var crossItems = width ~/ maxCrossAxisExtent;
if (width % maxCrossAxisExtent != 0) {
crossItems += 1;
}
final itemWidth = width / crossItems;
return itemWidth / itemHeight;
}
}
class SliverGridDelegateWithFixedHeight extends SliverGridDelegate {
const SliverGridDelegateWithFixedHeight({
required this.maxCrossAxisExtent,
required this.itemHeight,
});
final double maxCrossAxisExtent;
final double itemHeight;
@override
SliverGridLayout getLayout(SliverConstraints constraints) {
final width = constraints.crossAxisExtent;
var crossItems = width ~/ maxCrossAxisExtent;
if (width % maxCrossAxisExtent != 0) {
crossItems += 1;
}
return SliverGridRegularTileLayout(
crossAxisCount: crossItems,
mainAxisStride: itemHeight,
crossAxisStride: width / crossItems,
childMainAxisExtent: itemHeight,
childCrossAxisExtent: width / crossItems,
reverseCrossAxis: false);
}
@override
bool shouldRelayout(covariant SliverGridDelegate oldDelegate) {
if (oldDelegate is! SliverGridDelegateWithFixedHeight) return true;
if (oldDelegate.maxCrossAxisExtent != maxCrossAxisExtent ||
oldDelegate.itemHeight != itemHeight) {
return true;
}
return false;
}
}
class SliverGridDelegateWithComics extends SliverGridDelegate {
SliverGridDelegateWithComics();
final bool useBriefMode = appdata.settings['comicDisplayMode'] == 'brief';
final double scale = (appdata.settings['comicTileScale'] as num).toDouble();
@override
SliverGridLayout getLayout(SliverConstraints constraints) {
if (useBriefMode) {
return getBriefModeLayout(
constraints,
scale,
);
} else {
return getDetailedModeLayout(
constraints,
scale,
);
}
}
SliverGridLayout getDetailedModeLayout(
SliverConstraints constraints, double scale) {
const minCrossAxisExtent = 360;
final itemHeight = 152 * scale;
final width = constraints.crossAxisExtent;
var crossItems = width ~/ minCrossAxisExtent;
crossItems = math.max(1, crossItems);
return SliverGridRegularTileLayout(
crossAxisCount: crossItems,
mainAxisStride: itemHeight,
crossAxisStride: width / crossItems,
childMainAxisExtent: itemHeight,
childCrossAxisExtent: width / crossItems,
reverseCrossAxis: false);
}
SliverGridLayout getBriefModeLayout(
SliverConstraints constraints, double scale) {
final maxCrossAxisExtent = 192.0 * scale;
const childAspectRatio = 0.64;
const crossAxisSpacing = 0.0;
int crossAxisCount =
(constraints.crossAxisExtent / (maxCrossAxisExtent + crossAxisSpacing))
.ceil();
// Ensure a minimum count of 1, can be zero and result in an infinite extent
// below when the window size is 0.
crossAxisCount = math.max(1, crossAxisCount);
final double usableCrossAxisExtent = math.max(
0.0,
constraints.crossAxisExtent - crossAxisSpacing * (crossAxisCount - 1),
);
final double childCrossAxisExtent = usableCrossAxisExtent / crossAxisCount;
final double childMainAxisExtent = childCrossAxisExtent / childAspectRatio;
return SliverGridRegularTileLayout(
crossAxisCount: crossAxisCount,
mainAxisStride: childMainAxisExtent,
crossAxisStride: childCrossAxisExtent + crossAxisSpacing,
childMainAxisExtent: childMainAxisExtent,
childCrossAxisExtent: childCrossAxisExtent,
reverseCrossAxis: axisDirectionIsReversed(constraints.crossAxisDirection),
);
}
@override
bool shouldRelayout(covariant SliverGridDelegate oldDelegate) {
if (oldDelegate is! SliverGridDelegateWithComics) return true;
if (oldDelegate.scale != scale ||
oldDelegate.useBriefMode != useBriefMode) {
return true;
}
return false;
}
}