EEltaCrew
블로그

홈 위젯 13개를 삼성 위젯 옆에 놓고 다시 고친 기준 7가지

게시 2026-09-16실측 기준 2026-09-15읽는 시간 약 3분elta · EltaCrew

앱 5개의 홈 위젯 13개를 실기기 홈 화면에 삼성 날씨·페이 위젯과 나란히 놓고 보니 "코드가 있다" 와 "상용 앱처럼 보인다" 는 전혀 달랐습니다. 시스템 다크 모드 추종, 빈 상태 디자인, previewLayout 과 label, dp 모서리, 비트맵 위젯의 테마 지연까지 고친 기준을 씁니다.

위젯은 앱 안이 아니라 남의 화면(홈)에 놓입니다. 그래서 잘 만들었는지는 앱 안에서가 아니라, 홈 화면에 삼성·구글 위젯과 나란히 놓고 봐야 압니다. 앱 5개의 위젯 13개(광고 수익 앱 3, 시험 디데이 6, 일출·일몰 2, 스크린타임 1, 반려동물 1)를 그렇게 놓고 보니 고칠 게 많았습니다.

1. 홈 화면의 다크 모드를 따른다

한 앱은 위젯이 앱 안의 테마 설정을 따르고 있었습니다. 홈이 다크인데 위젯만 밝은 판이 뜹니다. 위젯은 시스템 다크 모드를 따라야 합니다. values-night 리소스로 색을 분기하면 RemoteViews 가 알아서 골라 줍니다.

단, 비트맵으로 그리는 위젯(그래프, 달력 그리드)은 한계가 있습니다. 테마가 바뀌어도 다음 갱신(최대 30분)까지 옛 판이 남습니다. 이건 고칠 수 없는 한계라 알고 넘어갑니다.

2. 빈 상태·권한 없음 상태도 디자인한다

데이터가 없을 때 "데이터가 없습니다" 회색 한 줄만 두면 2×2 에서 잘립니다. 아이콘 + 제목 + 줄바꿈된 안내 한 줄로 만듭니다. 위치 권한이 없을 때, 아직 기록이 없을 때, 앱을 처음 깔았을 때 각각 어떤 화면인지 실기기에서 다 봐야 합니다.

3. previewLayout 과 리시버 label

위젯 피커에서 앱 아이콘만 덜렁 뜨는 앱이 있었습니다. android:previewLayout 이 없어서입니다. 그리고 한 앱의 위젯 6개가 피커에서 전부 「시험 디데이 위젯」이라는 같은 이름이었습니다. 리시버에 android:label 을 위젯마다 다르게 줍니다.

previewLayout 은 코드를 실행하지 않고 XML 만 그립니다. 실제 위젯 레이아웃을 그대로 지정하면 빈 값이 뜨므로, 예시 값을 박아 둔 미리보기용 사본 레이아웃을 따로 둡니다.

4. 빈 공간을 채운다, 앱 이름 머리줄은 뺀다

그리드 위젯은 항목 수에 맞춰 칸을 재배치하고, 리스트의 빈 줄은 「+ 추가」 점선으로 채웁니다. 4×2 는 보조 정보 줄(평일/주말 같은)을 둡니다. 숫자 위젯은 큰 숫자 하나 + 증감 색 알약 + 7일 막대 정도로 끝냅니다.

반대로 위젯 맨 위에 앱 이름을 머리줄로 넣지 않습니다. 삼성 위젯에는 그런 줄이 없고, 놓고 보면 "만든 티"가 그 줄에서 납니다.

5. 좌표 대신 지명

위치 기반 위젯에 위도·경도를 그대로 찍는 건 아무도 안 읽습니다. Geocoder 로 지명을 받아 캐시하고, 실패하면 「내 위치」로 둡니다.

6. 모서리는 dp 로, 여백은 비례로

모서리 반지름을 "슬라이더 40 = 반원" 식 비율로 계산했더니 큰 위젯에서 폭의 25%짜리 알약이 됐습니다. 모서리는 약 20dp 고정, 1×1 만 짧은 변의 22% 상한을 둡니다. 안쪽 여백도 고정 12px 로 두면 큰 카드에서 글자가 모서리에 붙습니다. 칸 크기에 비례시킵니다. 그리드에 항목이 하나뿐이면 배경 판 없이 카드만 둡니다. 판 위에 카드 하나는 테두리처럼 보입니다.

7. 미리보기 PNG 의 초승달

미리보기 이미지를 다크 배경 캡처에서 잘라 쓰면 모서리에 초승달 모양의 배경이 남습니다. 카드 반지름으로 다시 마스킹합니다. 다크용은 drawable-night-nodpi 에 따로 둡니다.

RemoteViews 가 허용하는 뷰만

빌드는 통과하는데 위젯이 아예 안 열리는 경우가 있었습니다. 레이아웃에 <View> 하나를 구분선으로 넣은 게 원인입니다. RemoteViews 는 허용된 뷰 클래스만 받고, 아닌 게 하나라도 있으면 위젯 전체가 로드되지 않습니다. 구분선은 ImageView 나 배경이 있는 FrameLayout 으로 대신합니다.

확인 방법

실기기(갤럭시 노트10, One UI) 홈에 위젯을 실제로 배치해서 라이트/다크, 실데이터/빈 상태 네 장을 다 봅니다. 배치를 자동화하면서 알게 된 것 하나: 위젯 설정(configure) 액티비티가 뜨면 「저장」을 눌러야 위젯이 남습니다. 안 누르고 홈으로 나가면 삭제됩니다.

두 앱(스크린타임, 반려동물)은 이 기준을 이미 충족해서 손대지 않았습니다.

정리

Android홈 위젯UIRemoteViews

함께 읽기

R8 을 켜고 빌드는 통과했는데 앱이 깨졌다: 15개 앱에서 실제로 걸린 런타임 함정 5가지Play 의 2027년 코드 최적화 요건에 맞춰 앱 15개에 R8 을 켰습니다. 빌드는 전부 통과했지만 7개 중 2개가 실행 중에 깨졌습니다. Gson 역직렬화, getIdentifier 리소스 조회, Room _Impl, 디버그 빌드의 무효화 등 크래시 로그에 안 잡히는 유형을 정리합니다.앱 안에서 언어를 바꿨는데 가끔 안 바뀌는 이유: setApplicationLocales 는 떠 있는 액티비티만 다시 만든다"한국어에서 English 로 바꿔도 그대로다, 껐다 켜야 바뀐다" 는 제보의 원인은 AppCompat 이 그 순간 화면에 떠 있는 액티비티만 재생성하기 때문이었습니다. 뒤에 멈춰 있던 화면은 옛 언어로 돌아옵니다. 앱 8개에 적용한 해결책과, 같이 걸린 함정 5가지를 씁니다.앱 17개에 강제 인앱 업데이트(IMMEDIATE)를 넣은 이유: 광고 SDK 교체 때 옛 버전 수익이 0 이었다2026년 7월 광고 SDK 를 갈아탔을 때, 업데이트를 안 받은 사용자에게서는 수익이 0 이었습니다. 정책 수정도 광고 수정도 옛 버전에는 닿지 않습니다. Play In-App Update 를 IMMEDIATE 로 전 앱에 넣은 방법, 검증이 Play 설치본에서만 되는 이유, 그리고 함께 처리한 것들을 씁니다.