修改vip排版
This commit is contained in:
parent
071ab9ffed
commit
0a3ace948a
@ -14,6 +14,7 @@ import 'package:yumi/ui_kit/components/sc_compontent.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_debounce_widget.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_tts.dart';
|
||||
import 'package:yumi/ui_kit/widgets/props/sc_data_card_resource_view.dart';
|
||||
import 'package:yumi/ui_kit/widgets/store/store_bag_page_helpers.dart';
|
||||
|
||||
class VipDetailPage extends StatefulWidget {
|
||||
const VipDetailPage({super.key});
|
||||
@ -470,8 +471,7 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
|
||||
Widget _buildLevelCard() {
|
||||
final assetLevel = _assetLevel;
|
||||
final backgroundCard = _selectedBackgroundCard;
|
||||
final effectImage = _selectedEffectImage ?? _selectedLongBadge;
|
||||
final effectImage = _selectedEffectImage;
|
||||
return Center(
|
||||
child: SizedBox(
|
||||
width: 351.w,
|
||||
@ -482,10 +482,7 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
Positioned.fill(
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8.w),
|
||||
child: _buildVipCardBackground(
|
||||
resource: backgroundCard,
|
||||
assetLevel: assetLevel,
|
||||
),
|
||||
child: _buildVipCardBackground(assetLevel: assetLevel),
|
||||
),
|
||||
),
|
||||
Positioned.fill(
|
||||
@ -525,41 +522,30 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
),
|
||||
),
|
||||
),
|
||||
PositionedDirectional(
|
||||
end: 24.w,
|
||||
top: -36.w,
|
||||
child: _buildDynamicResourceVisual(
|
||||
resource: effectImage,
|
||||
width: 135.w,
|
||||
height: 135.w,
|
||||
fallbackIcon: Icons.workspace_premium_outlined,
|
||||
if (_hasResourceUrl(effectImage))
|
||||
PositionedDirectional(
|
||||
end: 24.w,
|
||||
top: -36.w,
|
||||
child: _buildDynamicResourceVisual(
|
||||
resource: effectImage,
|
||||
width: 135.w,
|
||||
height: 135.w,
|
||||
fallbackIcon: Icons.workspace_premium_outlined,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildVipCardBackground({
|
||||
required SCVipResourceRes? resource,
|
||||
required int assetLevel,
|
||||
}) {
|
||||
final fallback = Image.asset(
|
||||
Widget _buildVipCardBackground({required int assetLevel}) {
|
||||
return Image.asset(
|
||||
'sc_images/vip/sc_vip_card_bg_$assetLevel.png',
|
||||
fit: BoxFit.fill,
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
);
|
||||
if (!_hasResourceUrl(resource)) {
|
||||
return fallback;
|
||||
}
|
||||
return SCDataCardResourceView(
|
||||
sourceUrl: resource?.sourceResourceUrl,
|
||||
coverUrl: resource?.previewUrl,
|
||||
fit: BoxFit.fill,
|
||||
fallback: fallback,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildLevelDivider() {
|
||||
@ -632,19 +618,27 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
}
|
||||
|
||||
Widget _buildDecorationGrid(List<_VipFeatureData> items) {
|
||||
return Wrap(
|
||||
spacing: 10.w,
|
||||
runSpacing: 10.w,
|
||||
children:
|
||||
items
|
||||
.map(
|
||||
(item) => _buildFeatureTile(
|
||||
item,
|
||||
width: item.wide ? 206.w : 98.w,
|
||||
height: 100.w,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final spacing = 10.w;
|
||||
final maxWidth =
|
||||
constraints.maxWidth.isFinite ? constraints.maxWidth : 314.w;
|
||||
final itemWidth = (maxWidth - spacing * 2) / 3;
|
||||
return Wrap(
|
||||
spacing: spacing,
|
||||
runSpacing: spacing,
|
||||
children:
|
||||
items
|
||||
.map(
|
||||
(item) => _buildFeatureTile(
|
||||
item,
|
||||
width: itemWidth,
|
||||
height: 100.w,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@ -772,6 +766,7 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
resource: _selectedAvatarFrame,
|
||||
fallbackTitle: 'Avatar Frame',
|
||||
fallbackIcon: Icons.person_pin_circle_outlined,
|
||||
previewKind: SCStoreItemPreviewKind.avatarFrame,
|
||||
);
|
||||
_addResourceItem(
|
||||
items,
|
||||
@ -790,14 +785,14 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
resource: _selectedEntryEffect,
|
||||
fallbackTitle: 'Entry Effect',
|
||||
fallbackIcon: Icons.airline_seat_recline_extra,
|
||||
wide: true,
|
||||
);
|
||||
_addResourceItem(
|
||||
items,
|
||||
resource: _selectedBackgroundCard,
|
||||
fallbackTitle: 'Profile Card',
|
||||
fallbackIcon: Icons.badge_outlined,
|
||||
wide: true,
|
||||
previewKind: SCStoreItemPreviewKind.dataCard,
|
||||
previewFit: BoxFit.cover,
|
||||
);
|
||||
return items;
|
||||
}
|
||||
@ -815,6 +810,9 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
required String fallbackTitle,
|
||||
IconData? fallbackIcon,
|
||||
bool wide = false,
|
||||
SCStoreItemPreviewKind previewKind = SCStoreItemPreviewKind.resource,
|
||||
BoxFit previewFit = BoxFit.contain,
|
||||
BoxFit tileFit = BoxFit.contain,
|
||||
}) {
|
||||
if (!_hasResource(resource)) {
|
||||
return;
|
||||
@ -824,8 +822,12 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
_resourceTitle(resource, fallbackTitle),
|
||||
null,
|
||||
icon: fallbackIcon,
|
||||
resourceUrl: resource?.previewUrl,
|
||||
sourceUrl: resource?.sourceResourceUrl,
|
||||
coverUrl: _resourceCoverUrl(resource),
|
||||
wide: wide,
|
||||
previewKind: previewKind,
|
||||
previewFit: previewFit,
|
||||
tileFit: tileFit,
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -846,6 +848,18 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
return fallbackTitle;
|
||||
}
|
||||
|
||||
String? _resourceCoverUrl(SCVipResourceRes? resource) {
|
||||
final coverUrl = resource?.coverUrl?.trim();
|
||||
if (coverUrl != null && coverUrl.isNotEmpty) {
|
||||
return coverUrl;
|
||||
}
|
||||
final cover = resource?.cover?.trim();
|
||||
if (cover != null && cover.isNotEmpty) {
|
||||
return cover;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Widget _buildDynamicResourceVisual({
|
||||
required SCVipResourceRes? resource,
|
||||
required double width,
|
||||
@ -946,7 +960,7 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
}
|
||||
|
||||
Widget _buildFeatureIcon(_VipFeatureData item, {required double size}) {
|
||||
final url = item.resourceUrl?.trim();
|
||||
final url = item.coverUrl?.trim();
|
||||
if (url != null && url.isNotEmpty) {
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(6.w),
|
||||
@ -973,15 +987,15 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
}
|
||||
|
||||
Widget _buildFeatureVisual(_VipFeatureData item, {required bool isWide}) {
|
||||
final url = item.resourceUrl?.trim();
|
||||
if (url != null && url.isNotEmpty) {
|
||||
final coverUrl = item.coverUrl?.trim();
|
||||
if (coverUrl != null && coverUrl.isNotEmpty) {
|
||||
return netImage(
|
||||
url: url,
|
||||
fit: BoxFit.contain,
|
||||
url: coverUrl,
|
||||
fit: item.tileFit,
|
||||
noDefaultImg: true,
|
||||
errorWidget:
|
||||
item.assetPath != null
|
||||
? Image.asset(item.assetPath!, fit: BoxFit.contain)
|
||||
? Image.asset(item.assetPath!, fit: item.tileFit)
|
||||
: isWide
|
||||
? Center(child: _buildWideRewardPlaceholder())
|
||||
: _buildRewardPlaceholder(item.icon ?? Icons.auto_awesome),
|
||||
@ -1062,32 +1076,32 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
required double height,
|
||||
}) {
|
||||
final isWide = item.wide;
|
||||
return Container(
|
||||
width: width,
|
||||
height: height,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(6.w),
|
||||
border: Border.all(color: const Color(0xFFEBCB76), width: 1.w),
|
||||
color: Colors.black.withValues(alpha: 0.38),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 8.w),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(child: _buildFeatureVisual(item, isWide: isWide)),
|
||||
SizedBox(height: 5.w),
|
||||
Text(
|
||||
item.title,
|
||||
maxLines: 2,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
return GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap:
|
||||
item.canPreview
|
||||
? () => showStoreBagFullScreenResourcePreview(
|
||||
context,
|
||||
sourceUrl: item.sourceUrl,
|
||||
coverUrl: item.coverUrl,
|
||||
previewKind: item.previewKind,
|
||||
fit: item.previewFit,
|
||||
)
|
||||
: null,
|
||||
child: Semantics(
|
||||
label: item.title,
|
||||
button: item.canPreview,
|
||||
child: Container(
|
||||
width: width,
|
||||
height: height,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(6.w),
|
||||
border: Border.all(color: const Color(0xFFEBCB76), width: 1.w),
|
||||
color: Colors.black.withValues(alpha: 0.38),
|
||||
),
|
||||
],
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 8.w),
|
||||
child: Center(child: _buildFeatureVisual(item, isWide: isWide)),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -1420,15 +1434,27 @@ class _VipFeatureData {
|
||||
this.title,
|
||||
this.assetPath, {
|
||||
this.icon,
|
||||
this.resourceUrl,
|
||||
this.sourceUrl,
|
||||
this.coverUrl,
|
||||
this.wide = false,
|
||||
this.previewKind = SCStoreItemPreviewKind.resource,
|
||||
this.previewFit = BoxFit.contain,
|
||||
this.tileFit = BoxFit.contain,
|
||||
});
|
||||
|
||||
final String title;
|
||||
final String? assetPath;
|
||||
final IconData? icon;
|
||||
final String? resourceUrl;
|
||||
final String? sourceUrl;
|
||||
final String? coverUrl;
|
||||
final bool wide;
|
||||
final SCStoreItemPreviewKind previewKind;
|
||||
final BoxFit previewFit;
|
||||
final BoxFit tileFit;
|
||||
|
||||
bool get canPreview =>
|
||||
(sourceUrl?.trim().isNotEmpty ?? false) ||
|
||||
(coverUrl?.trim().isNotEmpty ?? false);
|
||||
}
|
||||
|
||||
class _VipActionButtonConfig {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user