Delphi пишем для android

Delphi XE5 + Android: первые впечатления

Возвращение к истокам

Delphi XE5 я взял в руки по случаю конкурса «Осенняя Мобилизация». Идея (и возможность) писать под Андроид не на си-шарпе или яве, а на знакомом вдоль и поперёк паскале мне определённо понравилась. Расскажу тут о своих впечатления, проблемах, которые встретились, а также развенчаю некоторые «городские легенды».

Использовал триал-версию Update-1. Теперь уже вроде второй апдейт вышел и, возможно, что-то поменялось. Сразу замечу, что менять в установке настройки по умолчанию лучше не стоит. Установленный до этого Андроид-SDK прицепить к Делфи не удалось, поэтому ставил заново с тем, который к ней прилагается. После первого запуска выяснилось, что не работает Хелп. Нашёл решение
support.embarcadero.com/article/43035

Хелп оказался толковый и довольно подробный. Содержит не только свойства и методы, но и примеры и даже описание методик разработки. В общем, возвращение к истокам, как оно было ещё у Борланда.

Cама среда мне очень нравится. В Визуал Студио всё какое-то аморфное и невнятное. Юнити визуально неплох, но там совсем другая специфика. Короче – язык программиста всё равно не опишет то, что видит глаз эстета, даже если они принадлежат одному человеку…

Интерфейс пользователя

FireMonkey порадовал своей гибкостью. На любой контрол можно повесить другой, на тот ещё один, и так далее, достигая очень интересных результатов. По сравнению с VCL стандартизовано именование свойств. Никаких больше Caption’ов и прочего, если где-то есть текст – это всегда Text. Позиция – всегда Position. Масса способов выравнивания. Кроме того, есть TLayout – нечто «невещественное» (об этом будет и ниже), невидимое, на что можно положить контролы и выравнивать их «в пустоте», а не обязательно на какой-нибудь панели.

Когда много всего на форме, становится очень полезным свойство DesignVisible – скрыть в дизайн-тайме. Набор стилей для Андроида прилагался только один, но очень элегантный – белым по чёрному, как мне нравится.
В инете ходят слухи, что ссылки на стиль для контрола (StyleLookup) иногда «не сохраняются». Для многих типов контролов (а может и для всех) существует для каждого своя ссылка «по умолчанию», которая будет назначена, даже если не указана, и которая-то и не сохраняется, как я понимаю, для экономии места в ресурсе формы.

Контролу можно добавить анимацию, и даже несколько, и даже одновременно. И это не только перемещение по экрану, но и изменение любых вещественно-численных свойств (размеров, цвета, масштаба и т.д.). Для каждой анимации можно указать временную задержку её начала, что очень удобно в сложных случаях, т.к. можно обойтись без дополнительных таймеров, просто запустив все нужные анимации одновременно из одного блока кода.

Теперь о жестах. В принципе всё просто – назначаем контролу Touch.GestureManager, галочками помечаем интересующие жесты, назначаем искусственное расширение границ ловли жестов (если контрол мелкий) в TouchTargetExpantion, создаём для него событие OnGesture и ловим там по EventInfo.GestureID нужный жест. Но есть тонкости.

Например, на большом TLayout мы разместили какие-то мелкие (относительно него) контролы и независимо от того, насколько «попал» пользователь пальцем по этим контролам своим жестом, надо что-то там делать. Замечу – если всё описанное в абзаце выше сделано для этого TLayout, то мы поймаем только те жесты, начало которых приходится на «видимые» объекты – т.е. на один из тех самых мелких контролов. Это я определил экспериментально. В принципе ничего удивительного – лайоута-то как бы и нет, он невидим и виртуален, и все «экранные сообщения», которые он может получить – от положенных на него «видимых» объектов. Можно сделать по-другому — не лениться, назначить менеджера и создать событие для формы (как и делается в демках) и гарантированно его всегда получать – но тогда придётся вручную разбираться с координатами, чтобы определить, к какому контролу какой жест относится.

Читайте также:  Просмотрщик png для андроид

Ещё именно под Андроидом я бы настоятельно порекомендовал явно проверять GestureID каждого пойманного жеста и реагировать только на те, которые интересуют (независимо от того, какие жесты помечены галочками).

И пример. Долго не мог сообразить, как показать баннер в TWebBrowser. Решение нашёл на одном форуме и творчески переработал. Но, если быть уж совсем точным, не до конца. Практикующие перфекционисты могут поразвлечься и этот недочёт поискать. Однако код при этом абсолютно рабочий и именно его я использую:

HTML тут – это код этого самого банера.

Базы данных

В XE5 включён набор компонентов для универсального доступа к базам данных – FireDAC. В принципе все названия свойств и методов как у других аналогичных наборов, так что тут всё ясно. Я использовал его для общения с SQLite. Всё настолько просто и обычно, что даже не знаю, что рассказать. К тому же и не помню ничего – в это время смотрел что-то по медиаплейеру, руки сами всё сделали.

Чтобы почувствовать разницу, желающие могут для сравнения после FireDAC сделать что-нибудь с базой данных из программы на той же Юнити. Да ладно Юнити, она игровая, – вон из той же Визуал Студии. После этого начинаешь понимать, где пули свистят, а где туземки коктейли разносят…

Ну и для любителей делать всё своими руками приведу небольшой пример, как заполнять ListBox без Bindings:

Кроме всего прочего, в зависимости от кода в столбце d_result в строчку лист-бокса помещается та или иная картинка:

Главное, что тут не забыть – это aList.AddObject(aItem);

Ну и Next, конечно, чтобы не зависло.

Манипуляции с формами

То, к чему приучает Делфи – это каждому действию свою форму. Под Андроидом в ней можно точно так же, как и под Виндоуз, создавать, показывать и закрывать формы. Каждая новая так или иначе созданная и показанная форма будет как бы «модальной», т.е. закрывающей всё пространство приложения. Однако Form.ShowModal делать не следует (Андроид этого «не понимает»), а следует по старинке просто вызывать Form.Show. По системной кнопке Back автоматом вызывается Form.Close и самая верхняя на данный момент форма закрывается. Можно её потом опять использовать. При закрытии главной (первой) формы приложение, как и следовало ожидать, закрывается. Замечу, что не следует закрывать форму с параметром caFree либо явно её уничтожать (Free, Release) – не любит Андроид этого!

Читал в инете про проблемы у людей с ARC. Уверен, дело не в этом. Если всё правильно спроектировано, то вообще без разницы, считаются ссылки или нет, ходит там сборщик мусора с косой по расписанию как в .Net или уничтожается сразу как в Delphi. Я всё писал по-старинке:

и работало как часы и под Андроидом, и под Виндами.

Если же возникают какие-либо проблемы с пониманием этого процесса, без всякого стёба рекомендую немного пописать на си-шарпе. Там вообще деструкторы явно вызывать не принято, просто или выходишь из процедуры, где данный объект был локальной переменной, или присваиваешь (глобальной) переменной значение null. Через некоторое время уже спинным мозгом начинаешь чувствовать момент, когда ладьи с объектами отправляются в Вальгаллу, причём безо всякого с твоей стороны толчка.

Массивы

При разработке под мобильный компилятор в руководстве по адаптации кода сказано «не использовать статические массивы». Указано также одно исключение – когда статический массив является членом структуры. И всё. Не совсем ясно, относится ли это к константам-массивам. Например, таким как

Не исключено, что так делать можно, хотя я такого старался избегать и формировал массивы строк в initialization динамически. В си-шарпе там хоть это можно в описании делать… Короче, вопрос требует дальнейшего исследования и разъяснения.
Следует также помнить, что элементы строки (string) в мобильном компиляторе нумеруются с нуля.

Читайте также:  Infinite painter полная версия для андроида

Операторы

Появился (уж не знаю в какой версии) новый оператор

Похоже, все языки стремятся к общему знаменателю. Кстати, перебирать им в паскале можно не только массивы, но и множества.

Источник

Разработка кроссплатформенных мобильных приложений в Delphi #3

Часть #1
Часть #2

Настройка среды и создание нового мобильного приложения.

В предыдущей части цикла мы определились с задачей и создали простейшее FM приложение, которое отображает список рецептов. При этом мы использовали библиотеку доступа к данным FireDAC и технологию связывания объектов LiveBinding. Также мы условились, что в рамках поставленной задачи будет создано два приложения, использующих единую кодовую базу. И теперь, настало время для, возможно, самой интересной части – создания первого Android приложения.

Прежде всего, необходимо произвести настройку среды. Если при установке RAD Studio вы не устанавливали инструменты разработки Android (JDK/SDK/NDK), то вам следует сделать это вручную. Так же необходимо установить USB драйвер для того Android устройства, с помощью которого будет производиться разработка приложения. Стоит отметить, что далеко не для всех Android устройств можно найти USB драйвер. В таком случае можно воспользоваться возможностью отладки через Wi-Fi.

При создании нового проекта нам предлагается воспользоваться одним из нескольких шаблонов мобильного приложения. Выберем шаблон Header/Footer, представляющий собой мобильную форму с двумя панелями инструментов (Toolbar). После выбора шаблона необходимо сохранить проект. Новый проект удобнее всего создавать с помощью Project Manafer (правая верхняя панель IDE), как это показано на рисунке. Таким образом, мы сможем работать сразу с двумя проектами в группе.

Главная форма приложения для выбранного нами шаблона по умолчанию адаптирована под устройство Google Nexus 4. С помощью выпадающего списка в правой верхней части дизайнера формы можно выбрать другое устройство. Для нашего приложения выберем одно из наиболее популярных планшетных устройств Google Nexus 7. Сразу же изменим и текст заголовка на главной форме (свойство Text компонента HeaderLabel).

Первый запуск приложения

Как вы уже поняли, для отладки приложения мы будем использовать физическое устройство, подключенное по USB. Хотя возможны и другие варианты (подключение с помощью Wi-Fi или использование эмулятора). Если вы подключили свой планшет или телефон в соответствии с инструкцией и активировали режим разработчика, то название вашего «девайса» появится в списке целевых устройств (Targets). Активируем его.

Еще раз убедитесь в том, что Android SDK настроен для вашего устройства, а т. н. «режим разработчика» активирован. Подробно весь процесс настройки среды для разработки Android приложения описан здесь.

Запускается мобильное приложение точно так же, как и обычное «настольное» (нажатием клавиши F9). Если вы все сделали правильно, то после компиляции вы увидите главную форму приложения на своем планшете.

Теперь попробуем реализовать тот же функционал, который мы реализовали в предыдущей части. Для этого добавим в текущий проект уже существующий модуль данных из предыдущего проекта (меню Project | Add to Project…). Как и в первом проекте, модуль надо включить в секцию Uses главной формы.

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

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

Главная форма приложения

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

Читайте также:  Wps office premium для андроид без рекламы

В нашем случае мы вполне можем организовать интерфейс главной формы мобильного приложения по образу «настольного» (на самом деле, интерфейс Windows приложения мы строили с учетом того, что нам придется делать мобильное приложение). Поместим на форму компоненты TPanel, TSplitter и TCalloutPanel. В Object Inspector поменяем их свойства следующим образом:

Для отображения списка рецептов мы точно также используем TListBox и TBindNavigator, которые расположим на левой панели. TTabControl расположим на компоненте TCalloutPanel и настроим для каждого из компонентов свойство Align.

Как и в прошлый раз, используем механизм LiveBinding для подключения набора данных. Данная процедура полностью аналогична той, которую мы проделали в предыдущей части, создавая «настольное приложение».

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

Создадим новую мобильную форму. На ней поместим панель, и уже на панели разместим те элементы управления, которые мы размещали на форме добавления рецепта в прошлый раз (TEdit и две кнопки). Значение свойства Align – alCenter. Для кнопок зададим значение свойства ModalResult (mrOk и mrCancel).

Для класса формы создадим следующий метод класса:

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

Данная форма будет вызываться при каждом добавлении записи в набор данных FDTRecipe.

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

Развертывание (deployment) Android приложения

Перед тем, как запустить приложение, работающее с БД на Android, следует сделать определенные настройки, которые позволят перенести базу данных на мобильное устройство, и дадут возможность приложению «увидеть» базу. Для этого следует использовать Deployment Manager (меню Project |Deployment).

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

Для того, что бы при развертывании приложения на устройство переносилась и база данных, следует воспользоваться кнопкой «Add files» (добавить файлы) и выбрать файл базы данных.

Введите assets\ в качестве значения поля Remote Path, а значение поля Platform установите Android. Директория assets это специальная директория, предназначенная для хранения вспомогательных ресурсов приложения. В поле Platform следует выбрать Android.

Вы можете нажать кнопку Deploy, что бы протестировать процесс развертывания приложения.

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

Директива компилятора <$IFDEF ANDROID>передается для того, что бы данный код выполнялся только на Android устройствах. Таким образом, мы указываем приложению относительный путь к БД.

Запускаем приложение, и на экране устройства получаем практически полный аналог Windows приложения, которое мы создали в предыдущей части.

В этой части мы построили первое мобильное приложение и разобрались с тем, насколько процесс создания мобильных приложений в Delphi схож и насколько он отличается от процесса создания «обычного» desktop приложения. Естественно, пока мы реализовали только базовый функционал. Это касается как логики программы, так и ее интерфейса. Но, всему свое время. В следующей части мы продолжим работу над Windows приложением и более углубленно познакомимся с возможностями и принципами работы механизма LiveBinding.

Источник

Оцените статью