diff --git a/android/app/build.gradle b/android/app/build.gradle index d7e3f44..27d975f 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -101,4 +101,7 @@ flutter { source '../..' } -dependencies {} +dependencies { + implementation 'androidx.work:work-runtime-ktx:2.9.0' + implementation 'com.github.bumptech.glide:glide:4.16.0' +} diff --git a/android/app/src/main/kotlin/com/hello/wallpaper/GlideWallpaperWorker.kt b/android/app/src/main/kotlin/com/hello/wallpaper/GlideWallpaperWorker.kt new file mode 100644 index 0000000..9125797 --- /dev/null +++ b/android/app/src/main/kotlin/com/hello/wallpaper/GlideWallpaperWorker.kt @@ -0,0 +1,95 @@ +package com.hello.wallpaper + +import android.app.Activity +import android.app.WallpaperManager +import android.content.Context +import android.graphics.Bitmap +import android.graphics.drawable.Drawable +import android.os.Build +import android.util.Size +import androidx.window.layout.WindowMetricsCalculator +import androidx.work.* +import com.bumptech.glide.Glide +import com.bumptech.glide.request.RequestOptions +import com.bumptech.glide.request.target.CustomTarget +import com.bumptech.glide.request.transition.Transition +import java.io.File +import java.io.IOException + +class GlideWallpaperWorker( + context: Context, + params: WorkerParameters +) : Worker(context, params) { + + override fun doWork(): Result { + val imagePath = inputData.getString("imagePath") ?: return Result.failure() + val wallpaperType = inputData.getInt("wallpaperType", 0) + val desiredWidth = inputData.getInt("desiredWidth", 0) + val desiredHeight = inputData.getInt("desiredHeight", 0) + + return try { + Glide.with(applicationContext) + .asBitmap() + .load(File(imagePath)) + .apply(RequestOptions().override(desiredWidth, desiredHeight)) + .into(object : CustomTarget() { + override fun onResourceReady(resource: Bitmap, transition: Transition?) { + val wallpaperManager = WallpaperManager.getInstance(applicationContext) + try { + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) { + wallpaperManager.setBitmap(resource) + } else { + when (wallpaperType) { + 0 -> wallpaperManager.setBitmap(resource, null, true, WallpaperManager.FLAG_SYSTEM) + 1 -> wallpaperManager.setBitmap(resource, null, true, WallpaperManager.FLAG_LOCK) + 2 -> { + wallpaperManager.setBitmap(resource, null, true, WallpaperManager.FLAG_SYSTEM) + wallpaperManager.setBitmap(resource, null, true, WallpaperManager.FLAG_LOCK) + } + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + + override fun onLoadCleared(placeholder: Drawable?) { + // Handle cleanup if needed + } + }) + Result.success() + } catch (e: Exception) { + e.printStackTrace() + Result.retry() + } + } +} + +// Trigger the WorkManager task +fun setWallpaperWithGlide(context: Context, activity: Activity, imagePath: String, wallpaperType: Int) { + val screenSize: Size = getScreenDimensions(activity) + val desiredWidth = screenSize.width * 2 // 适应横向滚动 + val desiredHeight = screenSize.height + + val inputData = Data.Builder() + .putString("imagePath", imagePath) + .putInt("wallpaperType", wallpaperType) + .putInt("desiredWidth", desiredWidth) + .putInt("desiredHeight", desiredHeight) + .build() + + val setWallpaperRequest = OneTimeWorkRequest.Builder(GlideWallpaperWorker::class.java) + .setInputData(inputData) + .build() + + WorkManager.getInstance(context).enqueue(setWallpaperRequest) +} + +// Modern method to get screen dimensions +private fun getScreenDimensions(activity: Activity): Size { + val windowMetrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(activity) + val bounds = windowMetrics.bounds + val width = bounds.width() + val height = bounds.height() + return Size(width, height) +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/hello/wallpaper/SetWallpaperPlugin.kt b/android/app/src/main/kotlin/com/hello/wallpaper/SetWallpaperPlugin.kt index e4fee8c..135ad47 100644 --- a/android/app/src/main/kotlin/com/hello/wallpaper/SetWallpaperPlugin.kt +++ b/android/app/src/main/kotlin/com/hello/wallpaper/SetWallpaperPlugin.kt @@ -1,22 +1,27 @@ package com.hello.wallpaper +import android.app.Activity import android.app.WallpaperManager import android.content.Context +import android.graphics.Bitmap import android.graphics.BitmapFactory import android.os.Build -import androidx.annotation.RequiresApi +import android.util.Size +import androidx.window.layout.WindowMetricsCalculator import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.embedding.engine.plugins.activity.ActivityAware +import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel import kotlinx.coroutines.DelicateCoroutinesApi -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -class SetWallpaperPlugin : FlutterPlugin, MethodChannel.MethodCallHandler { +class SetWallpaperPlugin : FlutterPlugin, ActivityAware, MethodChannel.MethodCallHandler { private lateinit var context: Context private lateinit var channel: MethodChannel + private lateinit var activity: Activity override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { channel = MethodChannel(flutterPluginBinding.binaryMessenger, "set_wallpaper") @@ -24,31 +29,13 @@ class SetWallpaperPlugin : FlutterPlugin, MethodChannel.MethodCallHandler { channel.setMethodCallHandler(this) } - @RequiresApi(Build.VERSION_CODES.N) - @OptIn(DelicateCoroutinesApi::class) override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { if (call.method == "setWallpaper") { val path = call.argument("path") val wallpaperType = call.argument("wallpaperType") // 0 for home screen, 1 for lock screen, 2 for both - GlobalScope.launch(Dispatchers.IO) { - val bitmap = BitmapFactory.decodeFile(path) - withContext(Dispatchers.Main) { - try { - val wallpaperManager = WallpaperManager.getInstance(context) - when (wallpaperType) { - 0 -> wallpaperManager.setBitmap(bitmap, null, true, WallpaperManager.FLAG_SYSTEM) - 1 -> wallpaperManager.setBitmap(bitmap, null, true, WallpaperManager.FLAG_LOCK) - 2 -> { - wallpaperManager.setBitmap(bitmap, null, true, WallpaperManager.FLAG_SYSTEM) - wallpaperManager.setBitmap(bitmap, null, true, WallpaperManager.FLAG_LOCK) - } - } - result.success("Wallpaper applied successfully") - } catch (e: Exception) { - result.error("ERROR", "Failed to set wallpaper: ${e.message}", null) - } - } + if (path != null && wallpaperType != null) { + setWallpaper(path, wallpaperType, result) } } else { result.notImplemented() @@ -58,4 +45,59 @@ class SetWallpaperPlugin : FlutterPlugin, MethodChannel.MethodCallHandler { override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { channel.setMethodCallHandler(null) } + + override fun onAttachedToActivity(binding: ActivityPluginBinding) { + activity = binding.activity + } + + override fun onDetachedFromActivityForConfigChanges() { + } + + override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) { + activity = binding.activity + } + + override fun onDetachedFromActivity() { + } + + @OptIn(DelicateCoroutinesApi::class) + fun setWallpaper(path: String, wallpaperType: Int, result: MethodChannel.Result) { + val screenSize: Size = getScreenDimensions() + val desiredWidth = screenSize.width * 2 // 适应横向滚动 + val desiredHeight = screenSize.height + + GlobalScope.launch(Dispatchers.IO) { + val wallpaperManager = WallpaperManager.getInstance(context) + try { + val largeBitmap = BitmapFactory.decodeFile(path) + val scaledBitmap = Bitmap.createScaledBitmap(largeBitmap, desiredWidth, desiredHeight, true) + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) { + wallpaperManager.setBitmap(scaledBitmap) + } else { + when (wallpaperType) { + 0 -> wallpaperManager.setBitmap(largeBitmap, null, true, WallpaperManager.FLAG_SYSTEM) + 1 -> wallpaperManager.setBitmap(largeBitmap, null, true, WallpaperManager.FLAG_LOCK) + 2 -> { + wallpaperManager.setBitmap(largeBitmap, null, true, WallpaperManager.FLAG_SYSTEM) + wallpaperManager.setBitmap(largeBitmap, null, true, WallpaperManager.FLAG_LOCK) + } + } + } + largeBitmap.recycle() + scaledBitmap.recycle() + result.success("Wallpaper applied successfully") + } catch (e: Exception) { + result.error("ERROR", "Failed to set wallpaper: ${e.message}", null) + } + } + } + + // Modern method to get screen dimensions + private fun getScreenDimensions(): Size { + val windowMetrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(activity) + val bounds = windowMetrics.bounds + val width = bounds.width() + val height = bounds.height() + return Size(width, height) + } } \ No newline at end of file diff --git a/lib/common/components/navigation_bar/title_bar_widget.dart b/lib/common/components/navigation_bar/title_bar_widget.dart index 143860f..8e3ce43 100644 --- a/lib/common/components/navigation_bar/title_bar_widget.dart +++ b/lib/common/components/navigation_bar/title_bar_widget.dart @@ -21,41 +21,44 @@ class TitleBarWidget extends StatelessWidget { @override Widget build(BuildContext context) { - return SizedBox( - height: titleBarHeight, - child: Row( - children: [ - SizedBox(width: 20.w), - Expanded( - child: Text( - title, - style: TextStyle( - color: Colors.white, - fontSize: 32.sp, - fontWeight: FontWeight.w600, + return Padding( + padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top), + child: SizedBox( + height: titleBarHeight, + child: Row( + children: [ + SizedBox(width: 20.w), + Expanded( + child: Text( + title, + style: TextStyle( + color: Colors.white, + fontSize: 32.sp, + fontWeight: FontWeight.w600, + ), ), ), - ), - if (showSettingsBtn!) ...[ - ClipOval( - child: Material( - color: Colors.transparent, - child: InkWell( - onTap: settingsOnTap, - child: Padding( - padding: const EdgeInsets.all(10).w, - child: Image.asset( - Assets.imagesIcSettings, - width: 20.w, - height: 20.w, + if (showSettingsBtn!) ...[ + ClipOval( + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: settingsOnTap, + child: Padding( + padding: const EdgeInsets.all(10).w, + child: Image.asset( + Assets.imagesIcSettings, + width: 20.w, + height: 20.w, + ), ), ), ), ), - ), - SizedBox(width: 10.w), + SizedBox(width: 10.w), + ], ], - ], + ), ), ); } diff --git a/lib/modules/catalog/catalog_controller.dart b/lib/modules/catalog/catalog_controller.dart index 1549efc..2fca9f5 100644 --- a/lib/modules/catalog/catalog_controller.dart +++ b/lib/modules/catalog/catalog_controller.dart @@ -51,7 +51,6 @@ class CatalogController extends GetxController { Get.toNamed(AppPages.wallpaperDet, arguments: { 'position': index, 'wallpaperList': wallpaperList, - 'heroTag': 'Catalog-$clsName-$index', }); } } diff --git a/lib/modules/catalog/catalog_view.dart b/lib/modules/catalog/catalog_view.dart index a631b75..cc04c0a 100644 --- a/lib/modules/catalog/catalog_view.dart +++ b/lib/modules/catalog/catalog_view.dart @@ -107,15 +107,12 @@ class CatalogView extends GetView { Widget _buildWallpaperItem(String clsName, List wallpaperList, WallpaperData item, int index) { return GestureDetector( onTap: () => controller.onTapItem(clsName, wallpaperList, index), - child: Hero( - tag: 'Catalog-$clsName-$index', - child: KeepAliveWrapper( - child: ImageNetworkWidget( - url: item.previewThumb, - width: 136.w, - height: double.infinity, - radius: 8.r, - ), + child: KeepAliveWrapper( + child: ImageNetworkWidget( + url: item.previewThumb, + width: 136.w, + height: double.infinity, + radius: 8.r, ), ), ); diff --git a/lib/modules/cls_det/cls_det_controller.dart b/lib/modules/cls_det/cls_det_controller.dart index f1400cc..df96a5a 100644 --- a/lib/modules/cls_det/cls_det_controller.dart +++ b/lib/modules/cls_det/cls_det_controller.dart @@ -19,7 +19,6 @@ class ClsDetController extends GetxController { Get.toNamed(AppPages.wallpaperDet, arguments: { 'position': index, 'wallpaperList': wallpaperDataList, - 'heroTag': 'ClsDet-$index', }); } } diff --git a/lib/modules/cls_det/cls_det_view.dart b/lib/modules/cls_det/cls_det_view.dart index 1b39058..7cbdfbe 100644 --- a/lib/modules/cls_det/cls_det_view.dart +++ b/lib/modules/cls_det/cls_det_view.dart @@ -35,12 +35,9 @@ class ClsDetView extends StatelessWidget { Widget _buildDiscoverItem(WallpaperData item, int index) { return GestureDetector( onTap: () => controller.onTapItem(index), - child: Hero( - tag: 'ClsDet-$index', - child: ImageNetworkWidget( - url: item.previewThumb, - radius: 8.r, - ), + child: ImageNetworkWidget( + url: item.previewThumb, + radius: 8.r, ), ); } diff --git a/lib/modules/discover/discover_controller.dart b/lib/modules/discover/discover_controller.dart index 7c2e223..0d32baa 100644 --- a/lib/modules/discover/discover_controller.dart +++ b/lib/modules/discover/discover_controller.dart @@ -80,7 +80,6 @@ class DiscoverController extends GetxController { Get.toNamed(AppPages.wallpaperDet, arguments: { 'position': index, 'wallpaperList': wallpaperDataList, - 'heroTag': 'Discover-$index', }); } } diff --git a/lib/modules/discover/discover_view.dart b/lib/modules/discover/discover_view.dart index 95f6946..d705011 100644 --- a/lib/modules/discover/discover_view.dart +++ b/lib/modules/discover/discover_view.dart @@ -18,7 +18,6 @@ class DiscoverView extends GetView { builder: (controller) { return Column( children: [ - SizedBox(height: 7.h), if (controller.todayNewestList.isNotEmpty) ...[ _buildTodayNewest(), SizedBox(height: 7.h), @@ -56,12 +55,9 @@ class DiscoverView extends GetView { Widget _buildDiscoverItem(WallpaperData item, int index) { return GestureDetector( onTap: () => controller.onTapItem(index), - child: Hero( - tag: 'Discover-$index', - child: ImageNetworkWidget( - url: item.previewThumb, - radius: 8.r, - ), + child: ImageNetworkWidget( + url: item.previewThumb, + radius: 8.r, ), ); } diff --git a/lib/modules/favorite/favorite_controller.dart b/lib/modules/favorite/favorite_controller.dart index 339f434..1e9b0de 100644 --- a/lib/modules/favorite/favorite_controller.dart +++ b/lib/modules/favorite/favorite_controller.dart @@ -54,7 +54,6 @@ class FavoriteController extends GetxController { Get.toNamed(AppPages.wallpaperDet, arguments: { 'position': index, 'wallpaperList': isFavorite ? favoriteList : todayHottestList, - 'heroTag': '${isFavorite ? 'Favorite' : 'TodayHottest'}-$index', }); } diff --git a/lib/modules/favorite/favorite_view.dart b/lib/modules/favorite/favorite_view.dart index 105f0fa..1d4ef88 100644 --- a/lib/modules/favorite/favorite_view.dart +++ b/lib/modules/favorite/favorite_view.dart @@ -55,12 +55,9 @@ class FavoriteView extends GetView { return GestureDetector( onTap: () => controller.onTapItem(index, true), onLongPress: () => controller.onLongPress(index), - child: Hero( - tag: 'Favorite-$index', - child: ImageNetworkWidget( - url: item.previewThumb, - radius: 8.r, - ), + child: ImageNetworkWidget( + url: item.previewThumb, + radius: 8.r, ), ); } @@ -87,13 +84,10 @@ class FavoriteView extends GetView { padding: const EdgeInsets.symmetric(horizontal: 3.5).w, child: GestureDetector( onTap: () => controller.onTapItem(e.key, false), - child: Hero( - tag: 'TodayHottest-${e.key}', - child: ImageNetworkWidget( - url: e.value.previewThumb, - height: 183.h, - radius: 8.r, - ), + child: ImageNetworkWidget( + url: e.value.previewThumb, + height: 183.h, + radius: 8.r, ), ), ), diff --git a/lib/modules/home/home_view.dart b/lib/modules/home/home_view.dart index 5c42392..387ebb9 100644 --- a/lib/modules/home/home_view.dart +++ b/lib/modules/home/home_view.dart @@ -15,13 +15,13 @@ class HomeView extends StatelessWidget { return Scaffold( body: Column( children: [ - SizedBox(height: ScreenUtil().statusBarHeight), Obx(() { return TitleBarWidget( controller.pages[controller.currentIndex.value].label, settingsOnTap: controller.onTapSettings, ); }), + SizedBox(height: 7.h), Expanded( child: PageView( physics: const NeverScrollableScrollPhysics(), diff --git a/lib/modules/wallpaper_det/wallpaper_det_controller.dart b/lib/modules/wallpaper_det/wallpaper_det_controller.dart index f6f6f28..39dc733 100644 --- a/lib/modules/wallpaper_det/wallpaper_det_controller.dart +++ b/lib/modules/wallpaper_det/wallpaper_det_controller.dart @@ -23,7 +23,6 @@ class WallpaperDetController extends GetxController { late final List globalKey; late final List wallpaperList; late final PageController pageController; - late final String heroTag; var blurs = [].obs; var position = 0; var filePath = ''; @@ -34,7 +33,6 @@ class WallpaperDetController extends GetxController { Map arguments = Get.arguments ?? {}; position = arguments['position'] ?? 0; wallpaperList = arguments['wallpaperList'] ?? []; - heroTag = arguments['heroTag'] ?? ''; globalKey = List.generate(wallpaperList.length, (index) => GlobalKey()); blurs.value = List.generate(wallpaperList.length, (index) => false); pageController = PageController(initialPage: position); diff --git a/lib/modules/wallpaper_det/wallpaper_det_view.dart b/lib/modules/wallpaper_det/wallpaper_det_view.dart index d14b25f..a7e610b 100644 --- a/lib/modules/wallpaper_det/wallpaper_det_view.dart +++ b/lib/modules/wallpaper_det/wallpaper_det_view.dart @@ -87,7 +87,6 @@ class WallpaperDetView extends StatelessWidget { maxScale: PhotoViewComputedScale.covered * 3, loadingBuilder: (context, event) => loadingView(), errorBuilder: (BuildContext context, Object error, StackTrace? stackTrace) => errorView, - heroAttributes: PhotoViewHeroAttributes(tag: controller.heroTag), ), ); }), diff --git a/lib/res/themes/app_sizes.dart b/lib/res/themes/app_sizes.dart index 6fcfa39..b643168 100644 --- a/lib/res/themes/app_sizes.dart +++ b/lib/res/themes/app_sizes.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; /// 标题栏高度 double titleBarHeight = 45.h; @@ -13,9 +14,9 @@ double todayNewestHeight = 64.h; /// discover列表高度 double discoverListHeight = 1.sh - - ScreenUtil().statusBarHeight - + MediaQuery.of(Get.context!).padding.top - titleBarHeight - todayNewestHeight - - 7.h - + 14.h - kBottomNavigationBarHeight - - ScreenUtil().bottomBarHeight; + MediaQuery.of(Get.context!).padding.bottom; diff --git a/pubspec.yaml b/pubspec.yaml index 1f07c2e..b6730cb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.1+2 +version: 1.0.2+3 environment: sdk: '>=3.3.4 <4.0.0'