diff --git a/lib/bean/card/network_img_layer.dart b/lib/bean/card/network_img_layer.dart index 487e527f1..997dc7a27 100644 --- a/lib/bean/card/network_img_layer.dart +++ b/lib/bean/card/network_img_layer.dart @@ -3,8 +3,7 @@ import 'package:flutter/material.dart'; import 'package:kazumi/utils/constants.dart'; import 'package:kazumi/utils/extension.dart'; import 'package:kazumi/utils/logger.dart'; - -class NetworkImgLayer extends StatelessWidget { +class NetworkImgLayer extends StatefulWidget { const NetworkImgLayer({ super.key, this.src, @@ -26,58 +25,64 @@ class NetworkImgLayer extends StatelessWidget { final int? quality; final double? origAspectRatio; + @override + State createState() => _NetworkImgLayerState(); +} + +class _NetworkImgLayerState extends State { + int? memCacheWidth, memCacheHeight; @override Widget build(BuildContext context) { - final String imageUrl = src ?? ''; + final String imageUrl = widget.src ?? ''; //// We need this to shink memory usage - int? memCacheWidth, memCacheHeight; - double aspectRatio = (width / height).toDouble(); - - void setMemCacheSizes() { - if (aspectRatio > 1) { - memCacheHeight = height.cacheSize(context); - } else if (aspectRatio < 1) { - memCacheWidth = width.cacheSize(context); - } else { - if (origAspectRatio != null && origAspectRatio! > 1) { - memCacheWidth = width.cacheSize(context); - } else if (origAspectRatio != null && origAspectRatio! < 1) { - memCacheHeight = height.cacheSize(context); + if (memCacheWidth == null && memCacheHeight == null) { + double aspectRatio = (widget.width / widget.height).toDouble(); + void setMemCacheSizes() { + if (aspectRatio > 1) { + memCacheHeight = widget.height.cacheSize(context); + } else if (aspectRatio < 1) { + memCacheWidth = widget.width.cacheSize(context); } else { - memCacheWidth = width.cacheSize(context); - memCacheHeight = height.cacheSize(context); + if (widget.origAspectRatio != null && widget.origAspectRatio! > 1) { + memCacheWidth = widget.width.cacheSize(context); + } else if (widget.origAspectRatio != null && widget.origAspectRatio! < 1) { + memCacheHeight = widget.height.cacheSize(context); + } else { + memCacheWidth = widget.width.cacheSize(context); + memCacheHeight = widget.height.cacheSize(context); + } } } - } - setMemCacheSizes(); + setMemCacheSizes(); - if (memCacheWidth == null && memCacheHeight == null) { - memCacheWidth = width.toInt(); + if (memCacheWidth == null && memCacheHeight == null) { + memCacheWidth = widget.width.toInt(); + } } - return src != '' && src != null + return widget.src != '' && widget.src != null ? ClipRRect( clipBehavior: Clip.antiAlias, borderRadius: BorderRadius.circular( - type == 'avatar' + widget.type == 'avatar' ? 50 - : type == 'emote' + : widget.type == 'emote' ? 0 : StyleString.imgRadius.x, ), child: CachedNetworkImage( imageUrl: imageUrl, - width: width, - height: height, + width: widget.width, + height: widget.height, memCacheWidth: memCacheWidth, memCacheHeight: memCacheHeight, fit: BoxFit.cover, fadeOutDuration: - fadeOutDuration ?? const Duration(milliseconds: 120), + widget.fadeOutDuration ?? const Duration(milliseconds: 120), fadeInDuration: - fadeInDuration ?? const Duration(milliseconds: 120), + widget.fadeInDuration ?? const Duration(milliseconds: 120), filterQuality: FilterQuality.high, errorListener: (e) { KazumiLogger().w("NetworkImage: network image load error", error: e); @@ -91,29 +96,32 @@ class NetworkImgLayer extends StatelessWidget { } Widget placeholder(BuildContext context) { + final int? cacheW = widget.width.cacheSize(context); + final int? cacheH = widget.height.cacheSize(context); + return Container( - width: width, - height: height, + width: widget.width, + height: widget.height, clipBehavior: Clip.antiAlias, decoration: BoxDecoration( color: Theme.of(context).colorScheme.onInverseSurface.withValues(alpha: 0.4), - borderRadius: BorderRadius.circular(type == 'avatar' + borderRadius: BorderRadius.circular(widget.type == 'avatar' ? 50 - : type == 'emote' + : widget.type == 'emote' ? 0 : StyleString.imgRadius.x), ), - child: type == 'bg' + child: widget.type == 'bg' ? const SizedBox() : Center( child: Image.asset( - type == 'avatar' + widget.type == 'avatar' ? 'assets/images/noface.jpeg' : 'assets/images/loading.png', - width: width, - height: height, - cacheWidth: width.cacheSize(context), - cacheHeight: height.cacheSize(context), + width: widget.width, + height: widget.height, + cacheWidth: (cacheW != null && cacheW > 0) ? cacheW : null, + cacheHeight: (cacheH != null && cacheH > 0) ? cacheH : null, ), ), ); diff --git a/lib/pages/collect/collect_page.dart b/lib/pages/collect/collect_page.dart index 747197492..b15f7b22d 100644 --- a/lib/pages/collect/collect_page.dart +++ b/lib/pages/collect/collect_page.dart @@ -152,12 +152,11 @@ class _CollectPageState extends State list.sort((a, b) => b.time.millisecondsSinceEpoch .compareTo(a.time.millisecondsSinceEpoch)); } - int crossCount = 3; + int crossCount; if (MediaQuery.sizeOf(context).width > LayoutBreakpoint.compact['width']!) { - crossCount = 5; - } - if (MediaQuery.sizeOf(context).width > LayoutBreakpoint.medium['width']!) { - crossCount = 6; + crossCount = 3 + ((MediaQuery.sizeOf(context).width-LayoutBreakpoint.compact['width']!) ~/ 200); + } else { + crossCount = 3; } for (List collectedBangumiRenderItem in collectedBangumiRenderItemList) { diff --git a/lib/pages/menu/menu.dart b/lib/pages/menu/menu.dart index 6e10810c2..09264ac41 100644 --- a/lib/pages/menu/menu.dart +++ b/lib/pages/menu/menu.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_modular/flutter_modular.dart'; import 'package:kazumi/bean/widget/embedded_native_control_area.dart'; +import 'package:kazumi/bean/appbar/drag_to_move_bar.dart'; import 'package:kazumi/pages/router.dart'; import 'package:provider/provider.dart'; @@ -38,8 +39,41 @@ class NavigationBarState extends ChangeNotifier { } } +// 通用导航项 +class _NavItem { + final IconData icon; + final IconData selectedIcon; + final String label; + const _NavItem(this.icon, this.selectedIcon, this.label); +} + class _ScaffoldMenu extends State { final PageController _page = PageController(); + final GlobalKey _pageViewKey = GlobalKey(); + + // 通用导航内容 + static const List<_NavItem> _navItems = <_NavItem>[ + _NavItem(Icons.home_outlined, Icons.home, '推荐'), + _NavItem(Icons.timeline_outlined, Icons.timeline, '时间表'), + _NavItem(Icons.favorite_border, Icons.favorite, '追番'), + _NavItem(Icons.settings_outlined, Icons.settings, '我的'), + ]; + static List get _bottomDestinations => _navItems + .map((e) => NavigationDestination(selectedIcon: Icon(e.selectedIcon), icon: Icon(e.icon), label: e.label)) + .toList(); + static List get _sideDestinations => _navItems + .map((e) => NavigationRailDestination(selectedIcon: Icon(e.selectedIcon), icon: Icon(e.icon), label: Text(e.label))) + .toList(); + + Widget _buildPageView() { + return PageView.builder( + key: _pageViewKey, + physics: const NeverScrollableScrollPhysics(), + controller: _page, + itemCount: menu.size, + itemBuilder: (_, __) => const RouterOutlet(), + ); + } @override Widget build(BuildContext context) { @@ -59,38 +93,12 @@ class _ScaffoldMenu extends State { return Scaffold( body: Container( color: Theme.of(context).colorScheme.primaryContainer, - child: PageView.builder( - physics: const NeverScrollableScrollPhysics(), - controller: _page, - itemCount: menu.size, - itemBuilder: (_, __) => const RouterOutlet(), - ), + child: _buildPageView(), ), bottomNavigationBar: state.isHide ? const SizedBox(height: 0) : NavigationBar( - destinations: const [ - NavigationDestination( - selectedIcon: Icon(Icons.home), - icon: Icon(Icons.home_outlined), - label: '推荐', - ), - NavigationDestination( - selectedIcon: Icon(Icons.timeline), - icon: Icon(Icons.timeline_outlined), - label: '时间表', - ), - NavigationDestination( - selectedIcon: Icon(Icons.favorite), - icon: Icon(Icons.favorite_outlined), - label: '追番', - ), - NavigationDestination( - selectedIcon: Icon(Icons.settings), - icon: Icon(Icons.settings), - label: '我的', - ), - ], + destinations: _bottomDestinations, selectedIndex: state.selectedIndex, onDestinationSelected: (int index) { state.updateSelectedIndex(index); @@ -107,45 +115,26 @@ class _ScaffoldMenu extends State { EmbeddedNativeControlArea( child: Visibility( visible: !state.isHide, - child: NavigationRail( - backgroundColor: Theme.of(context).colorScheme.surfaceContainer, - groupAlignment: 1.0, - leading: FloatingActionButton( - elevation: 0, - heroTag: null, - onPressed: () { - Modular.to.pushNamed('/search/'); + child: DragToMoveArea( + child: NavigationRail( + backgroundColor: Theme.of(context).colorScheme.surfaceContainer, + groupAlignment: 1.0, + leading: FloatingActionButton( + elevation: 0, + heroTag: null, + onPressed: () { + Modular.to.pushNamed('/search/'); + }, + child: const Icon(Icons.search), + ), + labelType: NavigationRailLabelType.selected, + destinations: _sideDestinations, + selectedIndex: state.selectedIndex, + onDestinationSelected: (int index) { + state.updateSelectedIndex(index); + Modular.to.navigate("/tab${menu.getPath(index)}/"); }, - child: const Icon(Icons.search), ), - labelType: NavigationRailLabelType.selected, - destinations: const [ - NavigationRailDestination( - selectedIcon: Icon(Icons.home), - icon: Icon(Icons.home_outlined), - label: Text('推荐'), - ), - NavigationRailDestination( - selectedIcon: Icon(Icons.timeline), - icon: Icon(Icons.timeline_outlined), - label: Text('时间表'), - ), - NavigationRailDestination( - selectedIcon: Icon(Icons.favorite), - icon: Icon(Icons.favorite_border), - label: Text('追番'), - ), - NavigationRailDestination( - selectedIcon: Icon(Icons.settings), - icon: Icon(Icons.settings_outlined), - label: Text('我的'), - ), - ], - selectedIndex: state.selectedIndex, - onDestinationSelected: (int index) { - state.updateSelectedIndex(index); - Modular.to.navigate("/tab${menu.getPath(index)}/"); - }, ), ), ), @@ -163,11 +152,7 @@ class _ScaffoldMenu extends State { topLeft: Radius.circular(16.0), bottomLeft: Radius.circular(16.0), ), - child: PageView.builder( - physics: const NeverScrollableScrollPhysics(), - itemCount: menu.size, - itemBuilder: (_, __) => const RouterOutlet(), - ), + child: _buildPageView(), ), ), ), diff --git a/lib/pages/popular/popular_page.dart b/lib/pages/popular/popular_page.dart index c17687b09..13e53cb90 100644 --- a/lib/pages/popular/popular_page.dart +++ b/lib/pages/popular/popular_page.dart @@ -164,12 +164,11 @@ class _PopularPageState extends State } Widget contentGrid(bangumiList) { - int crossCount = 3; + int crossCount; if (MediaQuery.sizeOf(context).width > LayoutBreakpoint.compact['width']!) { - crossCount = 5; - } - if (MediaQuery.sizeOf(context).width > LayoutBreakpoint.medium['width']!) { - crossCount = 6; + crossCount = 3 + ((MediaQuery.sizeOf(context).width-LayoutBreakpoint.compact['width']!) ~/ 200); + } else { + crossCount = 3; } return SliverPadding( padding: const EdgeInsets.all(8),