diff --git a/lib/common/widgets/network_img_layer.dart b/lib/common/widgets/network_img_layer.dart index 0a8bb028..03adc166 100644 --- a/lib/common/widgets/network_img_layer.dart +++ b/lib/common/widgets/network_img_layer.dart @@ -1,6 +1,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:hive/hive.dart'; +import 'package:pilipala/utils/extension.dart'; import '../../utils/storage.dart'; import '../constants.dart'; @@ -12,55 +13,75 @@ class NetworkImgLayer extends StatelessWidget { this.src, required this.width, required this.height, - this.cacheW, - this.cacheH, this.type, this.fadeOutDuration, this.fadeInDuration, // 图片质量 默认1% this.quality, + this.origAspectRatio, }); final String? src; - final double? width; - final double? height; - final double? cacheW; - final double? cacheH; + final double width; + final double height; final String? type; final Duration? fadeOutDuration; final Duration? fadeInDuration; final int? quality; + final double? origAspectRatio; @override Widget build(BuildContext context) { - final double pr = MediaQuery.of(context).devicePixelRatio; - final int picQuality = - setting.get(SettingBoxKey.defaultPicQa, defaultValue: 10) as int; + final String imageUrl = + '${src!.startsWith('//') ? 'https:${src!}' : src!}@${quality ?? 100}q.webp'; + int? memCacheWidth, memCacheHeight; + double aspectRatio = (width / height).toDouble(); - // double pr = 2; - return src != '' + 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); + } else { + memCacheWidth = width.cacheSize(context); + memCacheHeight = height.cacheSize(context); + } + } + } + + setMemCacheSizes(); + + if (memCacheWidth == null && memCacheHeight == null) { + memCacheWidth = width.toInt(); + } + + return src != '' && src != null ? ClipRRect( - clipBehavior: Clip.hardEdge, - borderRadius: BorderRadius.circular(type == 'avatar' - ? 50 - : type == 'emote' - ? 0 - : StyleString.imgRadius.x), + clipBehavior: Clip.antiAlias, + borderRadius: BorderRadius.circular( + type == 'avatar' + ? 50 + : type == 'emote' + ? 0 + : StyleString.imgRadius.x, + ), child: CachedNetworkImage( - imageUrl: - '${src!.startsWith('//') ? 'https:${src!}' : src!}@${quality ?? picQuality}q.webp', - width: width ?? double.infinity, - height: height ?? double.infinity, - maxWidthDiskCache: ((cacheW ?? width!) * pr).toInt(), - // maxHeightDiskCache: (cacheH ?? height!).toInt(), - memCacheWidth: ((cacheW ?? width!) * pr).toInt(), - // memCacheHeight: (cacheH ?? height!).toInt(), + imageUrl: imageUrl, + width: width, + height: height, + memCacheWidth: memCacheWidth, + memCacheHeight: memCacheHeight, fit: BoxFit.cover, fadeOutDuration: - fadeOutDuration ?? const Duration(milliseconds: 200), + fadeOutDuration ?? const Duration(milliseconds: 120), fadeInDuration: - fadeInDuration ?? const Duration(milliseconds: 200), - // filterQuality: FilterQuality.high, + fadeInDuration ?? const Duration(milliseconds: 120), + filterQuality: FilterQuality.high, errorWidget: (BuildContext context, String url, Object error) => placeholder(context), placeholder: (BuildContext context, String url) => @@ -72,9 +93,9 @@ class NetworkImgLayer extends StatelessWidget { Widget placeholder(BuildContext context) { return Container( - width: width ?? double.infinity, - height: height ?? double.infinity, - clipBehavior: Clip.hardEdge, + width: width, + height: height, + clipBehavior: Clip.antiAlias, decoration: BoxDecoration( color: Theme.of(context).colorScheme.onInverseSurface.withOpacity(0.4), borderRadius: BorderRadius.circular(type == 'avatar' @@ -84,13 +105,16 @@ class NetworkImgLayer extends StatelessWidget { : StyleString.imgRadius.x), ), child: Center( - child: Image.asset( - type == 'avatar' - ? 'assets/images/noface.jpeg' - : 'assets/images/loading.png', - width: 300, - height: 300, - )), + child: Image.asset( + type == 'avatar' + ? 'assets/images/noface.jpeg' + : 'assets/images/loading.png', + width: width, + height: height, + cacheWidth: width.cacheSize(context), + cacheHeight: height.cacheSize(context), + ), + ), ); } } diff --git a/lib/pages/dynamics/widgets/content_panel.dart b/lib/pages/dynamics/widgets/content_panel.dart index 680d21a2..7072d9cf 100644 --- a/lib/pages/dynamics/widgets/content_panel.dart +++ b/lib/pages/dynamics/widgets/content_panel.dart @@ -48,6 +48,7 @@ class _ContentState extends State { WidgetSpan( child: LayoutBuilder( builder: (context, BoxConstraints box) { + double maxWidth = box.maxWidth.truncateToDouble(); return GestureDetector( onTap: () { showDialog( @@ -62,8 +63,8 @@ class _ContentState extends State { padding: const EdgeInsets.only(top: 4), child: NetworkImgLayer( src: pictureItem.url, - width: box.maxWidth / 2, - height: box.maxWidth * + width: maxWidth / 2, + height: maxWidth * 0.5 * (pictureItem.height != null && pictureItem.width != null ? pictureItem.height! / pictureItem.width! @@ -83,6 +84,7 @@ class _ContentState extends State { list.add( LayoutBuilder( builder: (context, BoxConstraints box) { + double maxWidth = box.maxWidth.truncateToDouble(); return GestureDetector( onTap: () { showDialog( @@ -95,8 +97,10 @@ class _ContentState extends State { }, child: NetworkImgLayer( src: pics[i].url, - width: box.maxWidth, - height: box.maxWidth, + width: maxWidth, + height: maxWidth, + origAspectRatio: + pics[i].width!.toInt() / pics[i].height!.toInt(), ), ); }, @@ -107,7 +111,7 @@ class _ContentState extends State { WidgetSpan( child: LayoutBuilder( builder: (context, BoxConstraints box) { - double maxWidth = box.maxWidth; + double maxWidth = box.maxWidth.truncateToDouble(); double crossCount = len < 3 ? 2 : 3; double height = maxWidth / crossCount * diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index 8701025f..a2a78caf 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -849,6 +849,14 @@ InlineSpan buildContent( WidgetSpan( child: LayoutBuilder( builder: (BuildContext context, BoxConstraints box) { + double maxHeight = box.maxWidth * 0.6; // 设置最大高度 + double width = (box.maxWidth / 2).truncateToDouble(); + double height = ((box.maxWidth / + 2 * + pictureItem['img_height'] / + pictureItem['img_width'])) + .truncateToDouble(); + print('width: $width, height: $height'); return GestureDetector( onTap: () { showDialog( @@ -859,15 +867,28 @@ InlineSpan buildContent( }, ); }, - child: Padding( + child: Container( padding: const EdgeInsets.only(top: 4), - child: NetworkImgLayer( - src: pictureItem['img_src'], - width: box.maxWidth / 2, - height: box.maxWidth * - 0.5 * - pictureItem['img_height'] / - pictureItem['img_width'], + constraints: BoxConstraints(maxHeight: maxHeight), + width: box.maxWidth / 2, + height: height, + child: Stack( + children: [ + Positioned.fill( + child: NetworkImgLayer( + src: pictureItem['img_src'], + width: box.maxWidth / 2, + height: height, + ), + ), + height > maxHeight + ? const PBadge( + text: '长图', + right: 8, + bottom: 8, + ) + : const SizedBox(), + ], ), ), ); diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 38b81378..ff003a76 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -304,7 +304,7 @@ class _VideoDetailPageState extends State body: ExtendedNestedScrollView( controller: _extendNestCtr, headerSliverBuilder: - (BuildContext _context, bool innerBoxIsScrolled) { + (BuildContext context, bool innerBoxIsScrolled) { return [ Obx( () => SliverAppBar( @@ -459,10 +459,10 @@ class _VideoDetailPageState extends State child: TextButton.icon( style: ButtonStyle( side: MaterialStateProperty - .resolveWith( - (states) { + .resolveWith((states) { return BorderSide( - color: Theme.of(context) + color: Theme.of( + context) .colorScheme .primary .withOpacity(0.5), diff --git a/lib/utils/extension.dart b/lib/utils/extension.dart new file mode 100644 index 00000000..1b54c628 --- /dev/null +++ b/lib/utils/extension.dart @@ -0,0 +1,7 @@ +import 'package:flutter/material.dart'; + +extension ImageExtension on num { + int cacheSize(BuildContext context) { + return (this * MediaQuery.of(context).devicePixelRatio).round(); + } +}