- PVSM.RU - https://www.pvsm.ru -
Не всегда же только пользоваться. Именно с такой мысли началось написание библиотеки под Android и последующее написание этой статьи. Вдруг кому пригодится. Под катом то, что в итоге получилось.
Одним долгим зимним вечером у нас с друзьями разгорелся спор, как реализовать один из необходимых функционалов. Необходимо было написать *нечто*, что смогло бы:
Как самому активному, мне не терпелось испробовать силы, и в первую же ночь была написана view, которая на основе дерева формулы рисовала формулу. Посмотрели друзья на это дело и выдвинули еще требования.
Пригорюнился добрый молодец, почесал головушку и сел писать библиотеку. А чтобы было еще интереснее, поставил я себе дополнительно условие:
Здесь не будет поэтапного расписывания как написать библиотеку и как ее опубликовать – в интернете, и в том числе на Хабре, уже есть инструкции на этот счет. Я немного расскажу о своей логике, о тех проблемах и сложностях, с которыми столкнулся и как их решал. Кому-то это покажется банальным, кому-то неправильным – не претендую на верное решение и все замечания учту. Надеюсь, что кому-то пригодится эта статься или библиотека. Ссылка на github будет в конце. В описании к репозиторию есть ссылка на демо библиотеки и инструкция к ней.
К этому этапу у меня была моя первоначальная демка, требования и твердая уверенность, что все получится. Перво-наперво было решено взяться за отрисовку, а преобразование из строки в дерево оставить напоследок.
И так, логика дерева такова:
Лист – это набор символов. Например знак умножения или какое-то число. Лист знает о своих размерах, о том, есть ли после него кто-то, и как их расположить относительно себя. Я выделил несколько видов.
Чтобы логика работала, каждый лист должен уметь:
Чтобы максимально заполнить разрешенную область, перед отрисовкой идет этап масштабирования. Принцип прост. У меня есть единичный блок, на основе которого идут все расчеты и переменная, отвечающая за то, во сколько раз надо увеличить масштаб. Логика масштабирования такова: получаем размер формулы, сравниваем с размерами доступной области, изменяем коэффициент масштабирования.
И тут я столкнулся с небольшой проблемой. Ширина текста увеличивается не пропорционально атрибуту textSize. То есть, пусть у нас был блок текста шириной y и textSize x. Если мы увеличим textSize в 2 раза – ширина блока не будет равна 2*y. В связи с этим, значение масштабирования постоянно колебалось в близких значениях, из-за чего картинка при перерисовке «дрожала». Для решения этой проблемы я видел 2 способа:
Пойдя по второму методу, я столкнулся с проблемой в самом первом расчете, когда коэффициент еще равен 1. Что бы решить это, поначалу, я делал расчет по второму методу 2 раза, но это сказалось на производительности. Чтобы избежать второго лишнего расчета, было решено сохранять предыдущее значение и сравнивать его с новым. Если они одинаковые, то второй раз считать смысла нет. Подумав еще, я вынес пересчет в метод onSizeChanged, а так же дополнительно вызывал при задании новой формулы/листов для движения.
Здесь все очень просто. Была принята маленькая хитрость. Вместо движения листа, который мы выделили, мы скрываем его и заводим новый, координаты которого постоянно меняем при срабатывании onTouchEvent. Когда срабатывает MotionEvent.ACTION_DOWN, мы ищем, не попало ли наше касание на двигаемый лист, скрываем его и копируем значение в лист, который двигаем. Когда срабатывает MotionEvent.ACTION_UP, мы пробегаем по дереву и смотрим, не пересекаемся ли мы с каким-либо Changeable листом.
Тут в некой мере решение в лоб. Для начала было определено 2 спец. символа. Первый указывает на те блоки, которые станут Changeable. Второй символ — парный, указывает область, которую следует определить как Constable или Changeable без внутренних преобразований (например, символ деления). Получаем строку, удаляем все пробелы, что не входят в область выделенную вторым спец. символом, преобразуем знаки деления и начинаем посимвольно считывать. Чтобы можно было удобнее все преобразовывать, знаки деления из вида 2/3 преобразуются в /(2)(3).
Для простоты кастомизации, почти все переменные, которые фигурируют в коде отрисовки или парсера, вынесены в отдельные поля классов. В связи с чем можно успешно поменять почти все, что видишь.
Как оказалось, данная библиотека вполне подходит под «формулы» не только математические, но и, например, на проверку знаний словарных слов. Еще хотелось бы добавить на будущее, для тех кто тоже решит писать свои библиотеки – в android studio есть создание модуля-библиотеки, и удаляйте все из тега application в манифесте библиотеки. Если есть какие-либо вопросы – с радостью отвечу. Все замечания и пожелания учту.
→ Библиотека на github [1]
Автор: KuSu
Источник [2]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/android/243142
Ссылки в тексте:
[1] Библиотека на github: https://github.com/KuznetsSudby/FormulLib
[2] Источник: https://habrahabr.ru/post/321792/?utm_source=habrahabr&utm_medium=rss&utm_campaign=sandbox
Нажмите здесь для печати.