Как активизировать открытую форму в мобильном приложении 1С без её закрытия?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки мобильных приложений на платформе 1С программисты часто сталкиваются с поведением интерфейса, которое кардинально отличается от привычной десктопной версии. Типичный сценарий: в приложении последовательно открывается цепочка окон — Форма1 → Форма2 → Форма3. При этом предыдущие формы остаются открытыми в оперативной памяти. Перед разработчиком встает задача: как, находясь на активной Форма3, переключить фокус обратно на Форма2, не закрывая при этом текущую Форма3?

Настольная версия 1С решает эту задачу элементарно — например, через вызов метода ПолучитьОкна(), поиск нужного объекта ОкноКлиентскогоПриложения и последующий вызов метода Активизировать(). Однако в мобильной среде этот трюк не срабатывает. Давайте подробно разберем, почему возникает это ограничение и какие архитектурные обходные пути существуют в мобильной платформе 1С.

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

Почему стандартный метод активации окон не работает на мобильных устройствах?

Поведение платформы напрямую продиктовано ограничениями мобильных операционных систем (Android и iOS) и спецификой их графических подсистем:

  1. Однооконный режим работы: В отличие от персональных компьютеров, где интерфейс поддерживает многодокументный или многооконный режим (MDI/SDI), мобильная операционная система по умолчанию выводит на экран только одно активное приложение и одно активное окно в конкретный момент времени.
  2. Игнорирование метода Активизировать(): Хотя коллекция окон и метод ПолучитьОкна() доступны в мобильном клиенте и мобильном приложении, вызов Активизировать() у окна фоновой формы просто игнорируется платформой. Мобильный движок 1С физически не может "вытащить" фоновое окно на передний план, не изменив структуру стека окон.
  3. Строгая стековая архитектура: В мобильных ОС окна (или Activity в терминах Android) жестко организуются в стек по принципу "последним пришел — первым ушел" (LIFO). Верхняя форма в стеке всегда перекрывает предыдущие. Любая попытка открыть форму, которая уже есть в стеке, с тем же ключом уникальности, на мобильном устройстве приводит либо к созданию новой копии поверх стека, либо к игнорированию команды открытия. Прыгать "через голову" активного окна, оставляя его открытым под низом, мобильная операционная система не позволяет.

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

Решение 1. Динамическое управление видимостью элементов (Wizard-интерфейс)

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

Рассмотрим по шагам реализацию этого механизма:

  1. Создадим на форме несколько обычных групп без отображения (например, ГруппаШаг1, ГруппаШаг2, ГруппаШаг3).
  2. Разместим в этих группах соответствующие реквизиты и элементы управления.
  3. Настроим программное переключение видимости групп при переходе пользователя по этапам процесса.

Посмотрим на пример кода, управляющего видимостью шагов:


&НаКлиенте
Процедура ПерейтиНаСледующийШаг()
    
    // Скрываем текущий шаг (аналог Формы 2)
    Элементы.ГруппаШаг2.Видимость = Ложь;
    
    // Отображаем новый шаг (аналог Формы 3)
    Элементы.ГруппаШаг3.Видимость = Истина;
    
    // При необходимости фокус ввода можно перевести на конкретный элемент нового шага
    ТекущийЭлемент = Элементы.ПолеВводаШаг3;
    
КонецПроцедуры

&НаКлиенте
Процедура ВернутьсяНазад()
    
    // Возвращаемся обратно на предыдущий шаг без потери данных
    Элементы.ГруппаШаг3.Видимость = Ложь;
    Элементы.ГруппаШаг2.Видимость = Истина;
    
КонецПроцедуры

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

Решение 2. Использование страниц (вкладок) панели на форме

Этот способ является разновидностью предыдущего метода, но использует стандартный элемент управления платформы 1С — Панель со страницами. Чтобы интерфейс выглядел нативно на мобильном устройстве, у группы страниц отключают отображение закладок (свойство ОтображениеЗакладок устанавливают в значение Не использовать).

Разберем по шагам управление страницами:

  1. Добавим на форму группу вида Страницы и назовем её ПанельШагов.
  2. Внутри неё создадим страницы: Страница1, Страница2, Страница3.
  3. Управление переключением будем осуществлять через свойство формы ТекущаяСтраница.

Пример переключения страниц:


&НаКлиенте
Процедура АктивизироватьСтраницу2()
    
    // Прямой переход на нужную страницу без закрытия остальных данных
    Элементы.ПанельШагов.ТекущаяСтраница = Элементы.Страница2;
    
КонецПроцедуры

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

Решение 3. Механизм фоновых оповещений (Обмен данными без активации)

Если бизнес-логика требует, чтобы Форма3 оставалась открытой на экране, но при этом необходимо обновить состояние или выполнить расчеты в скрытой Форма2, мы можем организовать их программное взаимодействие. Скрытая форма в мобильном приложении продолжает жить в стеке и способна принимать программные сигналы.

Для реализации этого сценария используется глобальный механизм оповещений 1С:

  1. В активной Форма3 при наступлении определенных событий вызывается метод Оповестить().
  2. В скрытой Форма2 настраивается обработчик события ОбработкаОповещения, который отлавливает сигналы и обновляет экранные данные в фоновом режиме. Когда пользователь закроет Форма3, перед ним появится уже полностью обновленная Форма2.

Рассмотрим пример кода отправки оповещения из активной Форма3:


&НаКлиенте
Процедура ВнестиИзмененияИОповестить()
    
    ПараметрыСобытия = Новый Структура;
    ПараметрыСобытия.Вставить("ИдентификаторОбъекта", Объект.Ссылка);
    ПараметрыСобытия.Вставить("НовоеЗначение", Элементы.ПолеРеквизита.ТекстРедактирования);
    
    // Посылаем глобальное оповещение всем открытым формам
    Оповестить("ИзменениеДанныхФормы3", ПараметрыСобытия, ЭтаФорма);
    
КонецПроцедуры

Теперь опишем прием оповещения в скрытой Форма2:


&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
    
    // Проверяем, наше ли это событие
    Если ИмяСобытия = "ИзменениеДанныхФормы3" Тогда
        
        // Анализируем переданные данные и обновляем реквизиты фоновой формы
        Если Параметр.ИдентификаторОбъекта = Объект.Ссылка Тогда
            Объект.ДополнительныйПараметр = Параметр.НовоеЗначение;
            
            // Если требуется обновить динамические списки или прочитать данные из БД:
            // ЭтаФорма.Прочитать(); 
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Решение 4. Закрытие формы с передачей описания оповещения (Обратный вызов)

Если визуальное возвращение на Форма2 является обязательным шагом для продолжения работы пользователя, то правильным решением будет не "перескакивать" фокусом, а штатно закрыть Форма3 с передачей результатов ее работы в Форма2.

Для этого используется механизм описания оповещения о закрытии. Разберем его реализацию:

При вызове Форма3 из Форма2 мы передаем специальный объект обратного вызова:


&НаКлиенте
Процедура ОткрытьТретьюФорму()
    
    // Указываем процедуру-обработчик, которая выполнится на Форме 2 после закрытия Формы 3
    ОписаниеОповещения = Новый ОписаниеОповещения("ПослеЗакрытияФормы3", ЭтаФорма);
    
    ОткрытьФорму("ОбщаяФорма.Форма3", , ЭтаФорма, , , , ОписаниеОповещения);
    
КонецПроцедуры

&НаКлиенте
Процедура ПослеЗакрытияФормы3(РезультатЗакрытия, ДополнительныеПараметры) Экспорт
    
    Если РезультатЗакрытия <> Неопределено Тогда
        // Обрабатываем возвращенные данные
        Объект.РезультатВыбора = РезультатЗакрытия.ЗначениеВыбора;
        Модифицированность = Истина;
    КонецЕсли;
    
КонецПроцедуры

В модуле самой Форма3 при завершении работы вызываем закрытие с передачей структуры данных:


&НаКлиенте
Процедура ЗавершитьРаботуИВернуться()
    
    СтруктураРезультата = Новый Структура("ЗначениеВыбора", Элементы.ПолеВводаРезультата.Значение);
    
    // Закрываем форму и автоматически передаем фокус на Форму 2
    Закрыть(СтруктураРезультата);
    
КонецПроцедуры

Этот способ является наиболее стандартным и идеологически верным с точки зрения разработчиков платформы 1С. Он минимизирует потребление оперативной памяти мобильного устройства и предотвращает переполнение стека вызовов.

Решение 5. Хранение сквозного состояния во временном хранилище

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

Подведем итог. Физически перемещать фокус ("прыгать") между открытыми окнами в мобильном приложении 1С без закрытия верхнего окна невозможно из-за ограничений мобильных ОС. Наилучшим выходом для сохранения плавности работы интерфейса является проектирование логики приложения в рамках единой физической формы с использованием динамических групп видимости или страниц, а для раздельных форм — использование штатного механизма оповещений и закрытия окон с передачей параметров.

← На главную