В процессе разработки мобильных приложений на платформе 1С:Предприятие 8.3 часто возникает задача реализации полноценной галереи для товаров. Стандартный функционал платформы позволяет легко привязать одну картинку, но когда требуется добавить неограниченное количество фото и обеспечить удобную навигацию между ними, разработчику приходится проектировать собственную логику. В этой статье мы подробно разберем, как организовать хранение, загрузку и «листание» нескольких изображений для одной номенклатуры.
Прежде чем приступать к интерфейсу, нам необходимо правильно спроектировать структуру хранения в базе данных. Использование одного реквизита типа ХранилищеЗначения непосредственно в справочнике Номенклатура не подходит, так как это ограничит нас одной картинкой. Правильным подходом будет создание подчиненного справочника.
Рассмотрим создание справочника ПрисоединенныеФайлы (или использование типового механизма из БСП). Основные требования к справочнику:
СправочникСсылка.Номенклатура.ХранилищеЗначения, где будет храниться сам бинарный файл картинки.Владелец обязательно должно быть индексировано для быстрого поиска всех файлов конкретного товара.Чтобы реализовать перелистывание, нам нужно получить все ссылки на изображения товара и передать их на клиентскую сторону. Мы будем использовать массив навигационных ссылок, так как это наиболее эффективный способ работы с изображениями в управляемых формах.
Разберем процедуру получения данных, которую следует вызывать при открытии формы или при смене текущего товара:
&НаСервере
Процедура ПолучитьСписокКартинокСервер()
// Очищаем текущий массив ссылок на клиенте
МассивСсылок.Очистить();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПрисоединенныеФайлы.Ссылка КАК Ссылка
|ИЗ
| Справочник.ПрисоединенныеФайлы КАК ПрисоединенныеФайлы
|ГДЕ
| ПрисоединенныеФайлы.Владелец = &Владелец
|УПОРЯДОЧИТЬ ПО
| ПрисоединенныеФайлы.Порядок";
Запрос.УстановитьПараметр("Владелец", Объект.Ссылка);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
// Формируем навигационную ссылку на реквизит ХранилищеЗначения
СсылкаНаКартинку = ПолучитьНавигационнуюСсылку(Выборка.Ссылка, "ДанныеФайла");
МассивСсылок.Добавить(СсылкаНаКартинку);
КонецЦикла;
Если МассивСсылок.Количество() > 0 Тогда
ТекущийИндексКартинки = 0;
ОбновитьИзображениеНаФорме();
КонецЕсли;
КонецПроцедуры
Проанализируем ситуацию: у нас есть массив строк (навигационных ссылок) и индекс текущего элемента. Теперь нам нужно добавить на форму кнопки управления. Для этого создадим команды Вперед и Назад и привяжем их к кнопкам на форме мобильного приложения.
Выясним, как должна работать логика индексов, чтобы избежать ошибок выхода за границы массива:
&НаКлиенте
Процедура Вперед(Команда)
Если МассивСсылок.Количество() = 0 Тогда
Возврат;
КонецЕсли;
// Увеличиваем индекс, реализуя цикличность
Если ТекущийИндексКартинки < МассивСсылок.Количество() - 1 Тогда
ТекущийИндексКартинки = ТекущийИндексКартинки + 1;
Иначе
ТекущийИндексКартинки = 0; // Возврат в начало
КонецЕсли;
ОбновитьИзображениеНаФорме();
КонецПроцедуры
&НаКлиенте
Процедура Назад(Команда)
Если МассивСсылок.Количество() = 0 Тогда
Возврат;
КонецЕсли;
// Уменьшаем индекс
Если ТекущийИндексКартинки > 0 Тогда
ТекущийИндексКартинки = ТекущийИндексКартинки - 1;
Иначе
ТекущийИндексКартинки = МассивСсылок.Количество() - 1; // Переход в конец
КонецЕсли;
ОбновитьИзображениеНаФорме();
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьИзображениеНаФорме()
// Реквизит формы "Фото" (тип Строка) связан с элементом управления "Поле картинки"
Фото = МассивСсылок[ТекущийИндексКартинки].Значение;
КонецПроцедуры
Для мобильного приложения критически важно уметь добавлять фото «на лету». Рассмотрим, как программно вызвать камеру и сохранить результат в наш справочник. Для этого воспользуемся объектом СредстваМультимедиа.
&НаКлиенте
Процедура СделатьСнимок(Команда)
#Если МобильноеПриложениеКлиент Тогда
ДанныеФото = СредстваМультимедиа.СделатьФотоснимок();
Если ДанныеФото <> Неопределено Тогда
СохранитьФотоНаСервере(ДанныеФото.ПолучитьДвоичныеДанные());
КонецЕсли;
#КонецЕсли
КонецПроцедуры
&НаСервере
Процедура СохранитьФотоНаСервере(ДвоичныеДанные)
НовыйФайл = Справочники.ПрисоединенныеФайлы.СоздатьЭлемент();
НовыйФайл.Владелец = Объект.Ссылка;
НовыйФайл.ДанныеФайла = Новый ХранилищеЗначения(ДвоичныеДанные);
НовыйФайл.Наименование = "Фото от " + ТекущаяДата();
НовыйФайл.Записать();
// После записи обновляем массив ссылок
ПолучитьСписокКартинокСервер();
КонецПроцедуры
Если у товара много картинок (например, 10 или более), листать их кнопками становится неудобно. Разберем более продвинутый вариант — ленту миниатюр. Для этого на форму можно добавить таблицу, связанную со списком значений или коллекцией картинок.
Посмотрим на алгоритм реализации такой ленты:
СписокЗначений), у которой включен режим отображения Список.Поле картинки.ПриАктивизацииСтроки этой таблицы мы просто обновляем основное большое изображение, передавая в него адрес из текущей строки миниатюр.Важный момент для мобильных платформ: Память мобильных устройств ограничена. Если вы загружаете в ленту миниатюр полноразмерные фотографии (по нескольку мегабайт каждая), приложение может начать тормозить или аварийно завершаться. Рекомендуем при сохранении фото на сервере генерировать «превью» — уменьшенную копию изображения, и хранить её в отдельном реквизите справочника. В ленте миниатюр отображайте именно «легкие» копии.
Проанализируем еще одну интересную идею. Вместо стандартных кнопок и полей картинок можно использовать Поле HTML-документа. Это позволит реализовать полноценный слайдер с поддержкой жестов (свайпов).
Для этого потребуется:
Такой подход сделает мобильное приложение более «нативным» и приятным для пользователя, так как листание пальцем — это стандартное поведение в современных мобильных интерфейсах. Однако этот метод требует знаний HTML/JS и более сложен в отладке.
Таким образом, мы рассмотрели несколько способов работы с изображениями. Самый простой и надежный для реализации в 1С — это использование динамического массива ссылок и кнопок навигации, что позволяет пользователю комфортно работать с любым количеством фотографий товара.