Эта публикация – вторая из цикла статей о создании простого приложения для мобильной торговли - Контейнер (Google Play и App Store). Что такое Контейнер, почему оно так называется и как мы боролись с двойным заголовком, мы рассказали в первой статье:
Сказ о том, как мы мобильное приложение писали. Часть 1. Двойной заголовок
А сегодня мы расскажем, как в 1С отловить событие долгого нажатия на строку табличной части. Для простоты будем называть его долгим тапом, или просто тапом (от слова tap – касание). По сравнению с первой частью эта статья уже более техническая, поэтому здесь не будет веселых фотографий розовых контейнеров. Ну а что вы хотели – мы в первую очередь разработчики, а не маркетологи. :)
Проблема
В 1С невозможно отловить событие долгого тапа. Данное пожелание уже звучало на партнерском форуме, но разработчики платформы не планируют его реализовывать, т.к. долгий тап не принято использовать на iOS.
На самом деле в мобильной платформе долгий тап есть. Если просто нажать на строку, то сразу происходит ее открытие, но если нажать и держать – то строка подсвечивается синим и ничего не происходит. Это сделано, чтобы пользователь мог выделить строку для выполнения дальнейших действий – например, сдвинуть или удалить. Проблема в том, что разработчик не может переопределить это поведение, и, например, показать пользователю контекстное меню с вариантами действий.
Не может? Ой, да шо вы говорите!
Решение
Как известно, при обычном нажатии на строку срабатывает событие Выбор, и строка открывается. Если строку просто выделить, то сработает событие ПриАктивизацииЯчейки. Казалось бы – что мешает поместить наш код в это событие? Не всё так просто – оно срабатывает не только при выделении, но и при нажатии. Когда мы нажимаем на строку – она на мгновение выделяется (это можно увидеть невооруженным глазом), а потом уже открывается.
Итак, что мы имеем? При долгом тапе отрабатывает только ПриАктивизацииЯчейки, при коротком – ПриАктивизацииЯчейки и Выбор. Вывод напрашивается сам собой – если сработали оба события – значит это Выбор, если сработала только Активизация – значит это долгий тап.
Как мы будем это определять? Напрашивается простой вариант – у формы завести переменную ДолгийТап с типом булево, в событии ПриАктивизацииЯчейки устаналивать ее в Истину, а в Выборе в Ложь. При этом в Активизации подключить Обработчик ожидания, который через полсекунды проверяет – если ДолгийТап = Истина, тогда показываем пользователю меню, если Ложь – тогда ничего не делаем.
Сказано – сделано. Пишем код:
&НаКлиенте
Перем ДолгийТап;
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ДолгийТап = Ложь;
КонецПроцедуры
&НаКлиенте
Процедура КлиентыПриАктивизацииЯчейки(Элемент)
ДолгийТап = Истина;
ПодключитьОбработчикОжидания("Подключаемый_ПроверитьДолгийТап", 0.5, Истина);
КонецПроцедуры
&НаКлиенте
Процедура КлиентыВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
ДолгийТап = Ложь;
КонецПроцедуры
&НаКлиенте
Процедура Подключаемый_ПроверитьДолгийТап()
Если ДолгийТап Тогда
Предупреждение("Это долгий тап!");
КонецЕсли;
КонецПроцедуры
Открываем форму на телефоне – и при открытии сразу же выскакивает наше предупреждение. Как так, мы ведь даже ничего не нажали? Это связано с тем, что при открытии формы первая строка таблицы активизируется и 1С думает, что это долгий тап.
Есть еще один неприятный эффект – долгий тап не срабатывает для уже выделенной строки. То есть если тапнуть по строке, откроется меню, пользователь его закроет и снова тапнет – то второй раз меню не откроется. Такое происходит потому, что событие ПриАктивизацииЯчейки не вызывается второй раз для выделенной строки.
Впрочем, даже в таком варианте этим пользоваться можно. Но “можно” нас не устраивает, поэтому мы продолжаем эксперименты.
Если присмотреться, то корень обеих проблем кроется в выделенной строке. Значит, сделаем так – будем очищать выделенные строки везде, кроме обработчика Активизации, а в обработчике ожидания поставим проверку на выделенные строки. Если выделенные строки есть – значит, Активизации сработала, а Выбор – нет, следовательно, это долгий тап. Пишем алгоритм:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Элементы.Клиенты.ВыделенныеСтроки.Очистить();
КонецПроцедуры
&НаКлиенте
Процедура КлиентыПриАктивизацииЯчейки(Элемент)
ПодключитьОбработчикОжидания("Подключаемый_ПроверитьВыделенныеСтроки", 0.5, Истина);
КонецПроцедуры
&НаКлиенте
Процедура КлиентыВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
Элементы.Клиенты.ВыделенныеСтроки.Очистить();
КонецПроцедуры
&НаКлиенте
Процедура Подключаемый_ПроверитьВыделенныеСтроки()
Если Элементы.Клиенты.ВыделенныеСтроки.Количество() <> 0 Тогда
Предупреждение("Это долгий тап!");
Элементы.Клиенты.ВыделенныеСтроки.Очистить();
КонецЕсли;
КонецПроцедуры
Проверяем – первая проблема осталась. При открытии формы первая строка всё равно остается выделенной (и срабатывает долгий тап), как будто вызов процедуры принудительной очистки строк игнорируется платформой. Причем то же поведение наблюдается и в настольной версии.
Зато вторая проблема решилась – несмотря на то, что после открытия формы строки сама строка визуально остается выделенной, повторный тап по ней срабатывает и выполняется наш обработчик.
Подумаем над первой проблемой. Здесь есть несколько вариантов обхода, но мы остановились на следующей реализации: заведем переменную формы ЛожноеВыделение с типом булево и при открытии будем присваивать ей Истину, а в событии Активизации пропишем, что если это ложное выделение – то выделенные строки очищаются и ничего не происходит. Пробуем:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ЛожноеВыделение = Истина;
КонецПроцедуры
&НаКлиенте
Процедура КлиентыПриАктивизацииЯчейки(Элемент)
Если ЛожноеВыделение Тогда
Элементы.Клиенты.ВыделенныеСтроки.Очистить();
ЛожноеВыделение = Ложь;
Иначе
ПодключитьОбработчикОжидания("Подключаемый_ПроверитьВыделенныеСтроки", 0.5, Истина);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура КлиентыВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
Элементы.Клиенты.ВыделенныеСтроки.Очистить();
КонецПроцедуры
&НаКлиенте
Процедура Подключаемый_ПроверитьВыделенныеСтроки()
Если Элементы.Клиенты.ВыделенныеСтроки.Количество() <> 0 Тогда
Предупреждение("Это долгий тап!");
Элементы.Клиенты.ВыделенныеСтроки.Очистить();
КонецЕсли;
КонецПроцедуры
Запускаем на телефоне – работает!
Причем обратите внимание – можно не только определить свой обработчик долгого тапа, но и установить время задержки перед его срабатываем (второй параметр процедуры ПодключитьОбработчикОжидания).
Ну и чтобы вам два раза не вставать, к этой статье мы прикладываем обработку, в которой реализован простенький обработчик долгого тапа – можно тапнуть по строке и выбрать, что с ней сделать – переместить вверх, вниз, или удалить.
Вывод
Для обработки события длительного нажатия по строке табличной части следует воспользоваться комбинаций событий ПриАктивизацииЯчейки и Выбор, в которых проверяется, выделена ли текущая строка.
Пример реализации приведен в обработке, прикрепленной к статье. В описанном алгоритме также можно задать длительность задержки, после которой срабатывает обработчик. Метод одинаково работает на Android и iOS.
Послесловие
Я не удивлюсь, если первым комментарием к этой статье будет фраза “Мсье знает толк...” А что поделаешь – именно так выглядит программирование под мобильную платформу 1С, если хочется выжать из нее немножко больше, чем 100%. Впрочем мы уверены, что оно того стоит, и наше приложение Контейнер – тому пример.
Мы не прощаемся, и в следующей статье расскажем про наши прекрасные диаграммы расходов и платежей. Оставайтесь с нами!