Экраны¶
Экраны, общее¶
Экраны нужны для отрисовки визуальных элементов. По большей части визуальные элементы располагаются в контейнерах на экране и также есть элементы самого экрана.
Процессы – это просто набор экранов. Вся логика сосредоточена в экранах – обработчики, активные элементы и т.д.
Размещенные на экране элементы заполняются либо из констант либо из переменных стека либо из слайсов. Например вы разместили на экране кнопку. У нее есть Значение (Value), например «Записать»
Это выглядит так в конструкторе и на форме
Но можно определить значение как @btn_caption, предварительно записав в переменную btn_caption значение «Записать Документ №1»
Тогда при отрисовке, будет так
Когда запускается процесс, всегда запускается первый в списке экран процесса. У экрана при запуске происходит отрисовка и выполнение 2х событий друг за другом - onStart и onPostStart.
Вообще видов событий у экрана всего 3:
onStart – событие при запуске, но до начала отрисовки. Сюда можно поместить обработчик, который заполнит переменные экрана, связанные с визуальными элементами. Надо иметь ввиду такой нюанс: если обработчик быстрый, то можно использовать тип выполнения run. А если долгий, то runasync или runprogress (иначе открытие экрана будет зависать, что неэстетично и может привлечь внимание ОС). При этом, если вы используете асинхронный обработчик, то следует понимать, что он закончится, когда экран уже отрисован, и чтобы появились визуальные элементы, которые вы заполняли в таком обработчике (например вы заполняли большой список) нужно перерисовать экран командой RefreshScreen. В общем onStart в основном используется для заполнения визуальных элементов и инициализации переменных.
onPostStart событие после отрисовки элементов. В некотрых случаях нужно обработься к элементу когда он уже размещен на экране
onInput – любые события ввода: нажатия на кнопку, чтение штрихкода, выбор меню и т.д. За редким исключением, событие ввода влечет за собой перерисовку экрана. Соотвественно после onInput будут пересозданы элементы и запустятся обработчики onStart и onPostStart.
Как видно все многообразие событий ввода собрано в onInput, поэтому люое событие ввода имеет еще признак listener чтобы их можно было разделять.
Команды управления экранами и процессами¶
ShowScren, <имя экрана> – переключает на другой экран в процессе. Т.е. если в процессе есть Экран1 и Экран2, то ShowScreen, Экран2 вызовет запуск Экран2 с соответствующими событиями onStart, onPostStart.
Пример (тут и далее примеры команд пишутся для python, если у вас другие обработчики, переводите их под свой стек)
hashMap.put("ShowScreen","Экран 2");
ShowScreen,<ИмяПроцесса>|<ИмяЭкрана> - команда заимствования экрана из любого процесса (не обязательно текущего). Хороша тем, что работает без перезапуска процесса, в отличии от StartProcess (а перезапуск довольно затратный процесс, при котром происходит инициализация оборудования и другие длительные вещи)
hashMap.put("ShowScreen","Общие формы|Экран 2");
ResreshScreen, без параметра – обновление (перерисовка экрана) без вызова onStart/onPostStart. Нужна для того, чтобы перерисовать элементы из заполненных переменных. Обязательно использовать с любым асинхроном. Также, см. далее команду UpdateLayout для частичного апдейта выбранного контейнера.
RestartScreen, без параметров – перезапуск экрана, с выполнением onStart/onPostStart
StartProcess, <имя процесса> – запуск процесса из процесса
ShowProcessScreen, <имя процесса> – запуск процесса из фона (когда ни один процесс не запущен)
FinishProcess, без параметра – завершение процесса
Общие функции экранов¶
Таймер экрана¶
На экране можно определить таймер, который будет периодически генерировать событие ввода (частота таймера задается в общих настройках). Данная функция была введена до того, как в платформе появились асинхронные обработчики. Большинство сценариев для которых нужен таймер гораздо более эффективно реализуются на асинхроне и системе не нужно постоянно дергать экран, более того это еще и более быстрая реакция. Поэтому прежде чем использовать таймер, рекомендуется посмотреть в сторону асинхронных вызовов экранов или сервиса событий.
Скрыть верхнюю панель¶
Скрывает тулбар в экране. Если предусмотрен поиск в тулбаре или меню, то лучше того не делать
Нижняя панель и свойство Скрыть нижнюю панель¶
В SimpleUI ввиду совместимости на экране по умолчанию присутствует панель с кнопками Вперед (listener- пустая строка), Назад и План-факт. Это устаревший рудимент и рекомендуется отключать его галкой «Скрыть нижнюю панель»
Отключить прокрутку корневого контейнера¶
Все элементы экрана по умолчанию выводятся в бесконечный прокручиваемый по вертикали контейнер. Но в случае например списков (которые сами имею свою прокрутку) это создает некорректную ситуацию. Например нельзя разместить список «на весь экран» если этот экран – бесконечный. Значит нужно его ограничить(зафиксировать). Для этого существует опция Отключить прокрутку корневого контейнера.
Закрывать без вопроса¶
По умолчанию при закрытии экрана/процесса кнопкой назад (системной) пользователю задается вопрос. Этой галочкой можно отключить данный диалог.
Подключить обработчик клавиатуры¶
При включенном флаге, когда происходит нажатие одного из сочетаний клавиш генерируется событие listener= keyboard и в переменную keyboard возвращается считанная клавиша.
- Список клавиш такой (в обычном режиме):
сочетания с Ctrl
сочетания с Alt
сочетания с Shift
F1-F12
Также можно в настройках приложения установить галку «Перехватывать все клавиши» тогда будут возвращаться абсолютно все клавиши причем еще в виде 2х событий - нажатие и отпускание. Важно помнить - в таком режиме коды клавиш пишутся в с префиксами #up и #down - это нужно учитывать в обработчиках. Для того, чтобы понять какие коды у клавиш можно воспользоваться пунктом главного меню «Тест клавиатуры»
Элементы экрана¶
Далее перечисленные все актуальные элементы экрана (не упомянутые элементы оставлены для совместимости со старыми конфигурациями)
Контейнер – элемент разметки и контейнер для других визуальных элементов. Подробнее в разделе «Разметка экрана контейнерами»
Штрихкод – подключение к экрану обработчика чтения штрихкодов. Штрихкоды могут считываться через подключенное оборудование (подробнее в разделе Оборудование) либо через камеру. Если в экране подключен элемент штрихкод, то на экране появляется плавающая кнопка «Штрихкод», которая запускает считывание камерой. Если эта кнопка не нужна, ее можно скрыть в общих настройках приложения «Аппаратный сканер». Также штрихкоды могут считываться ActiveCV (описано в разделе ActiveCV) в более расширенном виде. Этот вариант (в случае с камерой) просто возвращает 1 штрикход на один запуск (нет потокового сканирования). В элменте нужно определить Переменную куда будет возвращаться штрихкод. При считывании (без разницы камерой или оборудованием) генерируется событие listener=barcode и в переменную Штрихкода пишется считанный штрихкод
Голос Запускается распознавание голоса. У элемента надо определить Переменную, куда будет возвращен результат. В случае успеха возникает событие listener=voice и в переменную помещается результат. Также возможно запускать распознавание из кода, см в разделе Голос и синтез речи.
Подпись Ввод подписи с экрана. Нужно определить переменную куда запишется base64-картинка подписи. При успешном вводе подписи генерируется событие listener=signature
Фото камерой, Фото из галереи, Горизонтальная галерея мультимедиа и Галерея слайдер Подробнее об этих элементах написано в разделе Работа с мультимедиа
Элемент меню Можно добавить элемент в меню опций (в тулбаре). У элемента нужно определить Значение – название пункта меню и Переменную – она будет возвращена в listener при выборе пункта меню. Причем если значение задать в виде иконки Awesome (см. пункт Awesome) то такой пункт меню будет в тулбаре
Плавающая кнопка Можно размещать свои кнопки поверх экрана справа снизу. У элемента нужно определить Переменную и Значение. В Значении можно либо написать имя одной из предопределенных иконок либо использовать Awesome-иконку. Предопределённые:
"forward","backward","run","cancel","edit","picture","info","settings","plus","save","search","send","done". Awesome описаны в разделе Awesome-иконки ниже. Ввиду того, что иконки генерируемые, они имеют разные пропорции. Поэтому именно в Плавающей кнопке желательно использовать сдвиги по x и y. Например, вот так определяется иконка «звездочка» но с сдвигом по X- 0, а по Y - -15: #f005;0;-15. Если не использовать сдвиг по y, то звездочка съезжает вниз.NFC Подключение считывания NFC. Описано в разделе NFC.
Разметка контейнерами¶
Высота, ширина, вес¶
Визуальные элементы находятся внутри контейнеров. В экране должен быть хотя бы один контейнер (корневой) в котором размещаются элементы, в т.ч. другие контейнеры. Контейнеры могут иметь горизонтальную и вертикальную ориентацию (свойство Ориентация(ключ orientation)) **Высота**(«height») и **ширина**(«width») контейнера может быть:
«На всю ширину» (match_parent) – контейнер занимает по выбранной оси все пространство.
«По размеру элементов» (wrap_content) – размер определяется соответствующим максимальным размером вложенных элементов
Определенную вручную – числовое значение в относительных экранных единицах
Если мы хотим разбить экран на зоны (пополам или в других пропорциях) по вертикали, то прежде всего нужно Отключить прокрутку корневого контейнера. Т.е. мы работаем не в бесконечном прокручиваемом экране, а в рамках одного экрана с конечной высотой и шириной.
И контейнеры, и элементы внутри них подчиняются одним и тем же правилам размещения.
Если нужно распределить несколько элементов в рамках контейнера пропорционально ширине или длине, то нужно выполнить следующее (пример для распределения горизонтально, для вертикального распределения действует аналогичное правило):
Элементы должны быть включены в горизонтальный контейнер (type: LinearLayout, orientation:horizontal), с шириной match_parent
у элементов внутри должна быть ширина= 0
у элементов должен быть вес (ключ weight) в тех пропорциях, в которых нужно распределить элементы на экране.
Например, еcли два элемента должны делить ширину пополам, то у обоих должен быть вес 1, если один должен быть в два раза шире то у него должен быть вес 2, а у другого – 1. Т.е. вес это пропорция или вес элемента в рамках контейнера по оси.
Еще один вариант часто встречающейся разметки: нужно растянуть элемент, но оставить место для элементов сверху и снизу. Например, у вас сверху несколько элементов, а снизу вы хотите разместить блок кнопок. Между ними пространство может быть пустое, либо занято списком, как вариант.
Предупреждение
Важно! Если вы что то хотите растягивать по верстикали - обязательно отключите прокрутку корневого контейнера!
Для этого элементы сверху имеют высоту по размеру элементов(wrap_content), снизу – тоже по размеру элементов, а элемент посередине имеет высоту(«height»)=0 и вес(weight)=1
Два вышеприведенных примера тут: https://disk.yandex.ru/d/JOJh0OtV1aAdig
Раздел конфигурации Контейнеры¶
Контейнеры используются в экранах, в макетах элементов списка, диалогах и команде SetRootLayout. Во всех этих местах можно определять контейнер непосредственно в виде JSON-строки. Но часто, например со списками и диалогами хранить контейнеры в отдельном месте (раздел конфигурации Контейнеры (в структуре конфигурации массив Layouts)), а при определении списков или диалогов, либо в setRootLayout использовать ссылку на переменную контейнера.
В разделе Контейнеры действуют все те же самые принципы построения контейнеров, толкьо с одним условием – у контейнера (верхнего уровня) обязательно должна быть переменная, по которой к нему можно будет ссылаться.
Конфигурация с примерами использования такого подхода: https://disk.yandex.ru/d/v9ZYd8GlMH_03w
Прочие поля и свойства контейнера, методы¶
Переменная. Необязательное для контейнера поле. Может использоваться для того, чтобы обратиться к контейнеру из какой либо функции.
Например есть команда-переменная UpdateLayout, <переменная контейнера> по которой обновиться только указанный контейнер. Т.е. это аналог RefreshScreen, но только для одного контейнера. Эту команду желательно использовать, когда на экране что то тяжелое, например ActiveCV
Замена контейнера экрана¶
Макет экрана, определенный из кода, можно динамически заменить в экране командой-переменной SetRootLayout (из onStart например). В качестве параметра к ней, можно использовать как JSON-строку с нужным контейнером, так и ссылку на контейнер через префикс «^»
Общие для элементов и контейнеров свойства¶
Цвет фона (свойство BackgroundColor) – цвет, задаваемый в виде HEX-значения. Например #89f096
Толщина окантовки (ключ StrokeWidth) - рисует рамку вокруг контейнера или элемента с заданной толщиной в экранных единицах
Внутренние отступы (ключ Padding) – отступы вглубь контейнера в экранных единицах
Радиус (ключ Радиус) – если задана Толщина окантовки, то рисуется не прямые поля а закругление. Для элемента можно назначить радиус, равный -1. Тогда закругление будет в виде полного круга.
Cвойства и функции элементов экрана¶
- Все элементы имеют поле Переменная (ключ Variable). Это ИД элемента. Оно выполняет несколько функций:
как правило при генерации событий, имя переменной пишется в listener (Например на экране несколько кнопок и при нажатии в listener пишется переменная кнопки)
По переменной можно обратиться к элементу, например установить видимость (см. ниже)
по переменной можно получить Java-объект функцией getView чтобы проделать с ним низкоуровневые манипуляции на уровне AndroidSDK
Значение (ключ Value). В зависимости от типа элемента – это различное значение, видимое в элементе. Для надписи – это текст надписи, для кнопки – текста кнопки, для таблицы – весь макет таблицы с данными и т.д. Значение может задаваться в виде константы, т.е. в виде просто текста в конфигурации, может быть в виде ссылки на переменную стека (через символ @) и может быть задано в виде ссылки на слайс (через символ #)
Выравнивание по горизонтали (gravity_horizontal) – выравнивание элемента отновительно контейнера. Может принимать значения left, right, center
Размер текста (TextSize), Цвет текста(TextColor), текст жирный («TextBold»), Наклонный («TextItalic») – задает параметры элементов, имеющих надписи (например Надпись): размер в виде относительного размера, цвет в виде HEX-значения, жирный и наклонный - булево
Количество знаков(NumberPrecision) – количество знаков после запятой для полей ввода типа число.
Писать в слайс (Slice) – для полей ввода информация будет писаться в слайс экрана/процесса в типизированном виде (без преобразования в строку ) – JSON-структуру доступную через переменные process_slice (слайс, существующий на протяжении всего процесса) и screen_slice (слайс экрана) в обработчике pythonscript
Подсветка обязательных полей и ошибок заполнения¶
Возможны варианты:
Галочка элемента Подсвечивать пустое. Это просто автоматическая подсветка незаполненного. Ни на что не влияет, убирается, когда происходит заполнение
Галочка Не пропускать пустое. Выдаст визуальную ошибку на поле и не даст выполнится обработчику дальше.
Проверка поля в обработчике и визуальная выдача ошибки, если поле не соответствует. Это уже проверка не просто на заполненность, а на значение самого поля. Выполняется с помощью команды Stop_<переменная поля>. Понятно, что и без этого достаточно вывести тост или что то подобное, но так нагляднее
Управление видимостью элементов¶
Для управления видимостью отдельных элементов экрана следует использовать команду Show_<Идентификатор элемента>, например ``hashMap.put(«Show_left»,»-1») `` , где left - переменная элемента (переменная=идентификатор). Значения могут быть:
«1» - виден
«0» - не виден, без освобождения места,
«1» - виден, с освобождением места
Отключение перерисовки экрана, генерации событий, подсветка краcным и зеленым¶
Можно использовать команду noRefresh, которая отключает перерисовку элементов - т.е. обновление экрана при выполнении обработчика. Пример:
hashMap.put("noRefresh","")
Можно отключить события по полям ввода, котрые автоматически генерируют события при вводе (например Галочка, поля с отслеживание ввода символов) командой disable_events, без параметров.
- Можно использовать подсветку полей ввода бледно-зеленым и бледно-красным цветом. Для того чтобы обозначить пользователю корректный или некорректный ввод можно выделить неярким красным или зеленым цветом поля ввода списком
SetRed, <список переменных полей ввода через “;”> - выделяет список полей красным
SetGreen, <список переменных полей ввода через “;”> - выделяет список полей зеленым
Фокусировка¶
Для поля ввода можно задать принудительную фокусировку – тогда при открытии экрана поле ввода будет активным (с курсором), командой FocusField, <имя переменной поля>. Можно выбрать только одно поле. Допустим у вас экран ввода штрихкода, а на следующем экране необходимо сразу
Html-строки¶
Все надписи, практических всех элементов (не только непосредственно элементы Надпись, но и прочие элементы, например текст в таблицах) можно размечать HTML-тегами. Это мощный и простой способ оживить интерфейс без усложнения лишними контейнерами, фоновыми цветами и т.д., Например можно выделить часть строки так. Это простой текст, а это <b>жирный</b>
- Вот примерный список поддерживаемых тегов:
p
ul
li
div
span
strong
b
em
cite
dfn
i
big
small
font
blockquote
tt
a
u
del
s
strike
sup
sub
h1
h2
h3
h4
h5
h6
img
br
Awesome-иконки¶
- В системе можно использовать растровые иконки (файлы подключаются через раздел Медиафайлы и потом используются через префикс ^). Но можно использовать набор шрифта Awesome. Это набор пиктограмм, с помощью которого можно сделать свои красивые кнопки, сделать иконки на карточках, экранах и т.д. Используется бесплатный набор из 1001 иконки (отбор по free + отбор по solid) https://fontawesome.com/v5.15/icons?d=gallery&p=2&s=solid&m=free Для того чтобы использовать, надо взять на сайте Unicode -код например f6be и присвоить переменной с префиксом # – т.е. #f6be, который потом указать в заголовке кнопки или надписи. Это можно использовать в элементах экранов, диалогов и т.д. Например:
Кнопка
Список кнопок
Горизонтальный список кнопок
Надпись
Упрощенная разметка полей ввода с заголовком помощью “|”¶
Все поля ввода (кроме современного поля ввода) можно разместить вместе с заголовком в упрощённом виде. Как это было бы в стандартном исполнении? Для этого надо сделать горизонтальный контейнер и разместить в нет два элемента – Надпись (заголовок поля) и поле ввода с весами у обоих =1. Тогда мы получим поле с заголовком. Это же действие можно выполнить, если разместить просто поле ввода:
Элементы контейнера¶
Надпись¶
Надпись(TextView) – выволится надпись из переменной или константы.
Кнопка¶
Кнопка(Button) – простая текстовая кнопка, но с помощью Awesome можно превратить ее в кнопку с иконкой. При нажатии генерирует событие с listener=переменная кнопки.
Простые поля ввода¶
Поле ввода строка(EditTextText), Поле ввода число(EditText EditTextNumeric), Поле ввода пароль(EditTextPass), Многострочный текст(MultilineText) – простые текстовые поля ввода соответствующих данных(регулируется фильтром на ввод). Для пароля введенный текст скрывается.
Современное поле ввода¶
Поле ввода, в котором размещается заголовок/подсказка в зависимости от того, заполнено оно или нет. Если в поле присутствует информация, подсказка смещается в область заголовка. Таким образом достаточно размещать только один элемент, что экономит место и упрощает разработку. Значение задается в виде JSON. Обязательными является hint – подсказка. Например
{
"hint":"Логин",
"default_text":"default_login"
}
– задает подсказку, и если поле уже должно содержать предопределенные данные, то они задаются в default_text (можно передавать не константу, а ссылку на переменную через @)
По умолчанию – это текстовое поле, но можно задать любой тип, имеющийся на Андроиде через input_type. Варианты – тут: https://developer.android.com/reference/android/text/InputType
Также, можно задать counter – счетчик введенных символов внизу и counter_max – максимальное количество символов.
Ключом events можно подключить генерацию событий с каждым введенным символом в поле, чтобы например записывать в БД сразу же введенный текст. Значение должно быть «true» Пример определения со всеми возможными опциями:
{
"hint":"Пароль",
"default_text":"default_password",
"counter":"true",
"counter_max":15,
"input_type":145,
"password":true,
"events":true,
}
Поле ввода с событием¶
Поле ввода с событием (EditTextAuto) – текстовое поле, при вводе каждого символа в котором генерируется событие и срабатывает обработчик
Галочка¶
Галочка (CheckBox) – поле чекбокса с событием изменения(генерируется событие с listener=имя переменно). Значение пишется в переменную стека (переменная определяется в Переменной(Variable)) (и читается также из переменной, а не из значения). В поле Значение (Value) - заголовок поля.
Дата¶
Дата(DateField) поле выбора даты из календаря. При выборе даты в переменную даты пишется отформатированная в соответствии с региональными настройками выбранная пользователем дата, а в переменную <переменная_поля>_d пишется дата в ISO-формате. В слайсы, аналогично пишутся даты в двух форматах – представление и ISO.
DatePicker, NumberPicher, TimePicker¶
Визуальные элементы для выбора числа, даты, времени. Выбранные значения записываются в переменную. Начальная установка определяется в Значении.
- Формат Значения для элементов:
Пикер числа: {«min»:0,»max»:10,»value»:»@number»}, где min/max задают диапазон, value- установленное значение
Пикер даты: {«year»:@year,»month»:@month,»day»:»@day»} - значение пишется в виде года, месяца и дня
Пикер времени: {«hour»:@hour,»minute»:@minute} – часы, минуты
Картинка (см. раздел «Работа с изображениями»)¶
Выпадающий список¶
Выпадающий список – простой выпадающий список. Элементы можно задать в виде строки с разделителем «;» через переменную или прямо в конструкторе. В списке всегда будет выбран первый элемент, поэтому если требуется чтобы по умолчанию было пусто , первым элементом следует определить пустую строку или что то подобное. Например «<Выберите значение>;Первый;Второй». В Переменную при этом возвращается выбранное значение. Можно указать значение по умолчанию - то значение, которое будет выбрано при открытии. Для этого нужно в стек переменных поместить переменную с именем переменной результата. Например, если переменная - res то помещаем в hashMap.put(«res»,»Второй»).
Примечание
Для выбора ссылочных объектов предназначены поля датасетов (см. Датасеты)
Список кнопок вертикальный и Список кнопок горизонтальный¶
Размещение нескольких кнопок с помощью списка. В значении передается список заголовков кнопок, и они размещаются в ряд вертикально или горизонтально. При нажатии генерируется событие с listener=<переменная кнопки> и также в стек помещается переменная =перменной кнопки со значением, равным заголовком кнопки.
Индикатор(Gauge)¶
стрелочная диаграмма для визуального представления какого то значения
В качестве значения передается JSON-строка с ключами Min(минимальное значение шкалы), Max (максимальное значение шкалы), Unit (единица измерения) и Value (текущее значение)
Пример:
tmenu['gauge_tasks'] = json.dumps({"Min":0,"Max":100,"Value":q,"Unit":" "})
Диаграммы. Линейная (Line), Столбчатая (Bar) и Круговая(Pie) вывод диаграмм в контейнер¶
Примечание
Кстати, еще одним хорошим способом вывести диаграммы и вообще отчеты является HTML-поле + какая либо библиотека для диаграмм на python. См. HTML-поле и например пример подключения библиотеки pygal https://infostart.ru/1c/articles/1760354/
Пример Значения столбчатой диаграммы
{"type":"Bar","Datasets":[{"name":"Оптовые продажи","values":[{"x":"2017","y":"100"},{"x":"2018","y":"210"},{"x":"2019","y":"260"}]},{"name":"Розничные продажи","values":[{"x":"2017","y":"55"},{"x":"2018","y":"40"},{"x":"2019","y":"75"}]}]}
Пример Значения линейной диаграммы
{"type":"Line","Datasets":[{"name":"Оптовые продажи","values":[{"x":"2017","y":"100"},{"x":"2018","y":"210"},{"x":"2019","y":"260"}]},{"name":"Розничные продажи","values":[{"x":"2017","y":"55"},{"x":"2018","y":"40"},{"x":"2019","y":"75"}]}]}
Пример Значения круговой диаграммы
{"type":"Pie","dataset_name":"по регионам","PieDataset":[{"value":35,"caption":"ЦФО"},{"value":20,"caption":"СЗФО"},{"value":45,"caption":"Прочие"}]}
Таблица и Список карточек¶
Таблица и список карточек отличаются только дизайном и форматом значения. По сути это один и тот же элемент с одними и теми же свойствами и поведением.
Таблица не имеет границ строк по умолчанию, их надо задавать в контейнере если требуется. Тоже самое с чересстрочной разметкой.
В Списке карточек элементы оформлены в виде карточек
Существует несколько подходов к определению значения этих списков, поэтому укажем универсальный формат
Для списка карточек переменная будет иметь структуру:
{ "customcards":{
"options":ОПЦИИ,
"layout": КОНТЕЙНЕР,
"cardsdata": ДАТАСЕТ
}
}
Для таблицы:
{ "customtable":{
"options":ОПЦИИ,
"layout": КОНТЕЙНЕР,
"tabledata": ДАТАСЕТ
}
}
Где:
ОПЦИИ (необязательный) – объект с различным набором опций:
search_enabled,булево – поиск в тулбаре. Для объектов без механизма датасетов – это поиск по вхождению строки по всем полям поиска. Для датасетов поиск настраиваемый см. Датасеты.
save_position, булево – сохранение поизиции при перерисовке. Например при обновлении строки. Работает только для списков с конечным датасетом. При использовании пополнения порциями в настоящий момент не работает.
override_search, булево – переопределить поиск в тулбаре. Будет срока поиска, но при вводе будет осуществляться не поиск, а генерация события ввода с переменной «SearchString» и listener=Search. Фильтрацию списка в данном случае осуществляет сам разработчик
search_submit – поиск/генерация событий соуществляется не после каждого введенного символа, а после подтверждения ввода на клавиатуре
colorizing использование выборочной раскраски элементов (см. далее)
horizontal – горизонтальное направление списка
КОНТЕЙНЕР – либо JSON с текстом контейнера (текст можно скопировать, например из конструктора) непосредственно (что неудобно и громоздко), либо ссылка на контейнер определенный в конфигурации через символ ^. Например, «layout»: «^item1» (см. пример ниже)
ДАТАСЕТ – либо JSON-массив, либо ссылка на датасет(механизм датасеты) через префикс ~. Данные в обоих случаях – массив JSON -объектов по одному на каждый элемент списка. В которых перечисляются переменные, отображаемые в контейнере (через @). Также могут быть добавлены любые другие(неотображаемые в интерфейсе). Также в элементе датасета отдельно можно указать key – ключ, возвращаемый при нажатии в специальную переменную (в случае с механизмом датасетов это делать не имеет смысла, так как в датасете у каждой записи есть _id)
Пример определения списка карточек в Python (без использования механизма датасетов, с опциями поиска в тулбаре и сохранение позиции)
j = { "customcards": {
"options":{
"search_enabled":True,
"save_position":True
},
"layout": "^card1",
"cardsdata":[]}
}
j["customcards"]["cardsdata"].append({"text1":"Какой то заголовок 1","text2":"Подзаголовок №1"})
j["customcards"]["cardsdata"].append({"text1":"Какой то заголовок 2","text2":"Подзаголовок №2"})
hashMap.put("cards",json_to_str(j))
Пример Таблицы с использование датасетов, без опций:
j = { "customtable": {
"layout": "^item",
"tabledata":"~goods"}
}
При нажатии на элемент списка генерируется событие CardsClick. В переменных появляется:
selected_card_key – ключ, если, а записи есть key
selected_card_position – позиция списка
selected_card_data (если это датасет, либо если не датасет, то если заранее включен флаг «return_selected_data») – целиком запись в виде JSON-элемента массива
Переопределение макета любого элемента списка¶
С релиза 10.35 можно для любого элемента customcards и customtable сделать свой дизайн на основе отдельного контейнера (например выделить цветом), абсолютно любого содержания. Для этого в rows в конкретном элементе надо использовать _layout и передать туда нужный макет. Таким образом, можно сделать каждый элемент со своим дизайном.
j = { "customtable": {
"layout": "^card1",
"tabledata":[]}
}
j["customtable"]["tabledata"].append({"text1":"Какой то заголовок 1","text2":"Подзаголовок №1"})
j["customtable"]["tabledata"].append({"_layout":"^card2","text1":"Какой то заголовок 2","text2":"Подзаголовок №2"})
j["customtable"]["tabledata"].append({"text1":"Какой то заголовок 3","text2":"Подзаголовок №3"})
hashMap.put("cards",json_to_str(j))
Выборочная раскраска элементов списка¶
В списках можно делать произвольный макет каждого элемента (через «_layout»), в том числе и раскраску, но это затратная технология (на больших списках и медленных устройствах сказывается на быстродействии). Поэтому добавлена просто «раскраска» (меняется только цвет фона, а не весь макет)
В опциях таблицы должно быть включено «colorizing», и тогда на элементы можно использовать свойство _background с указанием цвета в HEX-формате.
Использование активных элементов в списках¶
В элементах списков доступно использование активных элементов: Кнопки, Меню и Флажки. Для этого их нужно разместить в контейнере в любом количестве и любом месте. При нажатии они будут порождать отдельное от нажатия на саму карточку событие с listener=LayoutAction, также помещается переменные layout_listener и card_data. В первой содержится переменная элемента, породившего событие (кнопки, пункта меню, флажка). Во второй - данные карточки, включая позицию в виде JSON-строки. Для добавления меню нужно поместить в контейнер элемент PopupMenuButton, в качестве значения передать список пунктов меню, разделенных точкой с запятой. Например «Первый;Второй» Флажок ведет себя как обычный флажок, плюс выполняет необходимое действие - при изменении состояния, он прописывает значение состояния в датасет переменной списка, чтобы при обновлении списка показать текущее состояние.
Использование поиска, переопределение поиска¶
Примечание
Для датасетов поиск устроен по-другому. См. главу «Датасеты».
Для того, чтобы на экране появился автоматический поиск по таблице в тулбаре, необходимо добавить в JSON списка в раздел «options» поле search_enabled с значением True. Также по желанию, можно передать поле, по котору будет вестись поиск search_string - это ключ, в который для каждой карточки можно поместить строку с данными поиска. Поиск будет вестись по вхождению подстроки поиска в эту строку. Если такого поля нет в карточке, то будет вестись поиск по всем полям объекта данных. Этот поиск можно переопределить - пустить вводимый текст на события. Для этого в раздел «options» необходимо добавить override_search с значением True, тогда при вводе текста в поле поиска будет генерироваться событие Search, а в переменную SearchString будет попадать введенный текст
Горизонтальные списки¶
Опция horizontal:True делает список горизонтальным. Также, если требуется чтобы карточка была не на всю ширину экрана, а допустим на какую то его часть, нужно указать опцию «width_ratio» – с процентом от ширины экрана, например 50 - будет половина экрана. Если не указать, то карточка будет на всю ширину
Сохранение позиции в списке¶
Для того, чтобы на экране появился автоматический поиск по таблице в тулбаре, необходимо добавить в JSON списка в раздел «options» поле «save_position» с значением True. При наступлении события и перерисовке списка, список останется на том же месте.
Использование групп¶
Можно сгруппировать список карточек (работает только со списком карточек). Для этого в нужных местах датасета нужно вставить объекты с полем «group» (предопределенное поле)
Догрузка данных при промотке¶
Для больших списков можно сделать догрузку – получение порций данных, когда пользователь промотал до конца. При промотке дальше возникает событие LoadMoreItems, оформленное прогресс баром, в котором разработчик может определить обработчик добавления новой порции строк в переменную AdditionalItemsData.
Позиционирование на позицию в списке карточек и таблице¶
Теперь можно мгновенно или плавно переместиться на выбранную позицию двумя простыми командами:
ListGoTo, номер позиции – мгновенное перемещение на позицию
ListGoToSmooth, номер позиции – анимированное перемещение на позицию
Поля датасетов¶
Можно разместить на экране ссылочные поля ввода данных, содержащие ссылки на записи датасетов
Вы просто указывает переменную в которой храниться или будет храниться значение поля в виде ссылки и датасет в значении. И всё. Пользователь просто выбирает запись из списка, пользуется поиском если надо. При выборе в переменную также попадает универсальная ссылка.
Для такого случая у датасета желательно в опциях определить 2 вещи:
Представление записи – опция view_template. Можно использовать html. Имена полей указываются в фигурных скобках. Можно разместить в представлении несколько полей. Например {name}, {barcode}. Можно использовать html. Например {name}:{article}
Можно указать форму элементов списка list_layout – имя контейнера (по умолчанию AUTO)
Пример создания и указания опций датасета:
datasrv = CreateDataSet("goods")
datasrv.setOptions(json_to_str({"list_layout":"item","view_template":"{name} , <b>{article}</b>"}))
Можно использовать конструкцию с | чтобы разместить поле с заголовком
- Для задания настройки полей есть упрощенный вариант и вариант с настройками. Упрощенный вариант приведен выше, а для настроек необходимо указать JSON-настройки (обычно - через переменную)
dataset (обязательно) – имя датасета
inline – поиск по строке непосредственно в поле
select – кнопка выбора из списка
spinner – выбор из списка (аналог выпадающего списка) заменяет опцию inline
hint - подсказка
Выбранные и предустановленные значения¶
Везде используется универсальная ссылка - как результат пользовательского выбора, так и для установки предопределенных значений.
Например, создадим датасет nds
datasrv = CreateDataSet("nds")
datasrv.setOptions(json_to_str({"view_template":"Ставка - {name}"}))
nds_list = []
nds_list .append({"name":"10%","_id":"НДС10"})
nds_list .append({"name":"20%","_id":"НДС20"})
nds_list .append({"name":"0%","_id":"НДС0"})
datasrv.put(json_to_str(nds_list))
И на экране в onStart установим НДС по умолчанию
hashMap.put("nds","nds$НДС20")
Тогда, при открытии, увидим результат:
ActiveCV¶
CV-возможности подробно разобраны в разделе ActiveCV
Поле карты¶
Векторные карты подробно разобраны в разделе Векторный редактор
HTML-поле¶
Примечание
В данном разделе речь идет о элементе экрана HTML, но по большей части это справедливо и для команды PrintPreview которая открывает HTML-поле для предпросмотра и печати.
На экране можно разместить HTML-поле. В значение нужно передать HTML-документ, тогда отобразится в виде HTML.
Также этот элемент содержит поддержку Javascript и может выполнять cкрипты в документе. Связь с Андроид-приложением (генерация события в SimpleUI) происходит через функцию onInput
Пример реализации обработчиков кнопок.
<input type="button" onclick="callJS('Кнопка 1')" value="Кнопка 1">
<input type="button" onclick="callJS('Кнопка 2')" value="Кнопка 2">
<script type="text/javascript">
function callJS(param) {
Android.onInput(param);
}
</script>
Для подготовки HTML можно использовать, например шаблонизатор Jinja. Подробнее о приемах разработки написано тут https://infostart.ru/1c/articles/1760354/
Кстати, файлы макетов необязательно хранить в виде строк в обработчиках, для этой цели вполне хорошо подходят Медиафайлы. Можно прицепить несколько макетов к конфигурации и использвоать их.
Произвольная разметка экранов (XML-разметка)¶
Альтернатива конструктору и контейнерам - произвольная разметка экранов, в том виде, в котором она существует в нативной разработке. С соответствующими инструментами работы. Подробно описана в статье https://infostart.ru/1c/articles/1983895/