Flutter动态应用图标插件dynamic_app_icon_flutter的使用

发布于 1周前 作者 caililin 来自 Flutter

Flutter动态应用图标插件dynamic_app_icon_flutter的使用

dynamic_app_icon_flutter 是一个用于在移动平台上动态更改应用程序图标的Flutter插件。它支持iOS和Android(iOS版本需大于10.3)。

注意事项

由于最新版Android系统的启动画面问题,请考虑删除您的activityactivity-alias标签中的以下代码:

<meta-data
    android:name="io.flutter.embedding.android.SplashScreenDrawable"
    android:resource="@drawable/launch_background" />

同时,在MainActivity.ktonCreate函数中添加以下代码:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    splashScreen.setOnExitAnimationListener { splashScreenView -> splashScreenView.remove() }
}

Android集成

步骤

  1. pubspec.yaml文件的依赖部分添加插件的最新版本。
  2. 运行flutter pub get
  3. 更新android/src/main/AndroidManifest.xml如下所示:
<application ...>
    <activity
        android:name=".MainActivity"
        android:launchMode="singleTop"
        android:theme="@style/LaunchTheme"
        android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
        android:hardwareAccelerated="true"
        android:windowSoftInputMode="adjustResize"
        android:enabled="true">
        
        <meta-data
            android:name="io.flutter.embedding.android.NormalTheme"
            android:resource="@style/NormalTheme" />

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <!-- 示例:icon_1 作为替代图标 -->
    <activity-alias
        android:label="Your app"
        android:icon="@mipmap/ic_launcher_1"
        android:name=".icon_1"
        android:enabled="false"
        android:targetActivity=".MainActivity">

        <meta-data
            android:name="io.flutter.embedding.android.NormalTheme"
            android:resource="@style/NormalTheme" />

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>

    </activity-alias>
</application>
  1. 您可以在应用程序中拥有多个应用图标,并且可以像下面这样使用:
    • 方法中传递的名称必须在AndroidManifest.xml中声明。
    • 声明一个包含可用应用图标的字符串列表。
    • 不要忘记在列表中添加default

Android代码集成示例

const List<String> list = ["icon_1", "default"];
DynamicAppIcon.setupAppIcon(iconName: 'icon_1', iconList: list);

iOS集成

图标尺寸

  • 2x - 120px x 120px
  • 3x - 180px x 180px

步骤

  1. 准备一些图标文件,例如:

    • teamfortress@2x.png, teamfortress@3x.png
    • photos@2x.png, photos@3x.png
    • chills@2x.png, chills@3x.png

    这些图标不应放在Assets.xcassets文件夹中,而应放在外面。

  2. 配置Info.plist

    • 添加Icon files (iOS 5)到信息属性列表。
    • 添加CFBundleAlternateIcons作为字典,用于替代图标。
    • CFBundleAlternateIcons下设置三个字典,分别对应teamfortressphotoschills
    • 对于每个字典,配置两个属性——UIPrerenderedIconCFBundleIconFiles

如果需要iPad支持,您还需要在CFBundleIcons~ipad中添加这些图标声明。

iOS代码集成示例

import 'package:dynamic_app_icon/dynamic_app_icon.dart';

try {
  if (await DynamicAppIcon.supportsAlternateIcons) {
    await DynamicAppIcon.setAlternateIconName("photos");
    print("App icon change successful");
    return;
  }
} on PlatformException catch (e) {
  if (await DynamicAppIcon.supportsAlternateIcons) {
    await DynamicAppIcon.setAlternateIconName(null);
    print("Change app icon back to default");
    return;
  } else {
    print("Failed to change app icon");
  }
}

完整示例Demo

// ignore_for_file: deprecated_member_use

import 'package:dynamic_app_icon_flutter/dynamic_app_icon.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int batchIconNumber = 0;
  String currentIconName = "?";
  bool loading = false;
  TextEditingController controller = TextEditingController();

  @override
  void initState() {
    super.initState();
    DynamicAppIcon.getAlternateIconName().then((v) {
      setState(() {
        currentIconName = v ?? "`primary`";
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    GlobalKey<ScaffoldMessengerState> _scaffoldKey = GlobalKey();

    return MaterialApp(
      home: Scaffold(
        key: _scaffoldKey,
        appBar: AppBar(
          title: const Text('Dynamic App Icon'),
        ),
        body: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 28),
          child: ListView(
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text(
                  "Current Icon Name: $currentIconName",
                  textAlign: TextAlign.center,
                  style: Theme.of(context).textTheme.headline4,
                ),
              ),
              OutlinedButton.icon(
                icon: const Icon(Icons.ac_unit),
                label: const Text("Team Fortress"),
                onPressed: () async {
                  try {
                    if (await DynamicAppIcon.supportsAlternateIcons) {
                      await DynamicAppIcon.setAlternateIconName("teamfortress");
                      _scaffoldKey.currentState?.hideCurrentSnackBar();
                      _scaffoldKey.currentState?.showSnackBar(const SnackBar(
                        content: Text("App icon change successful"),
                      ));
                      DynamicAppIcon.getAlternateIconName().then((v) {
                        setState(() {
                          currentIconName = v ?? "`primary`";
                        });
                      });
                      return;
                    }
                  } on PlatformException {
                    _scaffoldKey.currentState?.hideCurrentSnackBar();
                    _scaffoldKey.currentState?.showSnackBar(const SnackBar(
                      content: Text("Failed to change app icon"),
                    ));
                  }
                },
              ),
              // 其他按钮类似...
            ],
          ),
        ),
      ),
    );
  }
}

通过上述步骤和示例代码,您可以轻松地在Flutter项目中实现动态应用图标功能。


更多关于Flutter动态应用图标插件dynamic_app_icon_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter动态应用图标插件dynamic_app_icon_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter应用中使用dynamic_app_icon_flutter插件来动态更改应用图标的示例代码。这个插件允许你根据应用的状态或用户偏好来更改应用的图标。

首先,确保你已经在pubspec.yaml文件中添加了dynamic_app_icon_flutter依赖:

dependencies:
  flutter:
    sdk: flutter
  dynamic_app_icon_flutter: ^最新版本号  # 请替换为最新版本号

然后,运行flutter pub get来安装依赖。

接下来,在你的Flutter应用中,你可以按照以下步骤来使用这个插件:

  1. 导入插件

在你的Dart文件中导入插件:

import 'package:dynamic_app_icon_flutter/dynamic_app_icon_flutter.dart';
  1. 请求权限

在Android上,更改应用图标需要动态权限。你可以在MainActivity.kt(对于Kotlin)或MainActivity.java(对于Java)中添加代码来处理权限请求。不过,dynamic_app_icon_flutter插件通常已经处理了大部分权限相关的逻辑,你可能只需要确保在需要时请求权限。

  1. 设置备选图标

在你的android/app/src/main/res/mipmap-*目录下添加你的备选图标。例如,你可以添加ic_launcher_alt.png作为备选图标。

  1. 使用插件更改图标

在你的Flutter代码中,你可以使用以下代码来更改应用图标:

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    // 初始时设置为备选图标
    _changeAppIconToAlternative();
    
    // 模拟一段时间后切换回默认图标
    Future.delayed(Duration(seconds: 10), () {
      _changeAppIconToDefault();
    });
  }

  void _changeAppIconToAlternative() async {
    try {
      bool isSupported = await DynamicAppIcon.isSupported();
      if (isSupported) {
        await DynamicAppIcon.setAlternateIconName('ic_launcher_alt');
        print('App icon changed to alternative.');
      } else {
        print('Changing app icon is not supported on this device.');
      }
    } catch (e) {
      print('Error changing app icon: $e');
    }
  }

  void _changeAppIconToDefault() async {
    try {
      await DynamicAppIcon.resetToDefaultIcon();
      print('App icon reset to default.');
    } catch (e) {
      print('Error resetting app icon: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Dynamic App Icon Demo'),
        ),
        body: Center(
          child: Text('Check your app icon!'),
        ),
      ),
    );
  }
}

在上面的代码中,我们首先检查设备是否支持动态图标更改,如果支持,则调用DynamicAppIcon.setAlternateIconName方法来设置备选图标。备选图标的名称应该与你在mipmap-*目录下添加的图标文件名相匹配(不包括文件扩展名)。

此外,我们还添加了一个延迟调用_changeAppIconToDefault的方法,以便在10秒后自动将图标切换回默认图标。你可以根据需要调整这个逻辑。

请注意,实际使用中,你可能需要在UI中添加按钮或其他交互元素来触发图标的更改,而不是像示例中那样使用Future.delayed

希望这个示例对你有帮助!如果你有任何其他问题,欢迎继续提问。

回到顶部