Статьи

Создайте собственный виджет часов: дизайн часов

Разработка виджетов для платформы Android включает несколько иной набор задач, чем разработка стандартных приложений. В этой серии руководств мы будем работать над процессом разработки настраиваемого виджета аналоговых часов. Часы будут основаны на классе Android AnalogClock и настроены с вашей собственной графикой.


В этой серии руководств мы разрабатываем настраиваемый виджет аналоговых часов для Android с использованием класса AnalogClock и пользовательской графики. В первой части серии мы создаем проект, готовим файл Manifest и другие ресурсы. В этой части мы будем работать над дизайном виджета. Это будет включать создание графики для часового циферблата и стрелок, а также реализацию макета в XML. Мы будем создавать графику для устройств различной плотности. В заключительной части серии мы собираемся реализовать возможность выбора пользователем дизайна часов, поэтому здесь мы создадим три варианта дизайна.

Это вторая часть нашей серии статей о создании настраиваемого виджета аналоговых часов для Android в течение четырех уроков:

Виджет Android AnalogClock использует три изображения: циферблат часов, минутную стрелку и часовую стрелку. Поэтому мы создадим три элемента дизайна для каждой версии виджета часов, которую мы хотим, чтобы пользователи могли выбирать между. Мы также создадим альтернативные варианты оформления с помощью циферблата, часовой и минутной стрелок. Для этого проекта нам нужно настроить таргетинг на разные плотности экрана устройства, для чего мы будем создавать файлы изображений в четырех разных масштабах.


Мы собираемся создать три дизайна часов, каждый с циферблатом, минутной стрелкой и часовой стрелкой. Вы, конечно, можете использовать свои собственные дизайны вместо этого, но не стесняйтесь использовать файлы изображений, которые мы используем здесь, чтобы начать. Файлы изображений для каждого дизайна в каждой плотности включены в ссылку для загрузки этого учебного пособия, а также будут включены в загрузку для части 4.

Сначала идет циферблат часов. Помните, что мы указали виджет в виде двух ячеек шириной и двух ячеек, что привело к максимальному размеру 146 dp (пикселей, не зависящих от плотности). Для этого урока мы создадим четыре версии каждого изображения в соответствии с четырьмя категориями плотности.

Вместо того, чтобы создавать изображения для каждой плотности, вы можете альтернативно использовать графику NinePatch , которая является растровым изображением, которое можно масштабировать вверх и вниз в соответствии с плотностью устройства, что позволяет вам создавать одно изображение для каждого дизайна. Возможность использования NinePatch частично зависит от содержания используемых вами дизайнов, но есть инструменты, которые помогут вам создать их, если вы хотите.

Проще всего начать со средней плотности, которая должна составлять максимум 146 пикселей по обеим осям. Вот часовой циферблат по умолчанию, который мы используем при средней плотности, который вы можете использовать либо в качестве справочного материала для ваших собственных дизайнов, либо, если вы не хотите создавать свой собственный позже.

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

Вот две альтернативные конструкции циферблата часов, которые мы будем использовать: каменная и другая металлическая, которые представлены здесь со средней плотностью:

Создав циферблат часов, вы можете создавать альтернативные версии каждого изображения для разных плотностей. В зависимости от ваших дизайнов в этом может не быть необходимости, но мы будем включать адаптированные версии каждого изображения для дизайнов в этом руководстве. Ниже указан максимальный размер, который мы используем для нашего виджета по осям X и Y при каждой плотности:

  • Низкая плотность: 110px
  • Средняя плотность: 146 пикселей
  • Высокая плотность: 220px
  • Очень высокая плотность: 292 пикселей

Если у вас есть файлы изображений для каждой конструкции циферблата, которую вы хотите использовать (и версии для каждой плотности, если необходимо), скопируйте их в доступные для рисования папки в рабочей области проекта виджета Android. Eclipse обычно создает папку для каждой категории плотности автоматически, но, если вы используете только одно изображение для всех плотностей, вы можете создать папку просто с именем «drawable» и поместить туда изображение. Папки для каждого уровня плотности:

  • Низкий: drawable-lpdi
  • Средний: drawable-mpdi
  • Высокий: drawable-hpdi
  • Очень высокий: drawable-xhpdi

Android AVD Manager позволит вам протестировать готовый проект виджета на каждой из этих плотностей. После того, как ваши изображения будут сохранены в различные папки для рисования, убедитесь, что вы использовали одинаковые имена в каждой из них. Например, один из дизайнов циферблата, который мы используем, называется «clock_dial_stone» — это имя файла изображения для каменного циферблата в каждой папке плотности, хотя содержание каждой версии отличается, если только по размеру. Если вы все еще сомневаетесь в том, как это должно работать, просто загрузите файлы изображений, используя ссылку для загрузки в верхней части этого руководства, и просмотрите папки, чтобы получить представление.


Затем создайте изображение для часовой и минутной стрелок виджета часов, включая изображения для каждого дизайна и каждой плотности, на которую вы нацеливаетесь. Вот наши минутные стрелки средней плотности для каждого дизайна:

Опять же, не стесняйтесь использовать их, чтобы начать или работать самостоятельно. Обратите внимание, что эти файлы изображений содержат прозрачное пространство вокруг руки. Вам необходимо создать каждое из ваших изображений рук с полной высотой циферблата, с которым они будут использоваться. Каждая стрелка должна быть в точном положении, в котором она была бы, если указывать на двенадцать, располагаться над изображением циферблата и на полпути через него. Стрелка также должна находиться в центре файла изображения по горизонтали, поскольку при отображении времени она будет поворачиваться от своей центральной точки. Длина стрелок в файле изображения действительно зависит от вас, если полная высота изображения равна высоте изображения циферблата.

Следующая диаграмма показывает полную шкалу изображений стрелок с минутной стрелкой в ​​двенадцать и часовой стрелкой в ​​три (часовая стрелка была повернута на 90 градусов по часовой стрелке в ее центральной точке):

После того как у вас отсортированы дизайны минутных стрелок, снова сохраните один для каждой плотности, масштабируя их вверх и вниз, чтобы соответствовать высоте циферблата в каждом случае. Скопируйте их снова в свои папки для рисования, используя одно и то же имя для каждого дизайна в папках плотности, как и в изображениях набора.

Затем выполните тот же процесс для ваших часовых стрелок. Вот часовые стрелки для трех конструкций, которые мы используем:

Принцип здесь тот же, что и для минутных стрелок, за исключением того, что часовые стрелки обычно должны быть короче. Создайте свои часовые стрелки, указывающие на 12 часов, и подготовьте версии для каждой плотности, копируя их в свои папки для рисования, как вы делали для минутных стрелок.


В дизайне виджета будут использоваться некоторые данные, которые мы включим в папки «значений» нашего проекта. В Android API 14 и более поздних версиях система автоматически включает поля между виджетами, когда они отображаются на домашнем экране пользователя. Однако в предыдущих версиях API это было не так. По этой причине мы хотим указать поле для включения круглосуточного виджета на устройствах с уровнями Android ниже 14. Это тот случай, когда мы можем использовать тот факт, что у нас есть папки значений, предназначенные для этих двух категорий уровней пользовательского API.

Мы определим поля в нашем файле макета XML, ссылаясь на ресурс измерения. В каталоге «values» создайте новый файл с именем «sizes.xml» — выберите папку «values» в Eclipse и щелкните правой кнопкой мыши или выберите «Файл», затем «Новый», «Файл» и введите имя файла.

Когда вы нажмете кнопку «Готово», Eclipse создаст и откроет файл. Выберите вкладку «sizes.xml» для редактирования кода. Введите следующее:

1
2
3
<resources>
<dimen name=»clock_margin»>8dp</dimen>
</resources>

Этот код просто перечисляет значение измерения с использованием независимых от плотности пикселей вместе с именем, чтобы мы могли ссылаться на него в другом месте.

Сохраните файл. Теперь скопируйте его, щелкнув правой кнопкой мыши в папке «values» или выбрав его и выбрав «Edit» — затем выберите «Copy». Вставьте его в папку «values-v14», которую мы создали в прошлый раз — щелкните правой кнопкой мыши или выберите папку и выберите «Изменить», затем выберите «Вставить». Файл появится в папке «values-v14», которая предназначена для уровней API начиная с 14. Откройте эту новую копию файла и отредактируйте значение измерения, чтобы указать нулевое поле следующим образом:

1
2
3
<resources>
<dimen name=»clock_margin»>0dp</dimen>
</resources>

Теперь, когда макет XML ссылается на это значение измерения, используя его имя, нулевое значение будет использоваться на устройствах, работающих под управлением API 14 плюс, а значение 8dp будет использоваться в противном случае.


Теперь давайте определим наш виджет в XML. Помните, что мы указали начальный макет виджета в файле XML, в котором мы определили его основные свойства. Макет, на который мы ссылались, был «clock_widget_layout», поэтому создайте этот файл сейчас. Щелкните правой кнопкой мыши или выберите папку с «макетом» и выберите «Файл», затем «Новый», «Файл». Введите «clock_widget_layout.xml» в качестве имени файла и нажмите «Готово».

Выберите вкладку «clock_widget_layout.xml», когда Eclipse откроет файл, чтобы вы могли редактировать XML. Мы используем Относительную компоновку для нашего виджета — если вы хотите использовать другой дизайн, вы можете альтернативно использовать либо линейную, либо рамочную компоновку, поскольку они являются единственными поддерживаемыми виджетами. Чтобы использовать Относительный макет, добавьте следующую схему в файл XML-макета:

1
2
3
4
5
6
7
8
9
<RelativeLayout
    xmlns:android=»http://schemas.android.com/apk/res/android»
    android:id=»@+id/custom_clock_widget»
    android:layout_width=»fill_parent»
    android:layout_height=»fill_parent»
    android:padding=»@dimen/clock_margin»
    android:gravity=»center»>
  
</RelativeLayout>

Здесь мы указываем идентификатор для виджета, который мы будем использовать для реализации кликов по нему в нашем Java-коде в части 4. Обратите внимание, что код также ссылается на значение измерения, которое мы создали, используя стандартный синтаксис — имя «измерений» .xml «файл на самом деле не имеет значения, вам просто нужно перечислить элемент» измерения «в файле значений, чтобы ссылаться на него таким образом.

Внутри Относительного макета добавьте свой виджет AnalogClock следующим образом:

1
2
3
4
5
6
7
8
<AnalogClock
    android:id=»@+id/AnalogClock0″
    android:layout_width=»wrap_content»
    android:layout_height=»wrap_content»
    android:dial=»@drawable/clock_dial»
    android:hand_hour=»@drawable/clock_hour_hand»
    android:hand_minute=»@drawable/clock_minute_hand»
/>

Это стандартный элемент Android Analog Clock, который позволяет настроить дисплей. Мы используем атрибут ID, чтобы мы могли ссылаться на виджет в Java. Последние три атрибута определяют доступные для рисования ресурсы, которые мы создали для циферблата, минутной и часовой стрелок. Если вы сохранили свои файлы под разными именами, измените этот код, чтобы отразить их. Android выберет файл для рисования из соответствующей папки плотности на каждом пользовательском устройстве.

Поскольку мы разрешаем пользователям выбирать дизайн, мы фактически собираемся включить все три дизайна в наш XML, установив все, кроме одного, изначально невидимыми. Убедитесь, что вы включили первый дизайн, который вы хотите отобразить по умолчанию, а затем добавьте остальные следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
<AnalogClock
    android:id=»@+id/AnalogClock1″
    android:layout_width=»wrap_content»
    android:layout_height=»wrap_content»
    android:dial=»@drawable/clock_dial_stone»
    android:hand_hour=»@drawable/clock_hour_hand_stone»
    android:hand_minute=»@drawable/clock_minute_hand_stone»
    android:visibility=»invisible»
/>
<AnalogClock
    android:id=»@+id/AnalogClock2″
    android:layout_width=»wrap_content»
    android:layout_height=»wrap_content»
    android:dial=»@drawable/clock_dial_metal»
    android:hand_hour=»@drawable/clock_hour_hand_metal»
    android:hand_minute=»@drawable/clock_minute_hand_metal»
    android:visibility=»invisible»
/>

Опять же, измените отображаемые имена, чтобы они соответствовали названиям циферблатов, минут и часовых стрелок для каждого из ваших дизайнов. Вы можете включить более трех дизайнов, если хотите — убедитесь, что у всех, кроме одного, видимость установлена ​​на невидимость, так что изначально отображается только один дизайн (опция по умолчанию). Мы сможем реализовать выбор пользователя между этими проектами в Java, используя атрибуты идентификатора элемента Analog Clock, которые заканчиваются целыми числами, начинающимися с нуля и увеличивающимися с каждым проектом. Сохраните файл макета.

Вот скриншоты того, как каждый из наших дизайнов будет выглядеть, когда виджет будет завершен:


На этом процесс разработки нашего виджета часов завершен. Если вы не хотите создавать свои собственные изображения дизайна на этом этапе, просто сначала используйте изображения в папке загрузки. В следующем уроке мы будем использовать класс AppWidgetProvider для реализации нашего виджета на Java. В заключительной части серии мы будем реализовывать пользовательские клики на виджете, представляя выбор между дизайнами и обновляя пользовательские настройки, чтобы непрерывно отображать выбранную ими опцию.