logo和名称替换
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:hgmj/assets_tool/images.dart';
|
||||
import 'package:hgmj/hj_utils/screen.dart';
|
||||
import 'package:wydj/assets_tool/images.dart';
|
||||
import 'package:wydj/hj_utils/screen.dart';
|
||||
import 'package:mobkit_dashed_border/mobkit_dashed_border.dart';
|
||||
|
||||
class AddMediaSourceButton extends StatelessWidget {
|
||||
@@ -43,11 +43,13 @@ class AddMediaSourceButton extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
((111 - 24) / 2).sizeBoxH,
|
||||
Image.asset('add_grey.png'.communityPath, width: 24, color: const Color(0xffDCDCDC)),
|
||||
Image.asset('add_grey.png'.communityPath,
|
||||
width: 24, color: const Color(0xffDCDCDC)),
|
||||
9.sizeBoxH,
|
||||
Text(
|
||||
title ?? (isVideo ? '添加视频' : '添加图片'),
|
||||
style: TextStyle(color: const Color(0xff999999), fontSize: 14.sp),
|
||||
style:
|
||||
TextStyle(color: const Color(0xff999999), fontSize: 14.sp),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hgmj/tools_base/widget/card_swiper/src/swiper_plugin.dart';
|
||||
import 'package:wydj/tools_base/widget/card_swiper/src/swiper_plugin.dart';
|
||||
|
||||
class SwiperControl extends SwiperPlugin {
|
||||
const SwiperControl({
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hgmj/assets_tool/app_colors.dart';
|
||||
import 'package:hgmj/hj_utils/screen.dart';
|
||||
import 'package:hgmj/tools_base/widget/common_dialog.dart';
|
||||
import 'package:wydj/assets_tool/app_colors.dart';
|
||||
import 'package:wydj/hj_utils/screen.dart';
|
||||
import 'package:wydj/tools_base/widget/common_dialog.dart';
|
||||
|
||||
/// 全站统一的提示/确认弹窗:标题 + 分割线 + 正文 + 副文案 + 灰「取消」红「确定」双按钮。
|
||||
/// 壳走 [CommonDialog],业务结果一律用返回值传(点确定=true),别在弹窗里塞跳转逻辑。
|
||||
@@ -68,7 +68,10 @@ class CommonAlert extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(color: Colors.white.withValues(alpha: .9), fontSize: 20, fontWeight: FontWeight.w600),
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: .9),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
if (showDivider) ...[
|
||||
12.sizeBoxH,
|
||||
@@ -79,7 +82,10 @@ class CommonAlert extends StatelessWidget {
|
||||
Text(
|
||||
content!,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: Colors.white.withValues(alpha: .5), fontSize: 16, fontWeight: FontWeight.w500),
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: .5),
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500),
|
||||
),
|
||||
],
|
||||
if (subContent?.isNotEmpty == true) ...[
|
||||
@@ -89,7 +95,8 @@ class CommonAlert extends StatelessWidget {
|
||||
child: Text(
|
||||
subContent!,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: Colors.white.withValues(alpha: .5), fontSize: 16),
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: .5), fontSize: 16),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -111,7 +118,10 @@ class CommonAlert extends StatelessWidget {
|
||||
),
|
||||
child: Text(
|
||||
cancelText,
|
||||
style: const TextStyle(color: Color(0xff989898), fontSize: 16, fontWeight: FontWeight.w500),
|
||||
style: const TextStyle(
|
||||
color: Color(0xff989898),
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -129,7 +139,10 @@ class CommonAlert extends StatelessWidget {
|
||||
),
|
||||
child: Text(
|
||||
confirmText,
|
||||
style: const TextStyle(color: Colors.black, fontSize: 16, fontWeight: FontWeight.w500),
|
||||
style: const TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hgmj/assets_tool/images.dart';
|
||||
import 'package:hgmj/hj_utils/screen.dart';
|
||||
import 'package:wydj/assets_tool/images.dart';
|
||||
import 'package:wydj/hj_utils/screen.dart';
|
||||
|
||||
import '../../assets_tool/app_colors.dart';
|
||||
import '../../hj_utils/api_service/acg_service.dart';
|
||||
import '../../hj_utils/api_service/mine_service.dart';
|
||||
import 'package:hgmj/tools_base/toast.dart';
|
||||
import 'package:wydj/tools_base/toast.dart';
|
||||
import '../../hj_utils/widget_util.dart';
|
||||
|
||||
enum FollowEnum {
|
||||
@@ -64,7 +64,9 @@ class _FollowButtonState extends State<FollowButton> {
|
||||
child: isLoading
|
||||
? _loading()
|
||||
: Image.asset(
|
||||
isFollow ? 'collect_red.png'.commonImgPath : 'collect_path.png'.commonImgPath,
|
||||
isFollow
|
||||
? 'collect_red.png'.commonImgPath
|
||||
: 'collect_path.png'.commonImgPath,
|
||||
width: 24,
|
||||
),
|
||||
);
|
||||
@@ -86,11 +88,17 @@ class _FollowButtonState extends State<FollowButton> {
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
isLoading ? _loading() : const Icon(Icons.check, size: 14, color: Color(0xff989898)),
|
||||
isLoading
|
||||
? _loading()
|
||||
: const Icon(Icons.check,
|
||||
size: 14, color: Color(0xff989898)),
|
||||
4.sizeBoxW,
|
||||
const Text(
|
||||
'关注',
|
||||
style: TextStyle(fontSize: 10, fontWeight: FontWeight.w500, color: Color(0xff989898)),
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Color(0xff989898)),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -104,11 +112,17 @@ class _FollowButtonState extends State<FollowButton> {
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
isLoading ? _loading() : const Icon(Icons.add, size: 14, color: AppColors.actionRed),
|
||||
isLoading
|
||||
? _loading()
|
||||
: const Icon(Icons.add,
|
||||
size: 14, color: AppColors.actionRed),
|
||||
4.sizeBoxW,
|
||||
const Text(
|
||||
'关注',
|
||||
style: TextStyle(fontSize: 10, fontWeight: FontWeight.w500, color: AppColors.actionRed),
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColors.actionRed),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -132,20 +146,25 @@ class _FollowButtonState extends State<FollowButton> {
|
||||
borderRadius: BorderRadius.circular(3),
|
||||
),
|
||||
child: isFollow
|
||||
? Text('已收藏', style: textStyle(10, Colors.white, FontWeight.w400))
|
||||
? Text('已收藏',
|
||||
style: textStyle(10, Colors.white, FontWeight.w400))
|
||||
: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Image.asset('add_red.png'.commonImgPath, width: 16, color: Colors.black),
|
||||
Image.asset('add_red.png'.commonImgPath,
|
||||
width: 16, color: Colors.black),
|
||||
2.sizeBoxW,
|
||||
Text('收藏', style: textStyle(10, Colors.black, FontWeight.w400)),
|
||||
Text('收藏',
|
||||
style:
|
||||
textStyle(10, Colors.black, FontWeight.w400)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _loading() => const CupertinoActivityIndicator(color: Colors.white, radius: 8);
|
||||
Widget _loading() =>
|
||||
const CupertinoActivityIndicator(color: Colors.white, radius: 8);
|
||||
|
||||
//加入书架 / 取消收藏
|
||||
void _onCollectTap() => isFollow ? _unCollect() : _collect();
|
||||
@@ -153,7 +172,8 @@ class _FollowButtonState extends State<FollowButton> {
|
||||
void _unCollect() async {
|
||||
if (isLoading) return;
|
||||
setState(() => isLoading = true);
|
||||
if (await ACGService.deleteBookshelf(mediaId ?? '')) widget.onSuccess?.call(false);
|
||||
if (await ACGService.deleteBookshelf(mediaId ?? ''))
|
||||
widget.onSuccess?.call(false);
|
||||
isLoading = false;
|
||||
if (mounted) setState(() {});
|
||||
}
|
||||
@@ -161,7 +181,8 @@ class _FollowButtonState extends State<FollowButton> {
|
||||
void _collect() async {
|
||||
if (isLoading) return;
|
||||
setState(() => isLoading = true);
|
||||
if (await ACGService.addBookshelf(mediaId ?? '')) widget.onSuccess?.call(true);
|
||||
if (await ACGService.addBookshelf(mediaId ?? ''))
|
||||
widget.onSuccess?.call(true);
|
||||
isLoading = false;
|
||||
if (mounted) setState(() {});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hgmj/tools_base/widget/net_image_widget.dart';
|
||||
import 'package:wydj/tools_base/widget/net_image_widget.dart';
|
||||
|
||||
///用户头像
|
||||
class HeaderWidget extends StatelessWidget {
|
||||
@@ -27,7 +27,8 @@ class HeaderWidget extends StatelessWidget {
|
||||
height: headHeight,
|
||||
decoration: isCircle
|
||||
? const BoxDecoration(
|
||||
border: Border.fromBorderSide(BorderSide(width: 4, color: Color.fromRGBO(253, 45, 85, 1))),
|
||||
border: Border.fromBorderSide(
|
||||
BorderSide(width: 4, color: Color.fromRGBO(253, 45, 85, 1))),
|
||||
shape: BoxShape.circle,
|
||||
)
|
||||
: null,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hgmj/assets_tool/app_colors.dart';
|
||||
import 'package:hgmj/assets_tool/images.dart';
|
||||
import 'package:hgmj/hj_utils/image_util.dart';
|
||||
import 'package:hgmj/tools_base/cache/image_cache_manager.dart';
|
||||
import 'package:hgmj/tools_base/loading/loading_alert_widget.dart';
|
||||
import 'package:hgmj/tools_base/toast.dart';
|
||||
import 'package:hgmj/tools_base/widget/net_image_widget.dart';
|
||||
import 'package:wydj/assets_tool/app_colors.dart';
|
||||
import 'package:wydj/assets_tool/images.dart';
|
||||
import 'package:wydj/hj_utils/image_util.dart';
|
||||
import 'package:wydj/tools_base/cache/image_cache_manager.dart';
|
||||
import 'package:wydj/tools_base/loading/loading_alert_widget.dart';
|
||||
import 'package:wydj/tools_base/toast.dart';
|
||||
import 'package:wydj/tools_base/widget/net_image_widget.dart';
|
||||
|
||||
/// 微信风格图片浏览器
|
||||
/// 横滑切图 + 双指/双击缩放 + 上下滑拖拽退出(图片跟手、背景随拖动渐隐露出下层页面) + 长按保存
|
||||
@@ -20,18 +20,26 @@ class ImageBrowserPage extends StatefulWidget {
|
||||
final int initialIndex;
|
||||
final bool showSaveButton; // 右上角显式"保存到相册"按钮(AI 生成图等场景);默认只支持长按保存
|
||||
|
||||
const ImageBrowserPage({super.key, required this.images, this.initialIndex = 0, this.showSaveButton = false});
|
||||
const ImageBrowserPage(
|
||||
{super.key,
|
||||
required this.images,
|
||||
this.initialIndex = 0,
|
||||
this.showSaveButton = false});
|
||||
|
||||
/// 打开浏览器(透明路由 + 淡入)
|
||||
/// [showSaveButton] 显示右上角"保存到相册"按钮
|
||||
static void open(List<String> images, {int index = 0, bool showSaveButton = false}) {
|
||||
static void open(List<String> images,
|
||||
{int index = 0, bool showSaveButton = false}) {
|
||||
final valid = images.where((e) => e.isNotEmpty).toList();
|
||||
if (valid.isEmpty) return;
|
||||
// fullscreenDialog:true → GetX canTransitionTo 返回 false,下层页面不做外出转场,
|
||||
// 保持完整渲染 → 拖拽偷看时看到的是整页而非"pop 一半"。
|
||||
// 瞬时 fadeIn:打开无残影。仍是 Get.to → Get.back 能正常 pop,下滑退出正常
|
||||
Get.to(
|
||||
() => ImageBrowserPage(images: valid, initialIndex: index.clamp(0, valid.length - 1), showSaveButton: showSaveButton),
|
||||
() => ImageBrowserPage(
|
||||
images: valid,
|
||||
initialIndex: index.clamp(0, valid.length - 1),
|
||||
showSaveButton: showSaveButton),
|
||||
opaque: false,
|
||||
transition: Transition.fadeIn,
|
||||
duration: Duration.zero,
|
||||
@@ -43,7 +51,8 @@ class ImageBrowserPage extends StatefulWidget {
|
||||
State<ImageBrowserPage> createState() => _ImageBrowserPageState();
|
||||
}
|
||||
|
||||
class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProviderStateMixin {
|
||||
class _ImageBrowserPageState extends State<ImageBrowserPage>
|
||||
with TickerProviderStateMixin {
|
||||
// ========== 分页 ==========
|
||||
late final PageController _pageCtr;
|
||||
late int _curIndex;
|
||||
@@ -72,11 +81,17 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
|
||||
super.initState();
|
||||
_curIndex = widget.initialIndex;
|
||||
_pageCtr = PageController(initialPage: _curIndex);
|
||||
_transCtrs = List.generate(widget.images.length, (_) => TransformationController());
|
||||
_resetCtr = AnimationController(vsync: this, duration: const Duration(milliseconds: 200));
|
||||
_zoomCtr = AnimationController(vsync: this, duration: const Duration(milliseconds: 200));
|
||||
_enterCtr = AnimationController(vsync: this, duration: const Duration(milliseconds: 220))..forward();
|
||||
_exitCtr = AnimationController(vsync: this, duration: const Duration(milliseconds: 200));
|
||||
_transCtrs =
|
||||
List.generate(widget.images.length, (_) => TransformationController());
|
||||
_resetCtr = AnimationController(
|
||||
vsync: this, duration: const Duration(milliseconds: 200));
|
||||
_zoomCtr = AnimationController(
|
||||
vsync: this, duration: const Duration(milliseconds: 200));
|
||||
_enterCtr = AnimationController(
|
||||
vsync: this, duration: const Duration(milliseconds: 220))
|
||||
..forward();
|
||||
_exitCtr = AnimationController(
|
||||
vsync: this, duration: const Duration(milliseconds: 200));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -97,10 +112,12 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
|
||||
bool get _isZoomed => _transCtrs[_curIndex].value.getMaxScaleOnAxis() > 1.05;
|
||||
|
||||
// 背景不透明度:随竖直拖动距离渐隐(下拉偷看下层)
|
||||
double get _bgOpacity => (1 - _dragY.abs() / (Get.height * 0.6)).clamp(0.0, 1.0);
|
||||
double get _bgOpacity =>
|
||||
(1 - _dragY.abs() / (Get.height * 0.6)).clamp(0.0, 1.0);
|
||||
|
||||
// 拖动时图片轻微缩小
|
||||
double get _dragScale => (1 - _dragY.abs() / (Get.height * 2)).clamp(0.85, 1.0);
|
||||
double get _dragScale =>
|
||||
(1 - _dragY.abs() / (Get.height * 2)).clamp(0.85, 1.0);
|
||||
|
||||
// 退出淡出系数:1→0
|
||||
double get _exitFactor => 1 - _exitCtr.value;
|
||||
@@ -119,8 +136,8 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
|
||||
_exit();
|
||||
return;
|
||||
}
|
||||
final anim =
|
||||
Tween<double>(begin: _dragY, end: 0).animate(CurvedAnimation(parent: _resetCtr, curve: Curves.easeOut));
|
||||
final anim = Tween<double>(begin: _dragY, end: 0)
|
||||
.animate(CurvedAnimation(parent: _resetCtr, curve: Curves.easeOut));
|
||||
void listener() => setState(() => _dragY = anim.value);
|
||||
anim.addListener(listener);
|
||||
// whenComplete 在 dispose 取消 ticker 时也会触发,一律先判 mounted
|
||||
@@ -156,8 +173,8 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
|
||||
-pos.dx * (scale - 1), -pos.dy * (scale - 1), 0, 1, //
|
||||
);
|
||||
}
|
||||
final anim =
|
||||
Matrix4Tween(begin: ctr.value, end: target).animate(CurvedAnimation(parent: _zoomCtr, curve: Curves.easeOut));
|
||||
final anim = Matrix4Tween(begin: ctr.value, end: target)
|
||||
.animate(CurvedAnimation(parent: _zoomCtr, curve: Curves.easeOut));
|
||||
void listener() => ctr.value = anim.value;
|
||||
anim.addListener(listener);
|
||||
_zoomCtr.forward(from: 0).whenComplete(() {
|
||||
@@ -195,7 +212,10 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
|
||||
builder: (_, __) => Stack(
|
||||
children: [
|
||||
// 黑色背景,随拖动/退出渐隐
|
||||
Positioned.fill(child: ColoredBox(color: Colors.black.withValues(alpha: _bgOpacity * _exitFactor))),
|
||||
Positioned.fill(
|
||||
child: ColoredBox(
|
||||
color: Colors.black
|
||||
.withValues(alpha: _bgOpacity * _exitFactor))),
|
||||
GestureDetector(
|
||||
onLongPress: _saveCurrent, // 长按保存
|
||||
onDoubleTapDown: (d) => _tapPos = d.localPosition,
|
||||
@@ -209,7 +229,8 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
|
||||
opacity: _enterCtr,
|
||||
child: Transform.translate(
|
||||
offset: Offset(0, _dragY),
|
||||
child: Transform.scale(scale: _dragScale, child: _pageView()),
|
||||
child:
|
||||
Transform.scale(scale: _dragScale, child: _pageView()),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -226,7 +247,9 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
|
||||
if (_isSaving)
|
||||
const Positioned.fill(
|
||||
child: AbsorbPointer(
|
||||
child: ColoredBox(color: Color(0x80000000), child: LoadingAlertWidget(title: '保存中...')),
|
||||
child: ColoredBox(
|
||||
color: Color(0x80000000),
|
||||
child: LoadingAlertWidget(title: '保存中...')),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -272,7 +295,8 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
|
||||
right: 20,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 11, vertical: 2),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(20)),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white, borderRadius: BorderRadius.circular(20)),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
@@ -287,7 +311,8 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
|
||||
: (isIncoming ? const Offset(0, -1) : const Offset(0, 1));
|
||||
return ClipRect(
|
||||
child: SlideTransition(
|
||||
position: Tween<Offset>(begin: begin, end: Offset.zero).animate(anim),
|
||||
position: Tween<Offset>(begin: begin, end: Offset.zero)
|
||||
.animate(anim),
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
@@ -295,10 +320,12 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
|
||||
child: Text(
|
||||
'${_curIndex + 1}',
|
||||
key: ValueKey(_curIndex),
|
||||
style: const TextStyle(color: AppColors.actionRed, fontSize: 12),
|
||||
style:
|
||||
const TextStyle(color: AppColors.actionRed, fontSize: 12),
|
||||
),
|
||||
),
|
||||
Text('/${widget.images.length}', style: const TextStyle(color: Color(0xff3D3D3D), fontSize: 12)),
|
||||
Text('/${widget.images.length}',
|
||||
style: const TextStyle(color: Color(0xff3D3D3D), fontSize: 12)),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -331,8 +358,11 @@ class _ImageBrowserPageState extends State<ImageBrowserPage> with TickerProvider
|
||||
onTap: _saveCurrent,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(4), color: const Color(0xFFE57310)),
|
||||
child: const Text('保存到相册', style: TextStyle(color: Colors.white, fontSize: 14)),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
color: const Color(0xFFE57310)),
|
||||
child: const Text('保存到相册',
|
||||
style: TextStyle(color: Colors.white, fontSize: 14)),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hgmj/assets_tool/images.dart';
|
||||
import 'package:wydj/assets_tool/images.dart';
|
||||
|
||||
/// 双击点赞爱心动效的触发器。onDoubleTapDown 里 [markAt] 记落点,onDoubleTap 里 [burst] 放动画
|
||||
class LikeBurstController extends ChangeNotifier {
|
||||
@@ -31,16 +31,19 @@ class LikeBurstView extends StatefulWidget {
|
||||
State<LikeBurstView> createState() => _LikeBurstViewState();
|
||||
}
|
||||
|
||||
class _LikeBurstViewState extends State<LikeBurstView> with SingleTickerProviderStateMixin {
|
||||
class _LikeBurstViewState extends State<LikeBurstView>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late final AnimationController _ctr;
|
||||
Offset? _at;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_ctr = AnimationController(vsync: this, duration: const Duration(milliseconds: 600))
|
||||
_ctr = AnimationController(
|
||||
vsync: this, duration: const Duration(milliseconds: 600))
|
||||
..addStatusListener((status) {
|
||||
if (status == AnimationStatus.completed && mounted) setState(() => _at = null);
|
||||
if (status == AnimationStatus.completed && mounted)
|
||||
setState(() => _at = null);
|
||||
});
|
||||
widget.controller.addListener(_onBurst);
|
||||
}
|
||||
@@ -81,8 +84,10 @@ class _LikeBurstViewState extends State<LikeBurstView> with SingleTickerProvider
|
||||
TweenSequenceItem(tween: Tween(begin: 1.0, end: 0.0), weight: 40),
|
||||
]).animate(_ctr),
|
||||
child: ScaleTransition(
|
||||
scale: Tween(begin: 0.5, end: 1.3).animate(CurvedAnimation(parent: _ctr, curve: Curves.easeOutBack)),
|
||||
child: Image.asset(widget.icon.commonImgPath, width: widget.size, height: widget.size),
|
||||
scale: Tween(begin: 0.5, end: 1.3).animate(
|
||||
CurvedAnimation(parent: _ctr, curve: Curves.easeOutBack)),
|
||||
child: Image.asset(widget.icon.commonImgPath,
|
||||
width: widget.size, height: widget.size),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -2,9 +2,9 @@ import 'dart:ui';
|
||||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hgmj/assets_tool/images.dart';
|
||||
import 'package:hgmj/hj_utils/screen.dart';
|
||||
import 'package:hgmj/tools_base/cache/image_cache_manager.dart';
|
||||
import 'package:wydj/assets_tool/images.dart';
|
||||
import 'package:wydj/hj_utils/screen.dart';
|
||||
import 'package:wydj/tools_base/cache/image_cache_manager.dart';
|
||||
|
||||
class NetworkImageLoader extends StatelessWidget {
|
||||
final String? imageUrl;
|
||||
@@ -55,12 +55,15 @@ class NetworkImageLoader extends StatelessWidget {
|
||||
fadeOutCurve: Curves.linear,
|
||||
);
|
||||
final radius = imgBorderRadius ?? BorderRadius.circular(borderRadius);
|
||||
if (borderRadius != 0) image = ClipRRect(borderRadius: radius, child: image);
|
||||
if (borderRadius != 0)
|
||||
image = ClipRRect(borderRadius: radius, child: image);
|
||||
//模糊会溢出边界,外面再裁一层
|
||||
if (blur) {
|
||||
image = ClipRRect(
|
||||
borderRadius: radius,
|
||||
child: ImageFiltered(imageFilter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), child: image),
|
||||
child: ImageFiltered(
|
||||
imageFilter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
|
||||
child: image),
|
||||
);
|
||||
}
|
||||
return image;
|
||||
@@ -72,7 +75,9 @@ class NetworkImageLoader extends StatelessWidget {
|
||||
final dpr = screen.devicePixelRatio;
|
||||
if (!isResizeImage) return (screen.screenWidth * dpr).toInt();
|
||||
//约束无限时用屏幕宽兜底,避免退化成按原图解码(图片过载)
|
||||
final w = (cons.maxWidth == double.infinity || cons.maxWidth.isNaN) ? screen.screenWidth : cons.maxWidth;
|
||||
final w = (cons.maxWidth == double.infinity || cons.maxWidth.isNaN)
|
||||
? screen.screenWidth
|
||||
: cons.maxWidth;
|
||||
return (w * dpr).toInt();
|
||||
}
|
||||
|
||||
@@ -82,7 +87,8 @@ class NetworkImageLoader extends StatelessWidget {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2),
|
||||
decoration: const BoxDecoration(color: Color(0xff151E2D)),
|
||||
alignment: Alignment.center,
|
||||
child: Image.asset('place_holder_logo.webp'.commonImgPath, width: 100, height: 35),
|
||||
child: Image.asset('place_holder_logo.webp'.commonImgPath,
|
||||
width: 100, height: 35),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,15 +8,14 @@ import 'dart:math';
|
||||
import 'package:collection/collection.dart' show IterableExtension;
|
||||
import 'package:flutter/scheduler.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:hgmj/tools_base/widget/scroll_positioned_list/src/item_positions_listener.dart';
|
||||
import 'package:hgmj/tools_base/widget/scroll_positioned_list/src/item_positions_notifier.dart';
|
||||
import 'package:hgmj/tools_base/widget/scroll_positioned_list/src/scroll_offset_listener.dart';
|
||||
import 'package:wydj/tools_base/widget/scroll_positioned_list/src/item_positions_listener.dart';
|
||||
import 'package:wydj/tools_base/widget/scroll_positioned_list/src/item_positions_notifier.dart';
|
||||
import 'package:wydj/tools_base/widget/scroll_positioned_list/src/scroll_offset_listener.dart';
|
||||
|
||||
import 'positioned_list.dart';
|
||||
import 'post_mount_callback.dart';
|
||||
import 'scroll_offset_notifier.dart';
|
||||
|
||||
|
||||
/// Number of screens to scroll when scrolling a long distance.
|
||||
const int _screenScrollCount = 2;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user