Widget — یک عنصر جمعوجور رابط کاربری در صفحه اصلی iOS یا Android است که اطلاعات بهروز را بدون باز کردن برنامه نمایش میدهد. ویجتها در iOS 14 (2020) با فریمورک WidgetKit بر روی SwiftUI ظاهر شدند و در Android از نسخه 1.5 از طریق AppWidgetProvider به Kotlin یا Java وجود دارند. آنها به کاربر امکان میدهند آبوهوا، نرخ ارز، تقویم، یادداشتها یا وضعیت وظایف را مستقیماً روی home screen ببیند، در زمان صرفهجویی کرده و تعامل را سادهتر کنند. طبق دادههای Apple، کاربران به طور میانگین 4–6 بار در روز با ویجتها تعامل دارند و نصب ویجت روی home screen تعامل با برنامه را 20–30% افزایش میدهد. برای Android این ارقام قابل مقایسه هستند. بیایید نحوه عملکرد ویجتها را در هر دو پلتفرم با مثالهای کد بررسی کنیم.
نکات اصلی
Widget — یک عنصر جمعوجور رابط کاربری است که روی صفحه اصلی دستگاه همراه برای نمایش اطلاعات بهروز از برنامه قرار میگیرد. برخلاف یک برنامه کامل، ویجت نیازی به اجرا ندارد — کاربر بلافاصله پس از باز کردن قفل صفحه دادهها را میبیند. این مفهوم از سیستمهای دسکتاپ (macOS Dashboard، Windows Sidebar) آمده است و در محیط همراه Android از اولین نسخه (Android 1.5 Cupcake، 2009) پشتیبانی از ویجتها را معرفی کرد، در حالی که Apple فقط در iOS 14 آنها را اضافه کرد.
پیادهسازی فنی در پلتفرمها متفاوت است. ویجت iOS — یک target جداگانه در Xcode که به عنوان Widget Extension کامپایل میشود و در فرآیند خود کار میکند. ویجت Android — BroadcastReceiver ای که AppWidgetProvider را توسعه میدهد و layout را از طریق RemoteViews رندر میکند. هر دو پلتفرم محدودیتهای سختی بر عملکرد و حافظه اعمال میکنند: سیستم میتواند ویجت را در صورت تجاوز از محدودیتها حذف کند. iOS ویجت را به 30–50 MB و زمان تشکیل timeline را به 10 ثانیه محدود میکند. Android — فاصله بهروزرسانی از طریق updatePeriodMillis حداکثر هر 30 دقیقه و خاتمه اجباری در صورت قفل شدن onUpdate.
Smart Stack در iOS و پشتهها در Android به کاربر امکان میدهند چندین ویجت را در یک اسلات روی home screen گروهبندی کند. دستگاه به طور خودکار ویجت نمایش داده شده را بسته به زمان روز، مکان یا فعالیت کاربر تغییر میدهد. مثلاً صبح تقویم، ظهر آبوهوا، عصر یادداشتها نمایش داده میشود. برای توسعهدهنده این به معنای آن است که ویجت باید درون پشته به درستی کار کند و به نمایش دائمی وابسته نباشد.
WidgetKit — فریمورک Apple برای ایجاد ویجتها در iOS 14+، iPadOS 14+ و macOS 11+ است. ویجتها به Swift با استفاده از SwiftUI و مکانیزم TimelineProvider برای بهروزرسانی محتوا نوشته میشوند. معماری WidgetKit شامل سه مؤلفه است: TimelineProvider — منبع دادهای که یک timeline با رکوردها تشکیل میدهد; Widget Entry View — SwiftUI View که محتوا را بر اساس رکورد نمایش میدهد; Widget Configuration — توصیف نوع، اندازهها و خانوادههای ویجت.
WidgetKit خود بهروزرسانی را مدیریت میکند — توسعهدهنده نمیتواند ویجت را بیشتر از آنچه سیستم اجازه میدهد بهروزرسانی کند. Apple از بودجه بهروزرسانی استفاده میکند که بین تمام ویجتهای دستگاه توزیع میشود. حداقل فاصله — 15–30 دقیقه. برای دادههای حیاتی (مثلاً وضعیت تحویل) از push-to-refresh استفاده میشود — ارسال اعلان push با تاریخ مربوطه در آینده، پس از آن WidgetKit یک timeline جدید درخواست میکند. از iOS 17 ویجتها از تعامل از طریق App Intents پشتیبانی میکنند — کاربر میتواند دکمههای داخل ویجت را بدون باز کردن برنامه فشار دهد.
| اندازه | iOS (pt) | محتوا |
|---|---|---|
| Small | 170 × 170 | 1–2 شاخص: دما، نرخ ارز |
| Medium | 360 × 170 | 2–4 شاخص: پیشبینی 5 روزه، لیست |
| Large | 360 × 380 | 5–10 شاخص: تقویم، فید خبری |
AppWidgetProvider — کلاس پایه برای ایجاد ویجتها در Android است که از API level 3 در Android SDK گنجانده شده است. ویجت Android — یک BroadcastReceiver است که رویدادهای بهروزرسانی، فعال و غیرفعال شدن را از سیستم دریافت میکند. برخلاف iOS که ویجت توسط SwiftUI بر روی موتور خود کشیده میشود، Android از RemoteViews — مجموعه محدودی از مؤلفههای View که در فرآیند سیستم (launcher) رندر میشوند استفاده میکند. نمیتوان از Viewهای سفارشی، انیمیشنهای پیچیده یا کتابخانههای UI استفاده کرد.
طرح کار ویجت Android شامل چهار مرحله است. پیکربندی — هنگام افزودن ویجت به صفحه، سیستم میتواند یک Activity پیکربندی راهاندازی کند که کاربر تنظیمات را انتخاب میکند. بهروزرسانی — سیستم onUpdate() را در یک بازه مشخص (حداقل 30 دقیقه) یا با سیگنال از برنامه از طریق WorkManager فراخوانی میکند. رندر — ارائهدهنده RemoteViews را با دادههای جاری ایجاد کرده و از طریق AppWidgetManager ارسال میکند. پردازش کلیکها — ویجت از PendingIntent برای دکمهها پشتیبانی میکند: با کلیک Activity باز میشود یا عملی انجام میشود. از Android 12 ویجتها پشتیبانی از گوشههای گرد، رنگهای تطبیقی Material You و تغییر اندازه پویا دریافت کردند.
بیایید یک ویجت آبوهوا به Swift با استفاده از WidgetKit و SwiftUI ایجاد کنیم. پروژه باید شامل Widget Extension target باشد که در Xcode از طریق File → New → Target → Widget Extension اضافه میشود.
import WidgetKit
import SwiftUI
// 1. مدل داده برای ویجت
struct WeatherEntry: TimelineEntry {
let date: Date
let temperature: Int
let condition: String
}
// 2. TimelineProvider — تأمینکننده داده
struct Provider: TimelineProvider {
func placeholder(in context: Context) -> WeatherEntry {
WeatherEntry(date: Date(), temperature: 22, condition: "آفتابی")
}
func getSnapshot(in context: Context, completion: @escaping (WeatherEntry) -> Void) {
let entry = WeatherEntry(date: Date(), temperature: 22, condition: "آفتابی")
completion(entry)
}
func getTimeline(in context: Context, completion: @escaping (Timeline<WeatherEntry>) -> Void) {
let now = Date()
let entry = WeatherEntry(date: now, temperature: 20, condition: "ابری")
let nextUpdate = Calendar.current.date(byAdding: .hour, value: 3, to: now)!
let timeline = Timeline(entries: [entry], policy: .after(nextUpdate))
completion(timeline)
}
}
// 3. SwiftUI View برای نمایش
struct WeatherWidgetEntryView: View {
var entry: WeatherEntry
var body: some View {
VStack(alignment: .leading) {
Text("آبوهوا").font(.caption).foregroundColor(.secondary)
HStack {
Text("\(entry.temperature)°").font(.largeTitle).fontWeight(.bold)
Spacer()
Text(entry.condition).font(.body)
}
}.padding()
}
}
// 4. پیکربندی ویجت
@main
struct WeatherWidget: Widget {
var body: some WidgetConfiguration {
StaticConfiguration(kind: "WeatherWidget", provider: Provider()) { entry in
WeatherWidgetEntryView(entry: entry)
}
.configurationDisplayName("آبوهوا")
.description("دمای فعلی را نشان میدهد")
.supportedFamilies([.systemSmall, .systemMedium])
}
}
نکات کلیدی: TimelineProvider تعیین میکند چه زمانی و چه دادههایی نمایش داده شود; getTimeline یک timeline با سیاست بهروزرسانی .after(nextUpdate) ایجاد میکند; StaticConfiguration ارائهدهنده را به View متصل میکند. برای دادههای پویا از IntentConfiguration با پارامترهای کاربر استفاده میشود.
ویجت مشابه آبوهوا را به Kotlin با AppWidgetProvider و RemoteViews پیادهسازی میکنیم.
// WeatherWidgetProvider.kt
class WeatherWidgetProvider : AppWidgetProvider() {
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray
) {
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
override fun onAppWidgetOptionsChanged(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetId: Int,
newOptions: Bundle
) {
updateAppWidget(context, appWidgetManager, appWidgetId)
}
companion object {
fun updateAppWidget(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetId: Int
) {
val temperature = 20
val condition = "ابری"
val views = RemoteViews(
context.packageName, R.layout.widget_weather
).apply {
setTextViewText(R.id.tv_temperature, "$temperature°")
setTextViewText(R.id.tv_condition, condition)
setOnClickPendingIntent(
R.id.widget_root, PendingIntent.getActivity(
context, 0,
Intent(context, MainActivity::class.java),
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
)
}
appWidgetManager.updateAppWidget(appWidgetId, views)
}
}
}
// AndroidManifest — ثبت ارائهدهنده
<receiver android:name=".WeatherWidgetProvider" android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_weather_info" />
</receiver>
فایل widget_weather_info.xml حداقل اندازهها، فاصله و layout را تعیین میکند: minWidth 160dp، minHeight 80dp، updatePeriodMillis 3600000 (1 ساعت). RemoteViews فقط از مؤلفههای پشتیبانی شده استفاده میکند: LinearLayout، TextView، ImageView. Viewهای سفارشی و ConstraintLayout از Android 5.0 در دسترس هستند. GlanceLayout — رویکرد آزمایشی Compose برای RemoteViews — در Android 15 ظاهر شد.
سوالات متداول
iOS WidgetKit سه اندازه ثابت (small، medium، large) و بهروزرسانی از طریق TimelineProvider با بودجه سیستم ارائه میدهد. Android AppWidgetProvider از اندازههای انعطافپذیر در سلولها، RemoteViews برای رندر و بهروزرسانی از طریق updatePeriodMillis یا WorkManager استفاده میکند.
در iOS بهروزرسانی توسط سیستم کنترل میشود — حداقل فاصله 15–30 دقیقه، برای دادههای حیاتی از push-to-refresh استفاده میشود. در Android فاصله در updatePeriodMillis (حداقل 30 دقیقه) یا از طریق WorkManager برای وظایف پسزمینه تنظیم میشود.
iOS از small (170x170pt)، medium (360x170pt) و large (360x380pt) پشتیبانی میکند. Android از شبکه سلولی انعطافپذیر استفاده میکند: از 2x1 تا 5x5، اندازه بستگی به launcher و نسخه OS دارد.
در iOS انیمیشنهایی درون ویجت وجود ندارد — اینها عناصر ایستا هستند. Android RemoteViews از انیمیشنهای پایه از طریق setFloat() و ViewPropertyAnimator پشتیبانی میکند، اما انیمیشنهای پیچیده در دسترس نیستند.
با پیادهسازی صحیح — خیر. سیستم منابع ویجت را به شدت محدود میکند: در iOS بودجه بهروزرسانی و حافظه (30–50 MB)، در Android — حداقل فاصله بهروزرسانی. ویجتهای مشکلدار توسط سیستم به اجبار خاتمه مییابند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.