Всем привет. Так случилось, что некоторое количество лет назад я отринул мирское и встал на тернистый путь проектировщика и дизайнера интерфейсов. Тогда было мало толковых материалов по теме, сейчас ситуация вроде бы исправилась, но, на мой взгляд, как то однобоко. На данный момент существует множество ресурсов, где подробно и доступно расскажут о том, как прототипировать сайты и мобильные приложения, как подобрать цвета и сделать красивую картинку. Но практически отсутствует информация по разработке интерфейсов для десктопных и сложных веб приложений, что подразумевает свою специфику в работе. Они конечно есть, но существует в них один пробел — они рассматривают общую теорию и редко дают практические советы. Попробуем исправить ситуацию.
Для начала небольшое отступление. Все, о чем я буду рассказывать, — не есть объективная истина. Это просто выводы, которые я сделал из своего личного/частного опыта, и совершенно не удивительно, если какие-то из них окажутся не верными, а решения, применяемые мной, — не самыми практичными. Буду только рад, если вы меня поправите. Далее я постараюсь на простых примерах рассказать, как я проектирую интерфейсы, каковы общие подходы и методы, на что стоит обратить внимание и как все это реализовать на практике. В конце поста я приложил ссылку на получившийся прототип.
Давайте попробуем сделать прототип таблицы. Чтобы не зарыться в данных, предлагаю взять некую абстрактную таблицу учета клиентов. Дизайн для простоты возьмем по мотивам Google Material.
Вводные требования:
Отображение контента
Сортировка контента
Фильтрация (например, за последний день)
Чтобы чем-то наполнить нашу таблицу, возьмем несколько позиций:
ФИО
Пол
Возраст
Телефон
Электронная почта
Дата регистрации
Естественно, в боевых условиях всю эту информацию вам или аналитику придется получать в процессе общения с заинтересованными и не очень лицами. Как толково провести сбор информации с контингента и грамотно с ней обойтись, я расскажу в одном из следующих выпусков.
Для начала сделаем разметку согласно дизайну. Открываем гайд Google Material и внимательно читаем. Потом расставляем направляющие и размещаем название таблицы и шапку с названиями колонок. Естественно, когда у нас нет никаких гайдов по дизайну, мы компонуем и оформляем контент сами, либо передаем прототип с примерной компоновкой на дизайн специально обученному человеку.
По итогам получаем следующее:
Рис. 1
Теперь настала очередь “тела” таблицы, в которой будет размещаться контент. Тут все не так просто. В Axure есть стандартный виджет “Table”, который нам совершенно не подойдет. На выходе мы получим набор ячеек, с которыми почти ничего нельзя сделать, в то время как наша цель — разумно приблизить прототип по интерактивности к конечному приложению. Заметьте, “разумно приблизить” — то есть затратив наименьшее количество времени, сделать максимально приближенный к живому приложению прототип. Иными словами нам нужно постараться сделать так, чтобы при использовании прототипа вопросов, как работает тот или иной элемент, оставалось как можно меньше. Такой подход может спасти вас от неприятных сюрпризов в будущем, когда вы, сделав поверхностное допущение относительно работы элемента (“Ну, тут все понятно”) и не проработав его, можете нарваться на переделку половины прототипа (а такое бывает).
Возвращаемся в Axure. Чтобы сделать адекватную таблицу я пользуюсь виджетом “Repeater”. Он работает следующим образом: по сути это динамическая панель, размноженная необходимое количество раз. Может содержать любые объекты и к каждому объекту мы можем привязать значение из базы (база располагается на панели справа).
Рис. 2
Итак мы вытащили репитер в рабочую область и теперь начинаем его настраивать. Двойным кликом заходим внутрь репитера и меняем размер стандартного прямоугольника на размер стандартной строки таблицы в Google Material — 40px высотой. Ширину задаем от фонаря — 1000рх (это будет ширина нашей таблицы). Настраиваем Interaction Style для строки.
Далее накидываем контейнеры, в которые будем класть контент (в нашем случае — текстовые виджеты). Из опыта — рекомендую вписывать название соответствующей колонки и называть сам контейнер точно так же. Это нам понадобится для присвоения значений из базы.
Рис. 3
Теперь наполняем базу. По сути нам необходимо создать точно такую же таблицу, которую мы хотим видеть в прототипе. Следовательно называем каждый столбец базы так же, как называются наши контейнеры. Лучше всего сохранить порядок, в котором идут столбцы, для удобства последующих корректировок.
Рис. 4
Следующим шагом наполняем базу контентом. На этом шаге нужно сесть и подумать о “фактуре” контента, то есть прикинуть, где и какое количество знаков может быть. Из наших требований можно вычленить, что предположительно самые длинные надписи будут содержаться в колонках ФИО и Электронная почта. Именно в них мы и должны показать на прототипе, как будет выглядеть максимально длинный и максимально короткий контент. Исходя из этого приступаем к наполнению.
Рис. 5
Как видите, я использовал абсурдно длинные и максимально короткие примеры, чтобы показать крайние случаи заполнения, а также, средней длины ФИО, чтобы показать наиболее вероятное наполнение таблицы. Не лишним будет продемонстрировать, как поведет себя надпись, не поместившаяся в колонку. Для полного реализма некоторые надписи набраны без соблюдения регистра, а некоторые — латиницей, ибо профессиия обязывает нас быть пессимистами.
Привязываем наши контейнеры к соответствующим айтемам базы. Делается это через событие “OnItemLoad”, на которое мы назначаем action ”Set Text”. В этом действии мы находим наш репитер (репитер обязательно называем заранее) и включаем чекбокс на необходимом контейнере. Устанавливаем значение текста равным айтему из базы, это можно сделать через контрол “fx”, выбрав через “Insert Variable or Function...” необходимый айтем, а можно просто написать в поле ввода “Set text to” [[Item.имя_колонки_которую_вы_хотите_присвоить]]. На это же действие навешиваем остальные айтемы.
Рис. 6
Теперь репитер автоматически возьмет данные из базы.
Рис. 7
Выравниваем названия столбцов в шапке относительно контента репитера и смотрим в браузере, что у нас получилось.
Рис. 8
Обнаруживаем неприятный момент: при наведении на текст внутри строки у нее сбрасывается MouseOver. Исправляем это, зайдя внутрь репитера и объединив все его содержимое в группу, после чего в свойствах группы ставим галочку “Triggered Mouse Interaction Style” — то есть указываем, что все объекты в группе будут менять свои состояния одновременно при действиях с любым из них. (На самом деле это можно не делать, но мне кажется такие мелочи — это обычная аккуратность и дисциплина в работе). Проверяем. Работает.
Рис. 9
Осталось только показать скролл. Для этого мы переводим таблицу в динамическую панель и уменьшаем до нужного размера. Теперь весь контент, который попадает за границу динамической панели, обрезается. Чтобы сделать прокрутку в настройках динамической панели выбираем из дропбокса “Scrollbars” пункт “Vertical as Needed”. Смотрим в браузере, скрол работает.
Рис. 10
Но так же появился программный скролбар, который сильно выбивается из общего дизайна и наползает на таблицу. Чтобы его скрыть придется воспользоваться индейской хитростью. Ширина программного скролбара — 17px, добавляем их к ширине динамической панели и сверху на него кладем плашку цвета фона. Все, скрол не видно. Теперь рисуем подходящий скролбар. Новый скролбар не будет двигаться при прокрутке, но это мы оставим как есть, потому что помним: нам нужно сделать прототип в разумные сроки (хотя, конечно, Axure позволяет нам сделать и это).
Рис. 11
Возвращаемся к списку требований. Мы сделали отображение контента — это пункт первый. Переходим ко второму — Сортировке.
Сортировку очень просто организовать именно через репитер. Как раз для этого он и сделан. Чтобы маркировать сортировку я буду использовать иконку “caret down” из Awesome font. Иконка будет появляться рядом с названием колонки, по которой мы будем сортировать контент. Делаем из названия колонки динамическую панель, добавляем ей два новых состояния. Первое состояние называем “Unsorted”, второе — “Sorted_Ascending”, третье — “Sorted_Descending”. Во второе состояние копируем текст из первого и ставим иконку-маркер справа, в третье копируем все объекты из второго и переворачиваем иконку на 180 градусов. Таким образом мы подготовили для прототипирования три состояния сортировки: Не отсортировано, Отсортировано по восходящей, Отсортировано по нисходящей.
Рис. 12
Теперь заставим все это работать. Выбираем нашу панель и назначаем на событие “OnClick” действие “Set Panel State”, в котором меняем состояние панели на “Next” и включаем чекбокс “Wrap from last to first”, то есть, наша динамическая панель будет менять свои состояния по кругу. Также на “OnClick” назначаем действие “Ad sort”, в котором выбираем наш репитер и указываем имя сортировки (пригодится, когда мы захотим ее отменять), выбираем колонку, по которой будет происходить сортировка, как сортировать содержимое колонки (как текст, цифры или даты) и порядок сортировки (по возрастанию, по убыванию или переключением от одного к другому). Готово. Теперь по клику на названии колонки у нас будет происходить сортировка, сначала по возрастанию, потом по убыванию, а при третьем клике — снова по возрастанию, но маркер будет исчезать, имитируя сброс сортировки.
Рис. 13
Проделываем то же самое для остальных колонок, которые вы планируете сортировать. Теперь у нас есть вполне рабочая сортировка в прототипе. Чтобы не тратить много времени, я рекомендую, сделать две колонки с сортировкой (см. прототип, колнки: “Имя” и “Пол”). В сопроводительной документации необходимо детально описать работу по сортировке контента.
Третий пункт требований — Фильтрация. Для примера будем фильтровать по дате “За сегодня”. За текущую дату возьмем последнюю дату в контенте. И снова благодаря тому, что мы использовали репитер, сделать это достаточно просто. Контролом для фильтрации у нас будет чекбокс, по событию “OnSelected” мы назначаем действие “Add Filter” из вкладки действий с репитерами, называем этот фильтр “Today” (в данном случае название обязательно, но в целом я вообще рекомендую завести привычку называть объекты как можно тщательней; это дисциплинирует и в разы повышает скорость внесения корректировок в прототип). В поле “Rule” (правила, по которым будет происходить фильтрация) пишем следующее: [[Item.название колонки по которой необходимо фильтровать=='значение для фильтрации’']] (если кто еще не догадался, Axure использует логические операторы из Java; если их выучить, работа упростится в разы). Должно получится следующее:
Рис. 14
Для отмены фильтрации в том же чекбоксе вешаем на событие “OnUnselected” действие “Remove filter” (указав имя фильтра, которое мы задали ранее).
Рис. 15
На закуску еще одна индейская хитрость. Чтобы сделать таблицу с закрашенными через одну строками, нужно сделать соответствующую полосатую подложку под репитер, а в самом репитере поменять прозрачность нормального состояния подложки на ноль (естественно в этом случае лучше убрать возможность прокрутки таблицы, потому что контент будет прокручиваться над неподвижной подложкой).
Вот в общем и все. При грамотном подходе на всю работу тратится около часа-полутора, а на выходе мы получаем, весьма правдоподобно работающий прототип, который можно прогонять через тестирование и который дает возможность достаточно подробно разобраться в его функционале. Конечно в большинстве случаев такая проработка не нужна, особенно если вы работаете в студии и времени у вас всегда в обрез. Но, как я говорил выше, мы рассматриваем работу над сложными десктопными и веб приложениями, которые, как правило, ведутся продуктовыми компаниями со своим штатом проектировщиков и дизайнеров. Соответственно, времени для погружения в проект и для более детальной его проработки у вас более чем достаточно. Конечно, в ваших же интересах с самого начала делать такой прототип, который будет легко редактировать и главное легко понимать, открыв его через год после сдачи в разработку.
→ Cсылка на получившийся в итоге прототип
В следующих выпусках я постараюсь рассказать, какие использую методы для оптимизации своей работы. Будет про интересное, а на сегодня все.
Спасибо за внимание.
Автор: Alex_Derik