Разработка интерфейсов для мобильной платформы 1С имеет свои уникальные особенности, с которыми программисты не сталкиваются при работе на настольных компьютерах. Одна из наиболее распространенных и неприятных проблем — это программная активация поля ввода и вызов виртуальной клавиатуры. В настольной версии достаточно просто переопределить свойство формы ТекущийЭлемент. Однако на мобильных устройствах под управлением Android или iOS этот механизм часто дает сбой, особенно когда требуется вернуть фокус в поле ввода после того, как пользователь переключился на другой элемент формы.
В рамках этой статьи мы подробно разберем, почему возникает данная проблема, проанализируем внутренние механизмы мобильной платформы 1С и рассмотрим два проверенных, рабочих способа гарантированного возврата фокуса в целевое поле ввода.
При работе в обычном тонком или веб-клиенте на ПК для перевода фокуса достаточно написать простую строку кода:
ЭтаФорма.ТекущийЭлемент = Элементы.ПолеВвода1;
На мобильной платформе этого действия недостаточно. Сенсорный интерфейс требует не просто подсветить рамку поля, но и инициировать появление экранной клавиатуры. Специально для этих целей, начиная с версии платформы 8.3.9, разработчики 1С добавили специализированный метод НачатьРедактированиеЭлемента().
Казалось бы, идеальная схема при открытии формы должна выглядеть следующим образом:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ЭтаФорма.ТекущийЭлемент = Элементы.ПолеВвода1;
#Если МобильноеПриложениеКлиент Тогда
ЭтаФорма.НачатьРедактированиеЭлемента();
#КонецЕсли
КонецПроцедуры
Этот код отлично отрабатывает при первом открытии формы. Но стоит пользователю перевести фокус на другое поле (например, для заполнения количества товара), а затем программно или вручную попытаться вернуть курсор в первое поле (например, в поле ввода штрихкода) — фокус пропадает. Платформа визуально игнорирует команды ТекущийЭлемент и НачатьРедактированиеЭлемента(), клавиатура не появляется, а курсор не возвращается на место.
Выясним причины такого поведения. Дело в том, что в мобильной платформе обновление экрана и перерисовка элементов интерфейса не происходят мгновенно в процессе выполнения текущего кода. До завершения работы всех активных обработчиков событий формы экран мобильного устройства заблокирован для обновления. Когда мы пытаемся переключить фокус внутри события ПриИзменении другого поля, мобильная платформа еще не успевает обработать изменения старого элемента, что приводит к внутреннему конфликту состояний фокуса.
---
Наиболее надежный и классический способ обойти ограничение платформы — это вынос вызова метода НачатьРедактированиеЭлемента() в асинхронный поток выполнения. Для этого мы задействуем системный механизм 1С — обработчики ожидания.
Разберем по шагам реализацию этого метода:
ТекущийЭлемент.Посмотрим на практический пример реализации кода в модуле управляемой формы:
&НаКлиенте
Процедура ВернутьФокусВПолеВвода()
// 1. Указываем платформе, какой элемент мы хотим сделать активным
ЭтаФорма.ТекущийЭлемент = Элементы.ПолеВвода1;
// 2. Подключаем обработчик ожидания для мобильного клиента
#Если МобильноеПриложениеКлиент Тогда
// Важно: третий параметр "Однократно" должен быть равен Истина!
ПодключитьОбработчикОжидания("НачатьРедактированиеТекущегоЭлемента", 0.1, Истина);
#КонецЕсли
КонецПроцедуры
&НаКлиенте
Процедура НачатьРедактированиеТекущегоЭлемента()
#Если МобильноеПриложениеКлиент Тогда
// 3. Непосредственно активируем ввод и вызываем клавиатуру
ЭтаФорма.НачатьРедактированиеЭлемента();
#КонецЕсли
КонецПроцедуры
Важное предостережение: Обратите пристальное внимание на третий параметр метода ПодключитьОбработчикОжидания. Он должен принимать значение Истина (Однократно). Если по ошибке передать туда значение Ложь, обработчик начнет циклически выполняться каждую десятую долю секунды. Это приведет к критическому падению производительности мобильного приложения, постоянному мерцанию интерфейса и невозможности нормально работать с формой.
---
Если по каким-то причинам вы не хотите плодить дополнительные процедуры обработчиков ожидания в модуле формы или микроскопическая задержка в 0.1 секунды кажется вам визуально заметной, существует альтернативный лайфхак. Этот способ был найден разработчиками экспериментальным путем и стабильно работает на большинстве версий мобильной платформы.
Суть метода заключается в принудительной переинициализации элемента управления на уровне графического движка ОС устройства. Для этого мы программно скрываем элемент с экрана и тут же возвращаем его видимость обратно в контексте одной транзакции кода.
Проанализируем пример кода:
&НаКлиенте
Процедура АктивироватьПолеЧерезВидимость()
#Если МобильноеПриложениеКлиент Тогда
// Скрываем элемент, заставляя платформу выгрузить его из активного рендера
Элементы.ПолеВвода1.Видимость = Ложь;
// Сразу же возвращаем видимость
Элементы.ПолеВвода1.Видимость = Истина;
// Устанавливаем фокус на пересозданный элемент
ЭтаФорма.ТекущийЭлемент = Элементы.ПолеВвода1;
// Стартуем режим ввода
ЭтаФорма.НачатьРедактированиеЭлемента();
#КонецЕсли
КонецПроцедуры
Этот прием позволяет моментально сбросить внутренний «зависший» статус блокировки фокуса в мобильной платформе 1С. Поскольку видимость меняется мгновенно в рамках одного клиентского вызова, пользователь даже не заметит визуального мерцания элемента, а клавиатура гарантированно откроется.
---
Наиболее часто с проблемой фокуса разработчики сталкиваются при автоматизации складской логистики и розничной торговли с использованием мобильных терминалов сбора данных (ТСД) на базе Android.
При потоковом сканировании штрихкодов критически важно обеспечить беспрерывный цикл работы:
Если фокус не вернется программно, кладовщику придется совершать лишнее действие — каждый раз нажимать пальцем на экран ТСД для активации поля ввода, что замедляет работу в несколько раз и сводит на нет всю пользу от автоматизации.
Используйте предложенные методы (обработчик ожидания с флагом Истина или быстрое переключение свойства Видимость), чтобы гарантировать стабильную работу интерфейса ваших мобильных приложений 1С на любых устройствах!