Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- room
- Behavior
- LiveData
- CollapsingToolbarLayout
- HTTP
- 안드로이드
- ViewModel
- hilt
- lifecycle
- Coroutine
- 알림
- onLayout
- 알고리즘
- kotlin
- recyclerview
- Algorithm
- 백준
- Navigation
- 코틀린
- CoordinatorLayout
- sqlite
- activity
- View
- CustomView
- AppBarLayout
- DataBinding
- BOJ
- onMeasure
- Android
- notification
Archives
- Today
- Total
개발일지
Android in A..Z - Widget (생성) 본문
위젯
위젯은 사용자의 홈 화면에서 바로 엑세스할 수 있으며, 정보 표현, 앱 제어 등 다양한 작업을 할 수 있습니다. 하지만 위젯은 홈 화면으로 제공되기 때문에 제한이 있습니다.
- 제스쳐 : 좌우 스와이프 기능이 제한됩니다. (대부분 홈화면은 ViewPager 형식의 네비게이션을 가지기 때문에 이벤트가 겹쳐서 제한됩니다.
- View : RemoteViews를 통해 제공되기 때문에 제한된 View만 사용가능합니다. (참고)
필수 설정
AppWidgetProviderInfo (참고)
위젯에 대한 갱신 주기, Layout, 크기 등 메타 데이터를 설명하며 XML로 정의합니다.
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/widget_covid"
android:configure="com.taetae98.widget.ui.activity.CovidWidgetConfigureActivity"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="360000"
android:minWidth="220dp"
android:minHeight="146dp" />
AppWidgetProvider (참고)
BroadcastReceiver를 상속받았으며 이벤트를 수신하여 처리할 수 있습니다.
@AndroidEntryPoint
class CovidWidgetProvider : AppWidgetProvider() {
@Inject
lateinit var covidStatusManager: CovidStatusManager
@Inject
lateinit var covidWidgetRepository: CovidWidgetRepository
companion object {
fun getLargeRemoteViews(context: Context, covidWidget: CovidWidget, covidStatusResponse: CovidStatusResponse): RemoteViews {
val format = NumberFormat.getInstance()
return RemoteViews(context.packageName, R.layout.widget_covid).apply {
setInt(R.id.layout, "setBackgroundColor", covidWidget.backgroundColor)
setTextColor(R.id.city_text_view, covidWidget.textColor)
setTextColor(R.id.total_title_text_view, covidWidget.textColor)
setTextColor(R.id.positive_title_text_view, covidWidget.textColor)
setTextColor(R.id.death_title_text_view, covidWidget.textColor)
setTextColor(R.id.total_text_view, covidWidget.textColor)
setTextColor(R.id.positive_text_view, covidWidget.textColor)
setTextColor(R.id.death_text_view, covidWidget.textColor)
setTextViewText(R.id.city_text_view, covidWidget.city)
setTextViewText(R.id.total_text_view, "${format.format(covidStatusResponse.body[covidWidget.city]?.totalPositive)}명")
setTextViewText(R.id.positive_text_view, "${format.format(covidStatusResponse.body[covidWidget.city]?.positive)}명")
setTextViewText(R.id.death_text_view, "${format.format(covidStatusResponse.body[covidWidget.city]?.death)}명")
}
}
private fun updateWidget(context: Context, covidWidget: CovidWidget, covidStatusResponse: CovidStatusResponse) {
AppWidgetManager.getInstance(context).updateAppWidget(
covidWidget.id, getLargeRemoteViews(context, covidWidget, covidStatusResponse)
)
}
suspend fun updateWidget(context: Context, appWidgetIds: IntArray, covidStatusResponse: CovidStatusResponse) {
appWidgetIds.forEach { id ->
AppDatabase.getInstance(context).covidWidgetDao().findById(id)?.let { widget ->
updateWidget(context, widget, covidStatusResponse)
}
}
}
}
override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
Logger.intent("CovidWidget", intent)
}
override fun onDeleted(context: Context, appWidgetIds: IntArray) {
super.onDeleted(context, appWidgetIds)
CoroutineScope(Dispatchers.IO).launch {
covidWidgetRepository.deleteByIds(appWidgetIds)
}
}
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
super.onUpdate(context, appWidgetManager, appWidgetIds)
covidStatusManager.onLatestCovidStatus().enqueue(
object : Callback<CovidStatusResponse> {
override fun onResponse(call: Call<CovidStatusResponse>, response: Response<CovidStatusResponse>) {
Logger.response("onLatestCovidStatus", response)
val covidStatusResponse = response.body() ?: return
CoroutineScope(Dispatchers.IO).launch {
updateWidget(context, appWidgetIds, covidStatusResponse)
}
}
override fun onFailure(call: Call<CovidStatusResponse>, t: Throwable) {
Logger.e("onLatestCovidStatus", t)
}
}
)
}
}
Layout
위젯의 Layout을 생성합니다. RemoteViews에서 제공하는 View만 사용가능합니다.
<?xml version="1.0" encoding="utf-8"?>
<GridLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout"
android:rowCount="3"
android:columnCount="3"
android:background="#80000000"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/city_text_view"
android:text="도시"
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold"
android:gravity="center"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_columnSpan="3"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/total_title_text_view"
android:text="총\n확진자"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
android:gravity="center"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:textColor="@color/white"/>
<TextView
android:id="@+id/positive_title_text_view"
android:text="일일\n확진자"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
android:gravity="center"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:textColor="@color/white"/>
<TextView
android:id="@+id/death_title_text_view"
android:text="사망자"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
android:gravity="center"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:textColor="@color/white"/>
<TextView
android:id="@+id/total_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:gravity="center"
android:text="0"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/positive_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:gravity="center"
android:text="0"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/death_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:gravity="center"
android:text="0"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold" />
</GridLayout>
Manifest
AppWidgetProvider가 BroadcastReceiver 기반이기 때문에 Manifest에 추가해야 합니다.
- 기본적으로 위젯에 업데이트를 받아야 하기 때문에 APPWIDGET_UPDATE Action을 추가합니다.
- AppWidgetProviderInfo를 연결하기 위해 meta-data를 추가합니다.
<receiver
android:name=".widget.CovidWidgetProvider"
android:exported="true"
android:label="@string/covid_widget" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/provider_covid_widget" />
</receiver>
예제코드 (Git)
https://github.com/KangTaeJong98/Example/tree/main/Android/Widget
'Android (안드로이드) > Widget' 카테고리의 다른 글
Android Widget - 위젯 이벤트 (0) | 2022.03.09 |
---|
Comments