[TIL] Day 72 Flutter 홈 위젯은 어떻게 만드는가?

현서·2026년 3월 11일

[TIL] Flutter 9기

목록 보기
84/102

Flutter 홈 위젯 제작

1. 패키지 설치

flutter pub add home_widget

2. iOS 위젯 만들기

1단계: Xcode에서 Widget Target 생성

  1. ios 폴더를 Xcode로 열기
  2. File → New → Target → Widget Extension 선택
  3. Product Name: NewsWidgets 입력
  4. Finish 클릭

2단계: 앱 그룹 설정

두 타겟 모두 설정해야 한다.

Runner 타겟:
1. Signing & Capabilities 탭 이동
2. + Capability → App Groups 선택
3. group.com.example.app 입력 (Bundle ID에 맞춰 수정)

NewsWidgets 타겟:
1. 동일하게 App Groups 추가
2. 동일한 그룹명 입력

3단계: Build Phases 순서 변경

  1. Runner 선택
  2. Build Phases 탭
  3. Thin Binary를 맨 아래로 이동

4단계: 위젯 UI 코드 작성 (NewsWidgets.swift)

// 데이터 구조 정의
struct NewsArticleEntry: TimelineEntry {
    let date: Date
    let title: String
    let description: String
}

// 위젯 UI 표시
struct NewsWidgetsEntryView : View {
    var entry: NewsArticleEntry

    var body: some View {
      VStack(alignment: .leading, spacing: 8) {
        Text(entry.title)
          .font(.headline)
          .lineLimit(2)
        
        Text(entry.description)
          .font(.body)
          .lineLimit(3)
      }
      .padding()
    }
}

5단계: 데이터 읽기 설정 (Provider)

struct Provider: TimelineProvider {
    
    // 위젯 처음 표시할 때 임시 데이터
    func placeholder(in context: Context) -> NewsArticleEntry {
        NewsArticleEntry(
            date: Date(),
            title: "제목",
            description: "설명"
        )
    }

    // 현재 데이터 가져오기
    func getSnapshot(in context: Context, completion: @escaping (NewsArticleEntry) -> ()) {
        let userDefaults = UserDefaults(suiteName: "group.com.example.app")
        let title = userDefaults?.string(forKey: "headline_title") ?? "제목 없음"
        let description = userDefaults?.string(forKey: "headline_description") ?? "설명 없음"
        
        let entry = NewsArticleEntry(
            date: Date(),
            title: title,
            description: description
        )
        completion(entry)
    }

    // 위젯 업데이트 일정 설정
    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        getSnapshot(in: context) { entry in
            let timeline = Timeline(entries: [entry], policy: .atEnd)
            completion(timeline)
        }
    }
}

6단계: 실행 및 테스트

  1. Xcode 상단에서 Target을 NewsWidgets으로 변경
  2. 시뮬레이터 선택 후 실행
  3. 홈 화면 길게 누르기 → + → NewsWidgets 추가

3. Android 위젯 만들기

1단계: Android Studio에서 Widget 생성

  1. app 폴더 우클릭
  2. New → Widget → App Widget 선택
  3. Class Name: NewsWidget 입력
  4. Configure Activity 선택
  5. Create 클릭

2단계: 레이아웃 파일 작성 (res/layout/news_widget.xml)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/widget_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="8dp"
    android:background="@android:color/white">

    <TextView
        android:id="@+id/headline_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="제목"
        android:textSize="18sp"
        android:textStyle="bold"
        android:textColor="@android:color/black" />

    <TextView
        android:id="@+id/headline_description"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/headline_title"
        android:layout_marginTop="8dp"
        android:text="설명"
        android:textSize="14sp"
        android:textColor="@android:color/darker_gray" />

</RelativeLayout>

3단계: 위젯 기능 구현 (NewsWidget.kt)

package com.example.homescreen_widgets

import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.widget.RemoteViews
import es.antonborri.home_widget.HomeWidgetPlugin

class NewsWidget : AppWidgetProvider() {
    
    override fun onUpdate(
        context: Context,
        appWidgetManager: AppWidgetManager,
        appWidgetIds: IntArray,
    ) {
        // 저장된 데이터 가져오기
        val widgetData = HomeWidgetPlugin.getData(context)
        
        for (appWidgetId in appWidgetIds) {
            // 위젯 레이아웃 설정
            val views = RemoteViews(context.packageName, R.layout.news_widget)
            
            // 제목 설정
            val title = widgetData.getString("headline_title", "제목 없음")
            views.setTextViewText(R.id.headline_title, title)
            
            // 설명 설정
            val description = widgetData.getString("headline_description", "설명 없음")
            views.setTextViewText(R.id.headline_description, description)
            
            // 위젯 업데이트
            appWidgetManager.updateAppWidget(appWidgetId, views)
        }
    }
}

4단계: 실행 및 테스트

  1. 앱 실행
  2. 앱 아이콘 길게 누르기
  3. Widgets 선택
  4. NewsWidget 추가
  5. 홈 화면에 위젯 표시됨

4. Flutter 앱에서 데이터 전송

패키지 설치

flutter pub add home_widget

위젯 업데이트 함수 작성

import 'package:home_widget/home_widget.dart';

Future<void> updateHomeWidget({
  required String title,
  required String description,
}) async {
  try {
    // 1. 데이터 저장
    await HomeWidget.saveWidgetData<String>('headline_title', title);
    await HomeWidget.saveWidgetData<String>('headline_description', description);
    
    // 2. 위젯 업데이트 신호
    await HomeWidget.updateWidget(
      iOSName: 'NewsWidgets',
      androidName: 'NewsWidget',
    );
    
    print('위젯 업데이트 완료');
  } catch (e) {
    print('위젯 업데이트 실패: $e');
  }
}

버튼에서 호출

ElevatedButton(
  onPressed: () {
    updateHomeWidget(
      title: '새로운 기사 제목',
      description: '기사 요약 내용',
    );
  },
  child: const Text('홈 위젯 업데이트'),
),

5. 동작 흐름

Flutter 앱
    ↓
updateHomeWidget() 호출
    ↓
HomeWidget.saveWidgetData() → 데이터 저장
    ├─ iOS: UserDefaults에 저장
    └─ Android: SharedPreferences에 저장
    ↓
HomeWidget.updateWidget() → 위젯 업데이트 신호
    ↓
iOS 위젯                          Android 위젯
Provider.getSnapshot()            NewsWidget.onUpdate()
UserDefaults에서 데이터 읽기      SharedPreferences에서 데이터 읽기
UI 업데이트                       UI 업데이트

6. 정리

항목iOSAndroid
저장소UserDefaultsSharedPreferences
앱 그룹group.com.example.app불필요
언어SwiftKotlin
레이아웃SwiftUIXML
주요 파일NewsWidgets.swiftNewsWidget.kt, news_widget.xml

결론

홈 위젯은 Flutter 앱이 켜지지 않아도 데이터를 표시한다
home_widget 패키지로 Flutter와 네이티브 코드를 연결하여 앱과 위젯이 데이터를 공유할 수 있다.

0개의 댓글