Widget — ένα συμπαγές στοιχείο διεπαφής χρήστη στην αρχική οθόνη iOS ή Android που εμφανίζει ενημερωμένες πληροφορίες χωρίς άνοιγμα της εφαρμογής. Τα widget εμφανίστηκαν στο iOS 14 (2020) με το πλαίσιο WidgetKit σε SwiftUI και υπάρχουν στο Android από την έκδοση 1.5 μέσω του AppWidgetProvider σε Kotlin ή Java. Επιτρέπουν στον χρήστη να βλέπει τον καιρό, τις ισοτιμίες, το ημερολόγιο, σημειώσεις ή την κατάσταση εργασιών απευθείας στην home screen, εξοικονομώντας χρόνο και απλοποιώντας την αλληλεπίδραση. Σύμφωνα με δεδομένα της Apple, οι χρήστες αλληλεπιδρούν με τα widget κατά μέσο όρο 4–6 φορές την ημέρα και η εγκατάσταση ενός widget στην home screen αυξάνει την αφοσίωση στην εφαρμογή κατά 20–30%. Για το Android αυτά τα νούμερα είναι συγκρίσιμα. Ας δούμε πώς λειτουργούν τα widget και στις δύο πλατφόρμες, με παραδείγματα κώδικα.
Κύρια σημεία
Widget — είναι ένα συμπαγές στοιχείο διεπαφής χρήστη που τοποθετείται στην αρχική οθόνη της κινητής συσκευής για εμφάνιση ενημερωμένων πληροφοριών από την εφαρμογή. Σε αντίθεση με μια πλήρη εφαρμογή, το widget δεν απαιτεί εκκίνηση — ο χρήστης βλέπει τα δεδομένα αμέσως μετά το ξεκλείδωμα της οθόνης. Η ιδέα προέρχεται από λειτουργικά συστήματα επιτραπέζιων υπολογιστών (macOS Dashboard, Windows Sidebar), και στο κινητό περιβάλλον το Android εισήγαγε υποστήριξη για widget από την πρώτη κυκλοφορία (Android 1.5 Cupcake, 2009), ενώ η Apple τα πρόσθεσε μόνο στο iOS 14.
Τεχνική υλοποίηση διαφέρει ανά πλατφόρμα. Widget iOS — ξεχωριστός στόχος στο Xcode, μεταγλωττισμένο ως Widget Extension, που λειτουργεί στη δική του διεργασία. Widget Android — BroadcastReceiver που επεκτείνει το AppWidgetProvider, αποδίδοντας τη διάταξη μέσω RemoteViews. Και οι δύο πλατφόρμες επιβάλλουν αυστηρούς περιορισμούς στην απόδοση και τη μνήμη: το σύστημα μπορεί να αφαιρέσει το widget όταν υπερβεί τα όρια. Το iOS περιορίζει το widget στα 30–50 MB και τον χρόνο δημιουργίας timeline στα 10 δευτερόλεπτα. Android — διάστημα ενημέρωσης όχι συχνότερο από 30 λεπτά μέσω updatePeriodMillis και αναγκαστικός τερματισμός σε περίπτωση παγώματος του onUpdate.
Smart Stack στο iOS και στοίβες στο Android επιτρέπουν στον χρήστη να ομαδοποιεί πολλά widget σε μία υποδοχή στην home screen. Η συσκευή εναλλάσσει αυτόματα το εμφανιζόμενο widget ανάλογα με την ώρα της ημέρας, την τοποθεσία ή τη δραστηριότητα του χρήστη. Για παράδειγμα, το πρωί εμφανίζεται το ημερολόγιο, το μεσημέρι — ο καιρός, το βράδυ — σημειώσεις. Για τον προγραμματιστή αυτό σημαίνει ότι το widget πρέπει να λειτουργεί σωστά εντός μιας στοίβας και να μην βασίζεται στη συνεχή εμφάνιση.
WidgetKit — το πλαίσιο της Apple για δημιουργία widget σε iOS 14+, iPadOS 14+ και macOS 11+. Τα widget γράφονται σε Swift χρησιμοποιώντας SwiftUI και τον μηχανισμό TimelineProvider για ενημέρωση περιεχομένου. Η αρχιτεκτονική του WidgetKit περιλαμβάνει τρία στοιχεία: TimelineProvider — πηγή δεδομένων που σχηματίζει μια γραμμή χρόνου με εγγραφές; Widget Entry View — SwiftUI View που εμφανίζει περιεχόμενο βάσει εγγραφής; Widget Configuration — περιγραφή τύπου, μεγεθών και οικογενειών του widget.
Το WidgetKit διαχειρίζεται μόνο του την ενημέρωση — ο προγραμματιστής δεν μπορεί να εξαναγκάσει την ενημέρωση του widget συχνότερα από όσο επιτρέπει το σύστημα. Η Apple χρησιμοποιεί προϋπολογισμό ενημερώσεων που κατανέμεται μεταξύ όλων των widget στη συσκευή. Ελάχιστο διάστημα — 15–30 λεπτά. Για κρίσιμα δεδομένα (π.χ. κατάσταση παράδοσης) χρησιμοποιείται push-to-refresh — αποστολή ειδοποίησης push με σχετική ημερομηνία στο μέλλον, μετά την οποία το WidgetKit ζητά νέα γραμμή χρόνου. Από το iOS 17 τα widget υποστηρίζουν διαδραστικότητα μέσω App Intents — ο χρήστης μπορεί να πατάει κουμπιά μέσα στο widget χωρίς να ανοίγει την εφαρμογή.
| Μέγεθος | iOS (pt) | Περιεχόμενο |
|---|---|---|
| Small | 170 × 170 | 1–2 δείκτες: θερμοκρασία, ισοτιμία |
| Medium | 360 × 170 | 2–4 δείκτες: πρόγνωση 5 ημερών, λίστα |
| Large | 360 × 380 | 5–10 δείκτες: ημερολόγιο, ροή ειδήσεων |
AppWidgetProvider — η βασική κλάση για δημιουργία widget στο Android, μέρος του Android SDK από το API level 3. Widget Android — είναι ένας BroadcastReceiver που λαμβάνει γεγονότα ενημέρωσης, ενεργοποίησης και απενεργοποίησης από το σύστημα. Σε αντίθεση με το iOS, όπου το widget σχεδιάζεται από το SwiftUI στη δική του μηχανή, το Android χρησιμοποιεί RemoteViews — ένα περιορισμένο σύνολο στοιχείων View που αποδίδονται στη διεργασία συστήματος (launcher). Δεν μπορούν να χρησιμοποιηθούν προσαρμοσμένα View, σύνθετες κινήσεις ή βιβλιοθήκες UI.
Το σχήμα λειτουργίας του widget Android περιλαμβάνει τέσσερα στάδια. Διαμόρφωση — κατά την προσθήκη του widget στην οθόνη, το σύστημα μπορεί να εκκινήσει μια Activity διαμόρφωσης όπου ο χρήστης επιλέγει ρυθμίσεις. Ενημέρωση — το σύστημα καλεί την onUpdate() σε καθορισμένο διάστημα (τουλάχιστον 30 λεπτά) ή με σήμα από την εφαρμογή μέσω WorkManager. Απόδοση — ο πάροχος δημιουργεί RemoteViews με τρέχοντα δεδομένα και τα μεταδίδει μέσω AppWidgetManager. Χειρισμός κλικ — το widget υποστηρίζει PendingIntent για κουμπιά: με το κλικ ανοίγει μια Activity ή εκτελείται μια ενέργεια. Από το Android 12 τα widget έλαβαν υποστήριξη για στρογγυλεμένες γωνίες, προσαρμοστικά χρώματα Material You και δυναμική αλλαγή μεγέθους.
Ας δημιουργήσουμε ένα widget καιρού σε Swift χρησιμοποιώντας WidgetKit και SwiftUI. Το έργο πρέπει να περιέχει έναν στόχο Widget Extension, που προστίθεται στο Xcode μέσω File → New → Target → Widget Extension.
import WidgetKit
import SwiftUI
// 1. Μοντέλο δεδομένων για widget
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. Διαμόρφωση widget
@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 δημιουργεί μια γραμμή χρόνου με πολιτική ενημέρωσης .after(nextUpdate); StaticConfiguration συνδέει τον πάροχο με το View. Για δυναμικά δεδομένα χρησιμοποιείται IntentConfiguration με παραμέτρους χρήστη.
Υλοποιούμε ένα παρόμοιο widget καιρού σε 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 ορίζει τα ελάχιστα μεγέθη, το διάστημα και τη διάταξη: 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, το μέγεθος εξαρτάται από τον εκκινητή και την έκδοση OS.
Στο iOS δεν υπάρχουν κινήσεις μέσα στο widget — είναι στατικά στοιχεία. Android RemoteViews υποστηρίζει βασικές κινήσεις μέσω setFloat() και ViewPropertyAnimator, αλλά σύνθετες κινήσεις δεν είναι διαθέσιμες.
Με σωστή υλοποίηση — όχι. Το σύστημα περιορίζει αυστηρά τους πόρους του widget: στο iOS προϋπολογισμό ενημερώσεων και μνήμης (30–50 MB), στο Android — ελάχιστο διάστημα ενημέρωσης. Τα προβληματικά widget τερματίζονται αναγκαστικά από το σύστημα.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης