تغيير أيقونة تطبيق Flutter أثناء التشغيل من المميزات الجميلة التي يمكن أن تضيف تجربة مختلفة داخل التطبيق، خصوصًا لو كنت تريد تغيير شكل التطبيق حسب الموسم، العروض، المناسبات، أو وضع معين داخل التطبيق.
بدل ما تكتفي بأيقونة واحدة ثابتة للتطبيق، يمكنك توفير أكثر من أيقونة، ثم تغيير الأيقونة برمجيًا من داخل Flutter باستخدام مكتبة جاهزة تسهّل التعامل مع Android و iOS.
في هذا المقال سنتعلم طريقة تغيير أيقونة تطبيق Flutter بسهولة وبدون تعقيد باستخدام مكتبة dynamic_app_icon_flutter_plus، مع شرح إعدادات Android و iOS خطوة بخطوة، بالإضافة إلى مثال عملي كامل.
ما المقصود بتغيير أيقونة التطبيق أثناء التشغيل؟
تغيير أيقونة التطبيق أثناء التشغيل أو ما يعرف باسم Dynamic App Icon يعني أن التطبيق يمكنه تغيير الأيقونة التي تظهر على شاشة الهاتف بدون الحاجة إلى تثبيت نسخة جديدة من التطبيق.
مثلًا، يمكنك جعل التطبيق يستخدم:
- أيقونة افتراضية للتطبيق
- أيقونة للوضع الداكن
- أيقونة خاصة بشهر رمضان
- أيقونة خاصة بالعروض والخصومات
- أيقونة خاصة بالمناسبات أو الحملات التسويقية
الميزة دي مفيدة جدًا لو تريد جعل التطبيق أكثر تفاعلًا مع المستخدمين أو مع الأحداث المختلفة.
لماذا نستخدم dynamic_app_icon_flutter_plus؟
مكتبة dynamic_app_icon_flutter_plus توفر طريقة سهلة لتغيير أيقونة التطبيق داخل Flutter، بدل ما تتعامل يدويًا مع تفاصيل Android و iOS المعقدة.
المكتبة تساعدك في:
- تغيير أيقونة التطبيق على Android
- تغيير أيقونة التطبيق على iOS
- التحقق هل الجهاز يدعم تغيير الأيقونة أم لا
- الحصول على الأيقونات المتاحة داخل التطبيق
- الرجوع إلى الأيقونة الأصلية بسهولة
- التعامل مع الفروق بين Android و iOS بطريقة أبسط
تثبيت مكتبة dynamic_app_icon_flutter_plus
أول خطوة هي إضافة المكتبة داخل ملف pubspec.yaml.
dependencies:
flutter:
sdk: flutter
dynamic_app_icon_flutter_plus: ^1.0.0
بعد إضافة المكتبة، شغل الأمر التالي:
flutter pub get
بعد ذلك نبدأ في إعداد Android و iOS حتى يستطيع التطبيق تغيير الأيقونة بشكل صحيح.
إعدادات Android لتغيير أيقونة تطبيق Flutter
في Android، الطريقة الأصلية لتغيير أيقونة التطبيق تعتمد على استخدام activity-alias داخل ملف AndroidManifest.xml.
الفكرة ببساطة أنك تقوم بتعريف أكثر من Alias لكل أيقونة، وكل Alias يشير إلى نفس MainActivity، لكن بأيقونة مختلفة.
مكان ملف AndroidManifest.xml
افتح الملف التالي داخل مشروع Flutter:
android/app/src/main/AndroidManifest.xml
ثم أضف activity-alias داخل وسم application.
مثال على activity-alias في Android
<activity-alias
android:name="com.example.yourapp.MainActivity.dark"
android:targetActivity=".MainActivity"
android:exported="true"
android:icon="@mipmap/ic_launcher_dark"
android:label="@string/app_name"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity-alias>
في المثال السابق قمنا بتعريف أيقونة بديلة باسم dark، وهي تستخدم الصورة الموجودة داخل:
@mipmap/ic_launcher_dark
شرح خصائص activity-alias
android:name
android:name="com.example.yourapp.MainActivity.dark"
هذا هو اسم الـ Alias الخاص بالأيقونة البديلة.
يفضل أن يكون الاسم واضحًا ويعبّر عن الأيقونة، مثل:
dark
ramadan
new_year
offer
android:targetActivity
android:targetActivity=".MainActivity"
هذا يعني أن الـ Alias سيقوم بتشغيل نفس MainActivity الخاصة بالتطبيق.
android:icon
android:icon="@mipmap/ic_launcher_dark"
هنا نحدد الأيقونة التي ستظهر عندما يتم تفعيل هذا الـ Alias.
android:enabled
android:enabled="false"
نجعل الأيقونة البديلة غير مفعلة في البداية، ثم نقوم بتفعيلها برمجيًا عند الحاجة.
إضافة أكثر من أيقونة في Android
يمكنك إضافة أكثر من activity-alias حسب عدد الأيقونات التي تريد دعمها.
<activity-alias
android:name="com.example.yourapp.MainActivity.ramadan"
android:targetActivity=".MainActivity"
android:exported="true"
android:icon="@mipmap/ic_launcher_ramadan"
android:label="@string/app_name"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity-alias>
في هذا المثال أضفنا أيقونة بديلة باسم ramadan.
مكان وضع أيقونات Android
يجب وضع الأيقونات داخل مجلدات mipmap المختلفة حسب الكثافة.
android/app/src/main/res/mipmap-mdpi/ic_launcher_dark.png
android/app/src/main/res/mipmap-hdpi/ic_launcher_dark.png
android/app/src/main/res/mipmap-xhdpi/ic_launcher_dark.png
android/app/src/main/res/mipmap-xxhdpi/ic_launcher_dark.png
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_dark.png
ويجب أن تكون أسماء الملفات متطابقة مع الاسم المستخدم في android:icon.
يعني لو كتبت:
android:icon="@mipmap/ic_launcher_dark"
لازم يكون اسم الملف:
ic_launcher_dark.png
ملاحظة مهمة حول Android
طريقة activity-alias هي الطريقة الأصلية والموثوقة في Android لتغيير أيقونة التطبيق.
لكن يجب الانتباه أن بعض أجهزة Android قد تحتاج عدة ثوانٍ حتى يظهر تغيير الأيقونة على الشاشة الرئيسية.
وفي بعض الأجهزة، قد لا يظهر التغيير إلا بعد إغلاق التطبيق أو تحديث شاشة اللانشر.
إعدادات iOS لتغيير أيقونة تطبيق Flutter
في iOS، تغيير الأيقونة يتم من خلال تعريف الأيقونات البديلة داخل ملف Info.plist.
النظام يسمح لك بتحديد CFBundlePrimaryIcon للأيقونة الأساسية، و CFBundleAlternateIcons للأيقونات البديلة.
مكان ملف Info.plist
افتح الملف التالي داخل مشروع Flutter:
ios/Runner/Info.plist
ثم أضف إعدادات الأيقونات داخل الملف.
مثال على CFBundleIcons داخل Info.plist
<key>CFBundleIcons</key>
<dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>default</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>dark</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>dark</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>ramadan</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>ramadan</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
</dict>
</dict>
في المثال السابق عندنا أيقونة أساسية باسم default، وأيقونتين بديلتين:
darkramadan
وضع أيقونات iOS داخل Assets
يجب وضع ملفات الأيقونات داخل Assets الخاصة بمشروع iOS.
غالبًا ستحتاج إلى توفير الأحجام المناسبة مثل:
@2x@3x
ويجب أن تطابق أسماء الأيقونات الأسماء الموجودة داخل Info.plist.
يعني لو كتبت:
<string>dark</string>
لازم تكون ملفات الأيقونة معرفة باسم dark داخل أصول iOS.
تحذير مهم بخصوص iOS
عند تغيير أيقونة التطبيق في iOS، قد يظهر تنبيه نظامي للمستخدم يخبره أن التطبيق يريد تغيير الأيقونة.
بعض المكتبات توفر خيارًا مثل showAlert لإخفاء هذا التنبيه، لكن يجب استخدامه بحذر لأنه يعتمد على حلول غير رسمية، وقد يتغير سلوك iOS في المستقبل.
التحقق هل الجهاز يدعم تغيير الأيقونة
قبل تغيير الأيقونة، من الأفضل التأكد أن الجهاز يدعم هذه الميزة.
final isSupported = await DynamicAppIconFlutterPlus.isSupported();
if (isSupported) {
print("Dynamic app icon is supported");
} else {
print("Dynamic app icon is not supported");
}
هذه الخطوة مهمة حتى لا تحاول تغيير الأيقونة على جهاز أو نظام لا يدعم الميزة.
الحصول على الأيقونات المتاحة
يمكنك الحصول على قائمة الأيقونات المتاحة داخل التطبيق باستخدام:
final icons = await DynamicAppIconFlutterPlus.getAlternateIconNames();
print(icons);
الميزة دي مفيدة لأنها تساعدك على عرض الأيقونات المتاحة للمستخدم داخل شاشة إعدادات مثلًا.
تعيين أيقونة بديلة في Flutter
لتغيير أيقونة التطبيق إلى أيقونة بديلة مثل الوضع الداكن، استخدم:
await DynamicAppIconFlutterPlus.setAlternateIconName('dark');
هنا يجب أن يكون الاسم dark مطابقًا للاسم الموجود في إعدادات Android و iOS.
مثال آخر لتغيير الأيقونة إلى أيقونة رمضان:
await DynamicAppIconFlutterPlus.setAlternateIconName('ramadan');
الرجوع إلى الأيقونة الأصلية
للرجوع إلى الأيقونة الافتراضية للتطبيق، أرسل قيمة null.
await DynamicAppIconFlutterPlus.setAlternateIconName(null);
بهذا الشكل يعود التطبيق إلى الأيقونة الأساسية.
مثال عملي كامل لتغيير أيقونة تطبيق Flutter
في المثال التالي سننشئ شاشة بسيطة تحتوي على أزرار لتغيير أيقونة التطبيق إلى الوضع الداكن أو أيقونة رمضان أو الرجوع للأيقونة الأصلية.
import 'package:flutter/material.dart';
import 'package:dynamic_app_icon_flutter_plus/dynamic_app_icon_flutter_plus.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: ChangeAppIconScreen(),
);
}
}
class ChangeAppIconScreen extends StatefulWidget {
const ChangeAppIconScreen({super.key});
@override
State<ChangeAppIconScreen> createState() => _ChangeAppIconScreenState();
}
class _ChangeAppIconScreenState extends State<ChangeAppIconScreen> {
bool isSupported = false;
String currentStatus = "Checking support...";
@override
void initState() {
super.initState();
checkSupport();
}
Future<void> checkSupport() async {
final supported = await DynamicAppIconFlutterPlus.isSupported();
setState(() {
isSupported = supported;
currentStatus = supported
? "تغيير الأيقونة مدعوم على هذا الجهاز"
: "تغيير الأيقونة غير مدعوم على هذا الجهاز";
});
}
Future<void> changeIcon(String? iconName) async {
if (!isSupported) {
setState(() {
currentStatus = "الجهاز لا يدعم تغيير الأيقونة";
});
return;
}
try {
await DynamicAppIconFlutterPlus.setAlternateIconName(iconName);
setState(() {
currentStatus = iconName == null
? "تم الرجوع إلى الأيقونة الأصلية"
: "تم تغيير الأيقونة إلى: $iconName";
});
} catch (e) {
setState(() {
currentStatus = "حدث خطأ أثناء تغيير الأيقونة: $e";
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("تغيير أيقونة التطبيق"),
),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Text(
currentStatus,
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 16),
),
const SizedBox(height: 24),
ElevatedButton(
onPressed: () => changeIcon('dark'),
child: const Text("تفعيل أيقونة الوضع الداكن"),
),
const SizedBox(height: 12),
ElevatedButton(
onPressed: () => changeIcon('ramadan'),
child: const Text("تفعيل أيقونة رمضان"),
),
const SizedBox(height: 12),
ElevatedButton(
onPressed: () => changeIcon(null),
child: const Text("الرجوع للأيقونة الأصلية"),
),
],
),
),
);
}
}
شرح المثال العملي
في البداية قمنا باستدعاء المكتبة:
import 'package:dynamic_app_icon_flutter_plus/dynamic_app_icon_flutter_plus.dart';
ثم تحققنا هل الجهاز يدعم تغيير الأيقونة:
final supported = await DynamicAppIconFlutterPlus.isSupported();
وبعد ذلك استخدمنا الدالة التالية لتغيير الأيقونة:
await DynamicAppIconFlutterPlus.setAlternateIconName(iconName);
لو كانت قيمة iconName تساوي dark، سيتم تعيين أيقونة الوضع الداكن.
ولو كانت القيمة null، سيتم الرجوع إلى الأيقونة الأصلية.
أسماء الأيقونات يجب أن تكون متطابقة
من أكثر الأخطاء الشائعة عند تغيير أيقونة تطبيق Flutter أن أسماء الأيقونات تكون مختلفة بين Flutter و Android و iOS.
لازم تتأكد أن الاسم المستخدم في الكود:
setAlternateIconName('dark')
يطابق الاسم الموجود في:
AndroidManifest.xmlInfo.plist- ملفات الأيقونات داخل المشروع
مثال على أسماء متطابقة
في Flutter:
await DynamicAppIconFlutterPlus.setAlternateIconName('dark');
في Android:
android:name="com.example.yourapp.MainActivity.dark"
android:icon="@mipmap/ic_launcher_dark"
في iOS:
<key>dark</key>
هذا التوافق في الأسماء يقلل المشاكل أثناء التشغيل.
مشاكل شائعة عند تغيير أيقونة تطبيق Flutter
الأيقونة لا تتغير على Android
تأكد من أنك أضفت activity-alias داخل AndroidManifest.xml، وأن الأيقونة موجودة داخل مجلدات mipmap.
ثم جرّب حذف التطبيق من الجهاز وإعادة تثبيته.
ظهور أكثر من أيقونة للتطبيق
هذا يحدث غالبًا إذا كانت أكثر من activity-alias مفعلة في نفس الوقت.
تأكد أن الأيقونات البديلة تكون:
android:enabled="false"
وأن المكتبة تقوم بتفعيل أيقونة واحدة فقط عند التغيير.
الأيقونة لا تتغير على iOS
تأكد من إضافة الأيقونات داخل Info.plist بشكل صحيح، وتأكد أن أسماء الملفات مطابقة لأسماء الأيقونات.
iOS يظهر تنبيه عند تغيير الأيقونة
هذا سلوك طبيعي في iOS. بعض المكتبات توفر خيارًا لإخفاء التنبيه، لكن الأفضل استخدامه بحذر.
الأيقونة لا تظهر مباشرة بعد التغيير
بعض أنظمة التشغيل أو واجهات اللانشر تحتاج وقت بسيط حتى تحدث الأيقونة.
انتظر قليلًا أو أغلق التطبيق وافتحه مرة أخرى.
أفضل الممارسات عند تغيير أيقونة التطبيق
- استخدم أسماء واضحة للأيقونات مثل
darkوramadan - تأكد من تطابق أسماء الأيقونات بين Flutter و Android و iOS
- وفر جميع مقاسات الأيقونات المطلوبة لكل منصة
- لا تغيّر الأيقونة بشكل متكرر ومزعج للمستخدم
- استخدم الميزة في حالات واضحة مثل المواسم أو الإعدادات
- اختبر الميزة على أجهزة حقيقية وليس المحاكي فقط
- تأكد من الرجوع للأيقونة الأصلية عند الحاجة
متى تستخدم Dynamic App Icon؟
ميزة تغيير أيقونة التطبيق مفيدة في حالات كثيرة، مثل:
- تطبيقات المتاجر أثناء العروض
- تطبيقات التعليم في المواسم الدراسية
- تطبيقات دينية في رمضان أو المناسبات
- تطبيقات الأخبار وقت الأحداث الخاصة
- تطبيقات تدعم الوضع الداكن
- تطبيقات تسمح للمستخدم بتخصيص شكل التطبيق
هل تغيير أيقونة التطبيق يعمل على كل الأجهزة؟
الميزة مدعومة على Android و iOS، لكن السلوك قد يختلف قليلًا حسب الجهاز ونظام التشغيل واللانشر المستخدم.
لذلك من الأفضل دائمًا استخدام:
DynamicAppIconFlutterPlus.isSupported()
قبل محاولة تغيير الأيقونة.
مميزات dynamic_app_icon_flutter_plus
- واجهة استخدام بسيطة داخل Flutter
- دعم Android و iOS
- إمكانية الرجوع للأيقونة الأصلية
- التحقق من دعم الجهاز للميزة
- تقليل التعامل المباشر مع أكواد Native
- مناسبة للتطبيقات التي تحتاج تخصيص بصري
عيوب أو ملاحظات قبل الاستخدام
- تحتاج إعدادات Native في Android و iOS
- يجب تجهيز الأيقونات بأحجام صحيحة
- قد يظهر تنبيه في iOS عند تغيير الأيقونة
- قد يتأخر ظهور التغيير على بعض أجهزة Android
- تحتاج اختبار جيد قبل إطلاق التطبيق
الخلاصة
تغيير أيقونة تطبيق Flutter أصبح أسهل باستخدام مكتبة dynamic_app_icon_flutter_plus، حيث يمكنك تغيير الأيقونة برمجيًا على Android و iOS بدون كتابة الكثير من الأكواد المعقدة.
على Android ستحتاج إلى إعداد activity-alias داخل AndroidManifest.xml، وعلى iOS ستحتاج إلى تعريف الأيقونات البديلة داخل Info.plist.
بعد ذلك يمكنك استخدام دالة بسيطة مثل:
await DynamicAppIconFlutterPlus.setAlternateIconName('dark');
أو الرجوع إلى الأيقونة الأصلية باستخدام:
await DynamicAppIconFlutterPlus.setAlternateIconName(null);
في النهاية، إذا كنت تريد تخصيص تجربة المستخدم أو تغيير شكل التطبيق في المناسبات والعروض، فإن تغيير أيقونة تطبيق Flutter باستخدام dynamic_app_icon_flutter_plus يعتبر حلًا عمليًا وسهل التنفيذ.
مزيد من المقالات : اجعل تطبيقات Flutter الخاصة بك تنبض بالحياة مع الوسائط المتعددة





