# Android-виджеты для разработчика: размеры, прозрачность, обновление

Страница: https://soft4android.ru/realizaciya-android-vidzhetov-dizajn-proporcii-prozrachnost/
Суть: Как спроектировать виджет для Android: размеры в ячейках, адаптивная вёрстка, прозрачный фон и тёмная тема, жизненный цикл и частота обновления данных.

Главное:
- Проектируйте виджет под диапазон размеров, а не под одну ячейку конкретного телефона
- Фон, углы и цвета берите из системной темы — так виджет не будет чужим ни в светлой, ни в тёмной теме
- Обновляйте по событию и редко: частое обновление садит батарею и всё равно ограничивается системой


Хороший Android-виджет проектируется не под один экран, а под диапазон: вы задаёте минимальный и желаемый размер в ячейках, разрешаете растягивание и готовите несколько раскладок под разные размеры. Фон, скругления и цвета лучше брать из системной темы, чтобы виджет одинаково смотрелся в светлом и тёмном оформлении, а данные обновлять по событию и как можно реже — система всё равно ограничивает частые обновления. Ниже — основные решения по дизайну и архитектуре общими словами, без привязки к конкретной версии API.

## Как виджет устроен изнутри

Виджет не живёт внутри вашего приложения. Его рисует процесс рабочего стола (лаунчера), а приложение передаёт ему описание интерфейса в виде `RemoteViews`. Отсюда главные ограничения:

- доступен ограниченный набор элементов: текст, изображения, кнопки, списки, контейнеры-разметки; произвольные собственные View использовать нельзя;
- нажатия обрабатываются через `PendingIntent`: открыть экран, отправить broadcast, запустить сервис;
- нет постоянно работающего кода: виджет обновляется, когда вы отправляете ему новое описание.

Базовые части виджета:

1. Класс-наследник `AppWidgetProvider` — по сути, приёмник событий.
2. XML-описание в `res/xml` (`appwidget-provider`): размеры, превью, режим изменения размера, экран настройки.
3. Разметка виджета в `res/layout`.
4. Запись о приёмнике в манифесте.

Если вы только начинаете путь в разработке, сначала разберитесь с основами из статьи [разработка под Android](https://soft4android.ru/razrabotka-android-eto/). Для тех, кто пишет на Kotlin и Compose, есть библиотека Jetpack Glance: она позволяет описывать виджет в декларативном стиле, но под капотом всё равно формирует `RemoteViews` с теми же ограничениями.

## Размеры и пропорции

Рабочий стол — сетка ячеек, но размер ячейки в dp отличается от устройства к устройству и от лаунчера к лаунчеру. Поэтому задавайте в описании:

- минимальный размер (`minWidth`, `minHeight`) — меньше виджет не станет;
- минимальный размер при ручном изменении (`minResizeWidth`, `minResizeHeight`), если хотите разрешить сжатие сильнее стартового;
- в свежих версиях Android — желаемый размер в ячейках (`targetCellWidth`, `targetCellHeight`), который лаунчер использует при добавлении;
- `resizeMode` — по горизонтали, вертикали или в обе стороны.

Пример описания:

```xml
<appwidget-provider
    android:minWidth="110dp"
    android:minHeight="40dp"
    android:targetCellWidth="2"
    android:targetCellHeight="1"
    android:resizeMode="horizontal|vertical"
    android:updatePeriodMillis="0"
    android:previewLayout="@layout/widget_preview"
    android:initialLayout="@layout/widget_main" />
```

| Размер | Что уместно показывать | Чего избегать |
|---|---|---|
| 1×1 | Одно число, значок состояния, одно действие | Текст длиннее двух слов |
| 2×1 / 4×1 | Строка данных и одна-две кнопки | Несколько строк текста |
| 2×2 | Главная цифра плюс подпись, 2–4 кнопки | Списки |
| 4×2 и больше | Список, расписание, несколько блоков | Плотный текст мелким шрифтом |

Чтобы виджет оставался полезным при растягивании, подготовьте несколько раскладок и выбирайте подходящую по фактическому размеру. Размер приходит в `onAppWidgetOptionsChanged`, а в свежих версиях можно передать системе набор `RemoteViews` под разные размеры, и она сама выберет нужный. Простое правило: при уменьшении сначала прячьте второстепенное (подписи, вторичные кнопки), а главную информацию оставляйте до последнего.

## Прозрачность, углы и тёмная тема

Прозрачный виджет хорошо смотрится на однотонных обоях и плохо — на пёстрых. Варианты решения:

- **Полупрозрачная подложка** вместо полной прозрачности: текст читается на любых обоях.
- **Настройка в приложении**: дайте пользователю выбрать уровень прозрачности на экране настройки виджета.
- **Системные цвета.** В свежих версиях Android виджеты могут брать динамические цвета из обоев. Используйте атрибуты темы, а не жёстко заданные цвета, тогда виджет автоматически подстроится под светлую и тёмную тему.
- **Скругление углов.** Берите системный радиус, если он доступен, иначе виджет будет выделяться острыми углами среди соседей. Внутренние элементы скругляйте с меньшим радиусом, чем внешний контур.

Для тёмной темы держите отдельные ресурсы цветов (`values-night`) и проверяйте контраст текста. Белый текст на прозрачном фоне при светлых обоях становится нечитаемым — это самая частая жалоба на виджеты.

## Жизненный цикл и обновление данных

Основные события `AppWidgetProvider`:

- `onEnabled` — добавлен первый экземпляр виджета, можно подготовить общие ресурсы;
- `onUpdate` — пора обновить экземпляры (по расписанию или при добавлении);
- `onAppWidgetOptionsChanged` — изменился размер;
- `onDeleted` — удалён конкретный экземпляр, почистите его настройки;
- `onDisabled` — удалён последний экземпляр, отмените фоновую работу.

Про частоту обновления. Значение `updatePeriodMillis` система не выполняет чаще, чем раз в 30 минут, и при этом будит устройство. Надёжнее схема «по событию»: обновлять виджет, когда изменились данные внутри приложения, а периодическую загрузку из сети выполнять через WorkManager с разумным интервалом и ограничениями (например, только при наличии сети). Пользователи замечают виджеты, которые садят батарею, — и удаляют их вместе с приложением. Как они это обнаруживают, видно из статьи о [приложениях, которые расходуют батарею](https://soft4android.ru/otchyot-10-samyx-prozhorlivyx-prilozhenij-dlya-android/).

Не забывайте, что каждый экземпляр виджета имеет свой ID и может быть настроен по-своему: храните настройки по ID и обновляйте только нужные экземпляры.

## Экран настройки и превью

Экран настройки (`configure` в описании) открывается при добавлении виджета. Делайте его коротким: одно-два решения, разумные значения по умолчанию. В свежих версиях можно разрешить пропустить настройку и вернуться к ней позже.

Превью в списке виджетов — первое, что видит пользователь. Сделайте его похожим на реальный виджет с правдоподобными данными: по пустому серому прямоугольнику никто не поймёт, зачем его добавлять. Как пользователь вообще находит и добавляет виджеты, описано в статье [как установить виджет на Android](https://soft4android.ru/kak-ustanovit-vidzhet-na-android-ustrojstvo-planshet-smartfon/).

## Типичные ошибки

- Виджет не помещается в 2 ячейки на компактных экранах — тестируйте минимальный размер на маленьком устройстве и с крупным шрифтом.
- Текст жёстко белого цвета — нечитаем на светлых обоях.
- Пустое состояние без подсказки — покажите, что сделать: войти, выбрать список, дать разрешение.
- Приложение разрешено ставить на карту памяти — виджеты таких приложений рабочий стол может не увидеть. Подробнее с точки зрения пользователя — в статье [пропали виджеты после обновления](https://soft4android.ru/propali-vidzhety-prilozhenij-posle-obn-3-03-2017/).

## Коротко: что сделать

- Задайте минимальный и желаемый размер и разрешите растягивание.
- Подготовьте раскладки под малый и большой размер.
- Используйте цвета и радиусы из системной темы, проверьте тёмную тему.
- Обновляйте по событию, а фоновые загрузки делайте через WorkManager.
- Сделайте понятное превью и короткий экран настройки.

## Частые вопросы

### Можно ли использовать в виджете любые свои View?

Нет. Виджет отображается в процессе рабочего стола через `RemoteViews`, а там поддерживается только ограниченный набор стандартных элементов разметки и представлений. Сложную графику обычно рисуют в растровое изображение и передают в `ImageView`, но это увеличивает объём данных и расход памяти, поэтому пользуйтесь таким приёмом осторожно.

### Как обновлять виджет чаще, чем раз в полчаса?

Через `updatePeriodMillis` не получится, система ограничивает минимальный интервал. Обновляйте виджет по событию из приложения или по сообщению с сервера, а для периодической работы используйте WorkManager. Но сначала подумайте, нужна ли такая частота: пользователь редко смотрит на виджет чаще, чем раз в несколько минут.

### Стоит ли переходить на Jetpack Glance?

Если проект уже на Kotlin и Compose, Glance упрощает код виджета и делает его привычнее для команды. Ограничения при этом остаются прежними, потому что результат всё равно превращается в `RemoteViews`. Для небольшого существующего виджета на XML переписывание ради одной библиотеки обычно не окупается.

### Как сделать прозрачность, которую выбирает пользователь?

Добавьте выбор уровня прозрачности на экран настройки виджета, сохраните значение по ID экземпляра и при каждом обновлении задавайте фон с нужной альфой через `RemoteViews`. Хорошая практика — значение по умолчанию с полупрозрачной подложкой, чтобы текст читался на любых обоях сразу после добавления.

