Как разработать WYSIWYG-редактор на Android так же, как Medium

Если вы разработчик, то вы, должно быть, были на Medium либо для чтения, либо для письма. Нет никаких сомнений в том, что это сервис мирового класса для блоггеров, а его пользовательский интерфейс является отраслевым стандартом для сайтов блогов.

Индекс —
  1. Что такое WYSIWYG-редактор?
  2. Внутренняя архитектура редактора.
  3. Как хранить контент?

Этот блог поможет вам понять, как думать, когда вы хотите создать редактор, какие строительные блоки и основные правила, на которые вы должны обратить внимание.
Я также дал ссылку на мой пример в конце этого блога для справки на случай, если вы где-то застряли или хотите напрямую пройтись по коду.
Итак, начнем, вот…

Что такое WYSIWYG-редактор?

WYSIWYG — это аббревиатура от «что видишь, то и получаешь». WYSIWYG-редактор — это система, в которой содержимое можно редактировать в форме, очень похожей на его внешний вид при печати или отображении в виде готового документа.
Как выглядит средний редактор?
1*4V7arzDmzqS4mtbE5A7aNA.png


Выше скриншот редактора, это чистый и интуитивно понятный интерфейс. Все инструменты редактирования представлены на нижней панели инструментов. Пользователь может ввести свой контент и отформатировать его соответствующим образом.
Сразу кажется, что это пользовательский EditText, который использует Spannables для форматирования своего содержимого. Но, используя spannable, было бы сложно управлять форматом длинного текста, такого как 10 000 слов. Согласно документам,

Это интерфейс для текста, к которому можно присоединять и отсоединять объекты разметки.
Прикрепите указанный объект разметки к началу диапазона…концу текста.

По сути, spannable выполняет операцию поиска строки от начала до конца индекса, а затем применяет тип Spans. При каждом изменении символа в тексте редактирования ему придется обновлять интервалы. Это включает в себя множество операций за конечное время, следовательно, это повлияет на производительность рендеринга пользовательского интерфейса и приведет к ужасному опыту, когда пользователь пытается слишком быстро печатать или слишком быстро удалять какой-либо контент.
Итак, чтобы проверить, давайте углубимся и попробуем рассмотреть «решетки за бетоном».


Внутренняя архитектура редактора

Рентген редактора

1*I4tQlfvDh8deqd527JS5Gg.png
Данное изображение представляет собой среднее приложение, открытое в режиме разработчика с включенным режимом. Активный курсор находится внутри рамки. Это поле по-прежнему является редактируемым текстом. Теперь давайте посмотрим еще один скриншот, когда мы что-то набираем

1*9CMzX-oqmejBai3N2ZN8_w.png

При вводе чего-либо Когда мы нажимаем ввод, курсор перемещается на новую строку и создается другое поле. Отсюда можно сделать вывод, что это не единый редактируемый текст и спаны не используются.
Если мы продолжаем нажимать Enter, добавляются новые поля. Итак, вот концепция —

Думайте о редакторе как о контейнере, и элементы добавляются/удаляются в/из него в зависимости от действий пользователя (ввод или нажатие). Каждый элемент представляет собой объект с независимым стилем, будь то полужирный шрифт, H2 или блочная цитата, изображение или элемент списка и т. д.

Теперь давайте узнаем больше об этом,

Основы внутренней архитектуры

Существует родительский вид, который добавляет вид в вертикальном порядке. В Android это просто может быть расширенная версия LinearLayout в вертикальной ориентации.

Первоначально в стек добавляется текст редактирования, который находится в фокусе. До тех пор, пока пользователь не нажмет Enter, содержимое переходит к тому же тексту редактирования.

После нажатия клавиши ввода в стек вставляется новый текст редактирования. Родительское представление отслеживает индексы каждого представления, добавленного в стек, а также представления, находящегося в фокусе. Взгляните на скелет —

1*dDalcjLvl3U32_0pB6GWtg.png

Костяк нашего редактора Думаю, внутренний костяк ясен. Теперь давайте посмотрим на часть форматирования.

Основные строительные блоки редактора

В нашем базовом редакторе мы будем поддерживать —

  1. Стили заголовков, такие как H1, H2…H5.
  2. Жирный, курсив
  3. Цитаты
  4. Изображение
  5. Упорядоченные/неупорядоченные списки
  6. Горизонтальные разделители

Мы можем отсортировать список и классифицировать их по группам, например.
Группа 1: стили заголовков, полужирный шрифт, курсив, цитаты, списки.
Группа 2: Изображение
Группа 3: Горизонтальные разделители
Здесь мы сгруппировали элементы на основе свойств, необходимых для их отображения. Другими словами, Текст, Изображение (мультимедиа) и Горизонтальный разделитель.

Действия, которые мы можем выполнить с группой 1 —

  1. Мы можем использовать Edittext для ввода.
  2. Применяйте стили заголовков с помощью шрифтов.
  3. Показать цитату, изменив фоновое представление edittext.

Следовательно, мы можем создать собственный текст редактирования. В этом представлении будут храниться все примененные конфигурации. Мы прочитаем их все, пока собираем данные редактора (рассмотренные позже) и сохраняем их на устройстве или отправляем на сервер.

Для группы 1: у нас может быть собственное представление со всеми параметрами. Этот блок (представление) будет добавлен или удален из редактора.

Действия, которые мы можем выполнить с группой 2-

  1. Мы используем ImageView для отображения изображения.
  2. Подписи к изображениям можно делать через Edittext.

Это может быть пользовательское представление, состоящее из ImageView и Edittext (для подписи к изображению). Он будет отвечать за загрузку изображения на сервер и сохранение самого URL-адреса. Кроме того, ему необходимо сохранить текст, введенный в EditText.

Для группы 2: у нас может быть пользовательский вид с ImageView и Edittext.

Действия, которые мы можем выполнить с группой 3 —

Это самая простая часть, это будет простой вид, который будет рисовать линию.

Для группы 3: у нас может быть представление с возможностью рисования линий.

Чтобы сделать стабильный редактор, нам нужно сделать его реакции подлинными. Итак, есть несколько основных правил, которые необходимо соблюдать.

Правила редактора

  1. Изначально будет редактируемый текст с курсором на нем.
  2. Если пользователь набирает абзац и нажимает ввод, нам нужно добавить еще одну строку (edittext).
  3. Если пользователь применяет стиль, он будет применяться ко всему содержимому блока.
  4. Если пользователь помещает курсор в середину текста и нажимает ввод, взять содержимое после курсора -> Вставить новый блок -> скопировать в него содержимое.
  5. Если пользователь пытается вставить изображение, возьмите индекс текущего сфокусированного представления и вставьте под ним новый блок изображения. Кроме того, вставьте блок EditText под изображением (чтобы пользователь мог нажать на изображение ниже и продолжить писать).
  6. Если пользователь удаляет все содержимое блока, перейдите к предыдущему блоку редактирования.

Это некоторые основные правила из множества правил, которые можно применять аналогичным образом.


Как хранить контент (текст, изображение…)?

До сих пор мы рассмотрели структурную часть редактора. Теперь давайте перейдем к хранению контента. Мы не можем хранить простой текст и URL-адреса напрямую, потому что это требует большого количества стилей. В этой части будет рассказано, как текст должен храниться на сервере и устройстве, а также для его правильного отображения.

Структура хранения данных

У нас будет вспомогательный класс, который будет проходить через родительский контейнер и собирать следующую информацию из каждой группы. Группы, которые мы определили ранее.
Из группы 1: тип объекта (текст), текст и стили.
Из группы 2: тип объекта (изображение), URL-адрес изображения и текст подписи.
Из группы 3: тип сущности.

Это одна из структур хранения блогов —

1*eMiO1gKttZIuF0qlp1-WjQ.png

После того, как мы соберем данные в этом формате, мы можем отправить их на сервер или сохранить как черновик.

Отображение данных

Теперь, если пользователь вернется к черновой версии блога, нам нужно прочитать структуру JSON, а затем подготовить представление в соответствии с ней. Вот как это делается —

  1. Прокрутите массив сущностей в наших данных JSON.
  2. Создайте экземпляр объекта определенного типа (текст, изображение или HR) и настройте их с заданными данными.
  3. Добавьте сущность в родительское представление.
  4. Сосредоточьтесь на первом ребенке.

Теперь мы успешно восстановили структуру черновика из необработанных данных.


Образец репозитория для справки —

1*dTosVbNDmOAIXVQvsa039g.jpeg

Я реализовал версию редактора, которая служит редактором WYSIWYG Markdown. В настоящее время используется в Приложение 1Ramp (приложение для социальных сетей).
Вы можете просмотреть исходный код на Гитхаб.
Не стесняйтесь задавать свои сомнения в комментариях.

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *