This commit is contained in:
xuhang-x 2024-07-22 10:45:47 +08:00
parent 992f46050b
commit 6668a35f02
9 changed files with 295 additions and 37 deletions

View File

@ -38,7 +38,7 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.ai.wallpaper.genie"
applicationId = "com.live.fantasy.wallpaper"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdk = flutter.minSdkVersion

View File

@ -17,7 +17,7 @@
<application
android:name="${applicationName}"
android:icon="@mipmap/launcher_icon"
android:label="Wallpaper Genie"
android:label="Fantasy Wallpaper"
android:requestLegacyExternalStorage="true"
android:enableOnBackInvokedCallback="true"
tools:targetApi="tiramisu">

View File

@ -488,18 +488,21 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 34W9G5KLNH;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 8B4CW938L2;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.ai.wallpaper.genie;
PRODUCT_BUNDLE_IDENTIFIER = com.live.fantasy.wallpaper;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Fantasy_Wallpaper_Release;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
@ -679,18 +682,21 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 34W9G5KLNH;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 8B4CW938L2;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.ai.wallpaper.genie;
PRODUCT_BUNDLE_IDENTIFIER = com.live.fantasy.wallpaper;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Fantasy_Wallpaper_Release;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
@ -710,18 +716,21 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 34W9G5KLNH;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 8B4CW938L2;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.ai.wallpaper.genie;
PRODUCT_BUNDLE_IDENTIFIER = com.live.fantasy.wallpaper;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = Fantasy_Wallpaper_Release;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;

View File

@ -7,7 +7,7 @@
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Wallpaper Genie</string>
<string>Fantasy Wallpaper</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
@ -15,7 +15,7 @@
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>wallpaper_genie</string>
<string>fantasy_wallpaper</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>

View File

@ -0,0 +1,106 @@
library stacked_animated_list;
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:stacked_animated_list/models/stacked_item.dart';
import 'package:stacked_animated_list/utils/animated_stack_list_mixin.dart';
import 'package:wallpaperx/common/components/custom_transformed_list_item_widget.dart';
class StackedListWidget extends StatefulWidget {
final List<Widget> listItems;
final double listItemWidth;
final Duration animationDuration;
final BorderRadiusGeometry? borderRadius;
final double rotationAngle;
final double additionalTranslateOffsetBeyondScreen;
final List<BoxShadow>? focusedItemShadow;
final ValueChanged<int>? onIndexChanged;
const StackedListWidget({
required this.listItems,
required this.listItemWidth,
this.animationDuration = const Duration(milliseconds: 350),
this.borderRadius = const BorderRadius.all(Radius.circular(16)),
this.rotationAngle = 15,
this.additionalTranslateOffsetBeyondScreen = 0,
this.focusedItemShadow,
this.onIndexChanged,
super.key,
});
@override
State<StackedListWidget> createState() => _StackedListWidgetState();
}
class _StackedListWidgetState extends State<StackedListWidget>
with SingleTickerProviderStateMixin, AnimatedStackListMixin {
final List<StackedItem> _stackWidgets = [];
AnimationController? _animationCtr;
Animation? _increaseAnim;
@override
void initState() {
_animationCtr = AnimationController(
vsync: this,
duration: widget.animationDuration,
);
_increaseAnim = Tween<double>(
begin: 0,
end: 1,
).animate(CurvedAnimation(parent: _animationCtr!, curve: Curves.easeOut));
_stackWidgets.clear();
_stackWidgets.addAll(generateStackedItems(widget.listItems));
_animationCtr?.forward(from: 0);
super.initState();
}
@override
void dispose() {
_animationCtr?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Stack(
children: _stackWidgets
.mapIndexed(
(index, item) {
final isFirstItem = index == 0;
return Center(
child: TransformedListItemWidget(
stackedItem: item,
animation: _increaseAnim!,
widgetWidth: widget.listItemWidth,
focusedWidget: isFirstItem,
borderRadius: widget.borderRadius,
rotationAngle: widget.rotationAngle,
additionalTranslateOffsetBeyondScreen:
widget.additionalTranslateOffsetBeyondScreen,
focusedItemShadow: widget.focusedItemShadow,
onDragEnded: () {
final refreshList = refreshedStackedItems(_stackWidgets);
_stackWidgets.clear();
_stackWidgets.addAll(refreshList);
_animationCtr?.forward(from: 0);
setState(() {
final String keyValue =
_stackWidgets[0].widget.key is ValueKey<String>
? (_stackWidgets[0].widget.key as ValueKey<String>).value
: '0';
widget.onIndexChanged?.call(int.parse(keyValue));
});
},
),
);
},
)
.toList()
.reversed
.toList(),
);
}
}

View File

@ -0,0 +1,93 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:stacked_animated_list/models/stacked_item.dart';
import 'package:stacked_animated_list/ui/focused_transformed_item_widget.dart';
import 'package:stacked_animated_list/ui/unfocused_transformed_item_widget.dart';
import 'package:stacked_animated_list/utils/animated_stack_list_mixin.dart';
import 'package:wallpaperx/common/utils/log_print.dart';
import 'package:wallpaperx/page/discover/discover_controller.dart';
class TransformedListItemWidget extends StatelessWidget
with AnimatedStackListMixin {
final StackedItem stackedItem;
final double widgetWidth;
final bool focusedWidget;
final Function() onDragEnded;
final Animation animation;
final BorderRadiusGeometry? borderRadius;
final double rotationAngle;
final double additionalTranslateOffsetBeyondScreen;
final List<BoxShadow>? focusedItemShadow;
const TransformedListItemWidget({
super.key,
required this.stackedItem,
required this.widgetWidth,
required this.focusedWidget,
required this.onDragEnded,
required this.animation,
this.borderRadius = const BorderRadius.all(Radius.circular(16)),
this.rotationAngle = 15,
this.additionalTranslateOffsetBeyondScreen = 0,
this.focusedItemShadow,
});
@override
Widget build(BuildContext context) {
final horizontalOffset = getListItemHorizontalOffset(
context,
widgetWidth,
additionalTranslateOffsetBeyondScreen,
);
if (focusedWidget) {
final childWidget = Container(
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
boxShadow: focusedItemShadow ?? defaultFocusedItemShadow(),
borderRadius: borderRadius,
),
child: stackedItem.widget,
);
final animatedFromPosType = stackedItem.positionTypeForNextItem.reverse;
return AnimatedBuilder(
animation: animation,
child: LongPressDraggable(
feedback: childWidget,
childWhenDragging: const SizedBox.shrink(),
delay: const Duration(milliseconds: 10),
child: childWidget,
onDragEnd: (details) {
if (isItemFlicked(details)) {
onDragEnded();
} else {
if (Get.isRegistered<DiscoverController>()) {
DiscoverController.to.onTapSwiperItem();
}
}
},
),
builder: (_, child) {
return FocusedTransformedItemWidget(
animation: animation,
rotationAngle: rotationAngle,
horizontalOffset: horizontalOffset,
positionType: animatedFromPosType,
child: child!,
);
},
);
}
return UnfocusedTransformedItemWidget(
stackedItem: stackedItem,
animation: animation,
rotationAngle: rotationAngle,
horizontalOffset: horizontalOffset,
borderRadius: borderRadius,
positionType: stackedItem.positionType,
);
}
}

View File

@ -9,12 +9,14 @@ import 'package:get/get_rx/get_rx.dart';
import 'package:wallpaperx/common/components/view_state_widget.dart';
import 'package:wallpaperx/common/http/http_util.dart';
import 'package:wallpaperx/common/http/url.dart';
import 'package:wallpaperx/common/utils/log_print.dart';
import 'package:wallpaperx/common/utils/shared_util.dart';
import 'package:wallpaperx/entity/image_model.dart';
import 'package:wallpaperx/page/home/home_controller.dart';
import 'package:wallpaperx/routes/app_pages.dart';
class DiscoverController extends GetxController {
static DiscoverController get to => Get.find<DiscoverController>();
late final EasyRefreshController refreshController;
late ScrollController scrollController;
@ -66,7 +68,7 @@ class DiscoverController extends GetxController {
if (res["images"] != null) {
List list = List.from(res["images"]);
images.addAll(list.map((e) => ImageModel.fromJson(e)).toList());
list = (list..shuffle()).take(10).toList();
list = (list..shuffle()).take(5).toList();
banners.addAll(list.map((e) => ImageModel.fromJson(e)).toList());
viewState = ViewState.normal.obs;
update(["discover_background"]);
@ -75,7 +77,7 @@ class DiscoverController extends GetxController {
}
_stopTimer();
}
},errorCallback: (e) {
}, errorCallback: (e) {
_timer ??= Timer.periodic(const Duration(seconds: 2), (Timer t) {
getImages();
});
@ -99,9 +101,9 @@ class DiscoverController extends GetxController {
}
///
void onTapSwiperItem(int index) {
void onTapSwiperItem() {
Get.toNamed(AppPages.wallpaperDet, arguments: {
'position': index,
'position': index.value,
'wallpaperList': banners,
});
}

View File

@ -7,10 +7,12 @@ import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:flutter_swiper_view/flutter_swiper_view.dart';
import 'package:get/get.dart';
import 'package:photo_view/photo_view.dart';
import 'package:wallpaperx/common/components/custom_stacked_list_widget.dart';
import 'package:wallpaperx/common/components/image_network_widget.dart';
import 'package:wallpaperx/common/components/navigation_bar/search_appbar.dart';
import 'package:wallpaperx/common/components/refresh/base_easyrefresh.dart';
import 'package:wallpaperx/common/components/view_state_widget.dart';
import 'package:wallpaperx/common/utils/log_print.dart';
import 'package:wallpaperx/entity/image_model.dart';
import 'package:wallpaperx/generated/assets.dart';
import 'package:wallpaperx/page/discover/discover_controller.dart';
@ -86,27 +88,72 @@ class DiscoverView extends GetView<DiscoverController> {
onTapToCategory: controller.homeController.openDrawer,
),
20.verticalSpace,
Obx(() {
return Expanded(
child: Swiper(
loop: true,
autoplay: true,
scale: .9,
viewportFraction: .85,
itemCount: controller.banners.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () => controller.onTapSwiperItem(index),
child: ImageNetworkWidget(
url: controller.banners[index].imageUrl,
radius: 30.r,
// Obx(() {
// return Expanded(
// child: Swiper(
// loop: true,
// autoplay: true,
// scale: .9,
// viewportFraction: .85,
// itemCount: controller.banners.length,
// itemBuilder: (context, index) {
// return GestureDetector(
// onTap: () => controller.onTapSwiperItem(index),
// child: ImageNetworkWidget(
// url: controller.banners[index].imageUrl,
// radius: 30.r,
// ),
// );
// },
// onIndexChanged: controller.onIndexChanged,
// ),
// );
// }),
Obx(
() => controller.banners.isEmpty
? Container()
: GestureDetector(
onTap: () => LogPrint.d('onTapSwiperItem'),
child: StackedListWidget(
listItems: controller.banners
.asMap()
.entries
.map(
(e) => Container(
key: Key(e.key.toString()),
child: ImageNetworkWidget(
url: controller.banners[e.key].imageUrl,
radius: 30.r,
width: 300.w,
height: 500.w,
fit: BoxFit.fitHeight,
),
),
)
.toList(),
listItemWidth: 200.w,
animationDuration: const Duration(milliseconds: 350),
borderRadius: BorderRadius.circular(30.r),
rotationAngle: 4,
additionalTranslateOffsetBeyondScreen: -93,
onIndexChanged: controller.onIndexChanged,
focusedItemShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.26),
blurRadius: 28,
spreadRadius: 8,
offset: const Offset(8, 16),
),
BoxShadow(
color: Colors.black.withOpacity(0.26),
blurRadius: 28,
spreadRadius: 8,
offset: const Offset(-8, 2),
),
],
),
);
},
onIndexChanged: controller.onIndexChanged,
),
);
}),
),
),
20.verticalSpace,
Image.asset(
width: 24.w,

View File

@ -100,6 +100,7 @@ dependencies:
flip_card: ^0.7.0
app_tracking_transparency: ^2.0.5
gradient_borders: ^1.0.1
stacked_animated_list: ^1.0.1
# Firebase
firebase_core: ^2.32.0