Разместите только свои настоящие кнопки формы, рассчитайте две собственные строки, выведите результат вперед и уберите завершенную команду лишь из собственного состава.
Где и как запускать
Своя новая Android ARM64 developer лаборатория/CF. МобильноеПриложениеКлиент, минимум8.3.13; scalar server helper — только МобильноеПриложениеСервер. Реальные preset buttons и user command handlers, без внешних SDK/сети/персональных данных.
Подготовка
Это будущий ручной опыт только в своей новой Android ARM64 developer лаборатории/эмуляторе, новой пустой CF и новом отдельном приложении. Ни рабочая ИБ, ни существующие контакты/сообщения/файлы/персональные данные, ни внешняя сеть/SDK/сервис не нужны. Сейчас 1С/GUI/устройство/публикация не запускались.
Создайте свою пустую конфигурацию УчебныеКоманды85, версия = e4a15f82-571d-4724-bf71-75e287184539, совместимость Не использовать. Общие → Общие формы: ровно одна управляемая ПультКоманд85 в рабочей области начальной страницы. Вставьте весь MAIN в ее модуль; событие ПриОткрытии свяжите с настоящим ПриОткрытии(Отказ), не вызывайте вручную.
Добавьте СогласенНаПанель85 (Булево, исходно Ложь), ВерсияRuntime85/Состояние85 (Строка), Сумма85 (Число15,2), ЧислоКоманд85 (Число5,0). Покажите ручной флажок согласия и поля наблюдения; наблюдения ТолькоПросмотр=Да.
Создайте ровно три команды формы НастроитьПанель85, Рассчитать85, ПоказатьИтог85. Для каждой в редакторе создайте реальный одноименный обработчик с параметром Команда и назначьте его как Действие. КомандаФормы.Действие — имя процедуры, не fake callback.
На верхнем уровне этой же формы разместите три обычные кнопки КнопкаНастройки85, КнопкаРасчета85, КнопкаИтога85. Родитель каждой — сама форма, не неизвестная группа. Их ИмяКоманды соответственно НастроитьПанель85/Рассчитать85/ПоказатьИтог85. Кнопки остаются настоящими элементами формы; состав — отдельная коллекция их размещения на мобильной панели.
В своей CF установите назначение использования Приложение для мобильной платформы. Проверьте конфигурацию для Мобильное приложение — клиент и Мобильное приложение — сервер, целостность и неподдерживаемые функции; при ошибках STOP. Конфигурация → Мобильное приложение → Публиковать…: только свой новый виртуальный каталог OwnMobileCommands85_<ownGUID> и своя новая папка своей Windows-VM/IIS. Возможное обновление — только собственной новой ИБ; рабочую базу не подключайте. Это публикация мобильной конфигурации, не сборка APK.
Вручную подготовьте на своем отдельном Android ARM64 стенде официальную developer mobile platform именно1cem-arm64.apk из своего фактически полученного мобильного дистрибутива. Не1cem-client-arm64.apk и не1cem-standalone-arm64.apk. В пустом списке developer приложений: + → Address = реальный URL своей private VM/IIS с точным именем собственной публикации → Load → имя УчебныеКоманды85 → OK/Done → открыть свое новое приложение. Не localhost телефона, не придуманный URL и не публичный/рабочий сервер. Связь только своей лаборатории с собственной VM нужна для загрузки конфигурации; MAIN сети не использует. Здесь нет скачивания, установки, публикации или новыхSDK/магазина/облачного сервиса.
Официальные инструкции будущей ручной подготовки: публикация https://1c-dn.com/library/publishing_of_1c_mobile_application/ ; developer ARM64 и добавление приложения https://1c-dn.com/library/tutorials/1c_enterprise_development_tools_user_guide/ ; собственная первая мобильная ИБ https://1c-dn.com/library/tutorials/first_application_mobile_platform/ . Эти ссылки не подтверждают текущую установку или runtime.
Windows платформа8.5.1.1343 не доказывает версию APK. ВерсияRuntime85 берется из настоящей СистемнаяИнформация.ВерсияПриложения; требуется минимум8.3.13. Scalar helper возвращает только Булево своей CF/версии/единственной формы. Формы/кнопки/состав/строки не передаются через RPC.
Начальный состав не объявлен пустым. Checker перебирает его целиком native Для каждого, подтверждает каждый реальный объект/имя/привязку/родителя, отсутствие повторов и все индексы. Разрешен только subset собственных трех кнопок. Системная/чужая/неизвестная группа или команда — STOP, не массовая очистка и не перезапись неизвестной панели.
Заранее прочитайте все изменения своей эфемерной формы. Отдельное исходноFalse согласие потребляется только кнопкой НастроитьПанель85: она удаляет только явно доказанный собственный subset и строит [КнопкаРасчета85, КнопкаИтога85] через Добавить/Вставить. Открытие формы не меняет состав. Состояние и счетчик относятся к этому экземпляру формы, не обещаны сохраняющимися после перезапуска.
Увидев свою панель, нажмите реальную Рассчитать85. Создаются свои ROW-A750/ROW-B250; полный typed-check вычисляет1000. Перед изменениями еще раз проверяется весь свой состав. Сдвинуть(своя кнопка итога,-1) выводит ее вперед; повторная полная проверка результата/состава предшествует Удалить(своя завершенная кнопка расчета).
Удаляется только ссылка на свою завершенную кнопку из этого состава, не элемент формы, команда, чужое окно или ОС. Обычные кнопки формы остаются; повторный расчет блокируется фазой. Выберите ПоказатьИтог85: фактически перечитанные свои1000 и полный финальный состав1 отражаются в наблюдениях. Визуальное отображение панели проверяйте вручную.
У состава native гарантирован Для каждого, но не оператор[]. Индексы определяются native Индекс только у присутствующих собственных кнопок; [] используется только для собственного обычного массива имен/строк. Для отсутствующих Find/Index не обещается sentinel. Найти физически может вернуть ГруппаФормы или КнопкаФормы; ограничение здесь — только собственные заранее подготовленные кнопки, не запрет native групп.
Имя/Родитель кнопки readonly. ИмяКоманды/Действие команды читаются, но не меняются на клиенте: изменения документированы только на сервере. Сдвинуть second arg и Удалить first arg optional в native, но здесь смещение/собственная кнопка всегда указаны явно. Нет fake-конструктора коллекции.
При изменившемся составе/привязке/среде, исключении или неизвестном исходе — sticky STOP этого экземпляра без automatic cleanup/повторов/восстановления неизвестного состояния. Новый опыт возможен лишь после явной ручной подготовки новой собственной формы, не как automatic recovery; закрытие/перезапуск не сохраняют гарантированную блокировку. Проверки не обещают атомарность, отсутствие гонок, privacy sandbox, OS permission или фактический GUI-success. Текущая доступность API на desktop не является доказательством мобильного отображения.
&НаКлиенте
Перем СогласиеИспользовано85, Остановка85, Этап85, ВерсияЗапуска85, Строки85;
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если СогласиеИспользовано85 <> Неопределено Тогда
Отказ = Истина;
Возврат;
КонецЕсли;
СогласиеИспользовано85 = Ложь;
Остановка85 = Истина;
СогласенНаПанель85 = Ложь;
Сумма85 = 0;
ЧислоКоманд85 = 0;
Попытка
ВерсияЗапуска85 = ПроверитьСреду85();
ВерсияRuntime85 = ВерсияЗапуска85;
ПроверитьСостав85(Неопределено);
Этап85 = "Готов";
Остановка85 = Ложь;
Состояние85 = "Свой состав проверен. Прочитайте опыт и отдельно согласитесь";
Исключение
Остановить85(ОписаниеОшибки());
Отказ = Истина;
КонецПопытки;
КонецПроцедуры
&НаКлиенте
Процедура Остановить85(Причина)
Остановка85 = Истина;
Этап85 = "STOP";
СогласенНаПанель85 = Ложь;
Состояние85 = "STOP. Исход неизвестен: без повторов и автоматической уборки. " + Причина;
КонецПроцедуры
&НаКлиенте
Процедура ПодтвердитьКоманду85(Команда, ИмяКоманды, НужныйЭтап)
Если ТипЗнч(Команда) <> Тип("КомандаФормы") Или Команда <> Команды.Найти(ИмяКоманды)
Или Остановка85 <> Ложь Или Этап85 <> НужныйЭтап
Или ВерсияЗапуска85 <> ПроверитьСреду85() Тогда
ВызватьИсключение "Не совпадает собственная команда, фаза или мобильная среда";
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Функция ПроверитьСостав85(Порядок)
Состав = СоставКоманднойПанелиНаМобильномУстройстве;
Если ТипЗнч(Состав) <> Тип("СоставКоманднойПанелиФормыНаМобильномУстройстве") Тогда
ВызватьИсключение "Нет настоящего состава именно своей формы";
КонецЕсли;
Описания = Новый Структура("КнопкаНастройки85,КнопкаРасчета85,КнопкаИтога85",
"НастроитьПанель85", "Рассчитать85", "ПоказатьИтог85");
Кнопки = Новый Соответствие;
Для Каждого Описание Из Описания Цикл
Кнопка = Элементы.Найти(Описание.Ключ);
Команда = Команды.Найти(Описание.Значение);
Если ТипЗнч(Кнопка) <> Тип("КнопкаФормы") Или ТипЗнч(Команда) <> Тип("КомандаФормы")
Или Кнопка.Имя <> Описание.Ключ Или Кнопка.ИмяКоманды <> Описание.Значение
Или Кнопка.Родитель <> ЭтотОбъект Или Команда.Имя <> Описание.Значение
Или Команда.Действие <> Описание.Значение Тогда
ВызватьИсключение "Изменилась собственная кнопка, родитель или настоящая привязка handler";
КонецЕсли;
Кнопки.Вставить(Описание.Ключ, Кнопка);
КонецЦикла;
Количество = Состав.Количество();
Если ТипЗнч(Количество) <> Тип("Число") Или Количество <> Цел(Количество)
Или Количество < 0 Или Количество > 3 Тогда
ВызватьИсключение "Неизвестный полный состав";
КонецЕсли;
Имена = Новый Массив(Количество);
Для Каждого ЭлементСостава Из Состав Цикл
Если ТипЗнч(ЭлементСостава) <> Тип("КнопкаФормы")
Или Кнопки.Получить(ЭлементСостава.Имя) <> ЭлементСостава Тогда
ВызватьИсключение "Состав содержит не доказанную собственную кнопку";
КонецЕсли;
Индекс = Состав.Индекс(ЭлементСостава);
Если ТипЗнч(Индекс) <> Тип("Число") Или Индекс <> Цел(Индекс)
Или Индекс < 0 Или Индекс >= Количество Тогда
ВызватьИсключение "Не совпадает индекс присутствующей своей кнопки";
КонецЕсли;
Если Имена[Индекс] <> Неопределено
Или Состав.Найти(ЭлементСостава.Имя) <> ЭлементСостава Тогда
ВызватьИсключение "Повтор индекса или подмена найденной своей кнопки";
КонецЕсли;
Имена[Индекс] = ЭлементСостава.Имя;
КонецЦикла;
Для Каждого Имя Из Имена Цикл
Если ТипЗнч(Имя) <> Тип("Строка") Тогда
ВызватьИсключение "Полный состав не сошелся с количеством";
КонецЕсли;
КонецЦикла;
Если Состав.Количество() <> Количество Или (Порядок <> Неопределено И СтрСоединить(Имена, ",") <> Порядок) Тогда
ВызватьИсключение "Изменился полный порядок своей панели";
КонецЕсли;
Возврат Новый Структура("Состав,Расчет,Итог,Имена", Состав,
Кнопки.Получить("КнопкаРасчета85"), Кнопки.Получить("КнопкаИтога85"), Имена);
КонецФункции
&НаКлиенте
Функция ПроверитьРезультат85()
Если ТипЗнч(Строки85) <> Тип("Массив") Или Строки85.Количество() <> 2 Тогда
ВызватьИсключение "Нет двух собственных строк";
КонецЕсли;
Сумма = 0;
Для Индекс = 0 По 1 Цикл
СтрокаРасчета = Строки85[Индекс];
Если ТипЗнч(СтрокаРасчета) <> Тип("Структура") Или СтрокаРасчета.Количество() <> 2
Или ТипЗнч(СтрокаРасчета.Код) <> Тип("Строка") Или ТипЗнч(СтрокаРасчета.Сумма) <> Тип("Число")
Или (Индекс = 0 И (СтрокаРасчета.Код <> "ROW-A" Или СтрокаРасчета.Сумма <> 750))
Или (Индекс = 1 И (СтрокаРасчета.Код <> "ROW-B" Или СтрокаРасчета.Сумма <> 250)) Тогда
ВызватьИсключение "Не совпадает полная собственная строка";
КонецЕсли;
Сумма = Сумма + СтрокаРасчета.Сумма;
КонецЦикла;
Если Сумма <> 1000 Тогда
ВызватьИсключение "Не сошелся свой расчет";
КонецЕсли;
Возврат Сумма;
КонецФункции
&НаКлиенте
Процедура НастроитьПанель85(Команда)
Попытка
ПодтвердитьКоманду85(Команда, "НастроитьПанель85", "Готов");
Если СогласиеИспользовано85 <> Ложь Или СогласенНаПанель85 <> Истина Тогда
ВызватьИсключение "Нужно отдельное неиспользованное согласие";
КонецЕсли;
СогласиеИспользовано85 = Истина;
СогласенНаПанель85 = Ложь;
Этап85 = "Настройка";
Снимок = ПроверитьСостав85(Неопределено);
Имена = Снимок.Имена;
Пока Имена.Количество() > 0 Цикл
Снимок = ПроверитьСостав85(СтрСоединить(Имена, ","));
Снимок.Состав.Удалить(Снимок.Состав.Найти(Имена[0]));
Имена.Удалить(0);
ПроверитьСостав85(СтрСоединить(Имена, ","));
КонецЦикла;
Снимок = ПроверитьСостав85("");
Снимок.Состав.Добавить(Снимок.Итог);
Снимок = ПроверитьСостав85("КнопкаИтога85");
Снимок.Состав.Вставить(Снимок.Расчет, 0);
Снимок = ПроверитьСостав85("КнопкаРасчета85,КнопкаИтога85");
ЧислоКоманд85 = Снимок.Состав.Количество();
Этап85 = "Расчет";
Состояние85 = "В своем составе расчет перед итогом. Проверьте отображение вручную";
Исключение
Остановить85(ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
&НаКлиенте
Процедура Рассчитать85(Команда)
Попытка
ПодтвердитьКоманду85(Команда, "Рассчитать85", "Расчет");
Если СогласиеИспользовано85 <> Истина Тогда
ВызватьИсключение "Нет своего начатого опыта";
КонецЕсли;
ПроверитьСостав85("КнопкаРасчета85,КнопкаИтога85");
Строки85 = Новый Массив;
Строки85.Добавить(Новый Структура("Код,Сумма", "ROW-A", 750));
Строки85.Добавить(Новый Структура("Код,Сумма", "ROW-B", 250));
Сумма85 = ПроверитьРезультат85();
Этап85 = "ПриоритетИтога";
Снимок = ПроверитьСостав85("КнопкаРасчета85,КнопкаИтога85");
Снимок.Состав.Сдвинуть(Снимок.Итог, -1);
ПроверитьРезультат85();
Снимок = ПроверитьСостав85("КнопкаИтога85,КнопкаРасчета85");
Снимок.Состав.Удалить(Снимок.Расчет);
Снимок = ПроверитьСостав85("КнопкаИтога85");
ЧислоКоманд85 = Снимок.Состав.Количество();
Этап85 = "Итог";
Состояние85 = "Свой расчет1000 готов; в составе оставлена только своя команда итога";
Исключение
Остановить85(ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
&НаКлиенте
Процедура ПоказатьИтог85(Команда)
Попытка
ПодтвердитьКоманду85(Команда, "ПоказатьИтог85", "Итог");
Если СогласиеИспользовано85 <> Истина Тогда
ВызватьИсключение "Нет своего начатого опыта";
КонецЕсли;
Снимок = ПроверитьСостав85("КнопкаИтога85");
Сумма85 = ПроверитьРезультат85();
ЧислоКоманд85 = Снимок.Состав.Количество();
Этап85 = "Прочитан";
Состояние85 = "Прочитан собственный итог1000 двух строк; состав содержит1 команду. GUI проверьте вручную";
Исключение
Остановить85(ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
&НаКлиенте
Функция ПроверитьСреду85()
#Если МобильноеПриложениеКлиент Тогда
Информация = Новый СистемнаяИнформация;
Версия = Информация.ВерсияПриложения;
Если ПодтвердитьСвойПакет85() <> Истина Тогда
ВызватьИсключение "Не подтверждена своя учебная конфигурация";
КонецЕсли;
Возврат Версия;
#Иначе
ВызватьИсключение "Только свое мобильное приложение; desktop/mobile-client fallback запрещен";
#КонецЕсли
КонецФункции
&НаСервереБезКонтекста
Функция ПодтвердитьСвойПакет85()
#Если МобильноеПриложениеСервер Тогда
Если Метаданные.ОбщиеФормы.Количество() <> 1 Или Метаданные.ОбщиеФормы.Найти("ПультКоманд85") = Неопределено Тогда
ВызватьИсключение "Не совпадает свой новый мобильный пакет";
КонецЕсли;
Возврат Истина;
#Иначе
ВызватьИсключение "Нужен сервер именно своего мобильного приложения";
#КонецЕсли
КонецФункции
Разбор по шагам
Подготовьте свою новую CF/форму/три настоящих команды и кнопки. Проверьте фактическую мобильную версию; открытие формы только читает полный свой состав.
Отдельно согласитесь и нажмите НастроитьПанель85. Только полностью доказанный собственный subset нормализуется; Добавить и Вставить дают [расчет,итог], count2 и настоящие индексы0/1.
Нажмите реальную Рассчитать85. Свои typed ROW-A750/ROW-B250 дают сумму1000; не входной чужой объект и не цифра из редактируемого поля.
При свежем полном составе Сдвинуть(своя кнопка итога,-1) делает [итог,расчет]. Еще одна полная проверка результата/состава разрешает explicit Удалить только завершенную свою кнопку расчета.
ПоказатьИтог85 перечитывает настоящие свои1000 и финальный состав [итог], count1/index0. Вручную проверьте мобильное отображение; процедуры состава не возвращают native Bool-success.
Как проверить результат
readonly producer именно собственной формы дает настоящий native состав; ни новый выдуманный объект, ни wrapper с ИсходныйОбъект не используются.
Каждый полный read проверяет собственные реальные button refs, Name/CommandName/Parent, настоящие command Name/Action, все элементы, уникальные индексы и отсутствие недостающих слотов собственного массива.
Normalization происходит только после отдельного consumed consent; перед каждой мутацией свежая полная проверка, после — проверенный собственный post-state. Открытие/error path не меняют состав.
Все7 методов связаны одной задачей. Индекс/Найти проверяют только присутствующие actual refs; Move получает explicit-1, Delete actual own button. Native коллекция никогда не индексируется оператором[].
Финальная кнопка действительно читает собственный проверенный расчет; неизвестный исход фиксируется STOP, без GUI/atomicity/privacy/restore claims.
Ожидаемый результат
Ожидаемые наблюдения: свой actual итог1000 двух строк, в своем составе осталась1 команда итога. Визуальное размещение и настоящий Android runtime здесь не проверены.
На что обратить внимание
Нативная справка Find5748 содержит union ГруппаФормы/КнопкаФормы; урезанное guide-data.returnTypeDefinition не повод объявлять native кнопки недопустимыми.
Количество/индексы относятся к собственному составу, не к числу строк расчета. Удаление из состава не уничтожает button/command object формы.
Нет утверждения, что default состав пуст, что отсутствующий элемент дает определенный sentinel или что foreach гарантирует порядок. Own порядок строится из native Индекс в обычном массиве.
Привязки существуют в метаданных; изменять Action/CommandName на клиенте нельзя. Обработчики запускаются настоящими командами, не вызовом вручную.
API since8.3.13; фактическая мобильная версия отдельно от Windows дистрибутива. Нет desktop fallback, внешнего SDK/сервиса/данных.
STOP этого экземпляра sticky; повтор нового опыта возможен лишь явной ручной подготовкой новой собственной формы, не automatic recovery. Нет технической гарантии сохранения STOP между новыми экземплярами; неизвестный prior state не восстанавливается. Только будущая собственная ручная лаборатория.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.