Java андроид программирование рисование толщина линий

Работаем с графикой. Основы

Цель нашего урока — понять основы графики. Мы напишем простую рисовалку — хотя это слишком громко сказано. Пока мы сами рисовать ничего не будем — за нас это будет делать глупая машина, т.е. Android. Но тем не менее некоторые полезные вещи мы узнаем, а значит повысим свой профессиональный уровень. Продолжить своё обучение можно в разделе Котошоп.

Создадим новый проект SimplePaint. Создадим новый класс Draw2D, который будет наследоваться от View. Именно в этом классе мы и будем проводить графические опыты. Щёлкаем правой кнопкой мыши на имени пакета и выбираем в меню New | Kotlin Class/File или New | Java Class. В открывшемся диалоговом окне устанавливаем имя для класса Draw2D.

В данном коде мы наследуемся от класса android.view.View и переопределяем метод класса onDraw().

Далее необходимо загрузить созданный класс при старте программы. Открываем основной файл активности MainActivity и заменяем строчку после super.onCreate(savedInstanceState):

В нашем случае мы говорим системе, что не нужно загружать разметку в экран активности. Вместо неё мы загрузим свой класс, у которого есть свой холст для рисования.

Подготовительные работы закончены. Перейдём к графике. Весь дальнейший код мы будем писать в классе Draw2D. Совсем коротко о теории рисования. Для графики используется холст Canvas — некая графическая поверхность для рисования. Прежде чем что-то рисовать, нужно определить некоторые параметры — цвет, толщина, фигура. Представьте себе, что вы рисуете на бумаге и в вашем распоряжении есть цветные карандаши, фломастеры, кисть, циркуль, ластик и т.п. Например, вы берёте толстый красный фломастер и рисуете жирную линию, затем берёте циркуль с жёлтым карандашом и рисуете окружность. Улавливаете аналогию? Теория закончена.

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

Итак, холст готов. Далее начинается собственно рисование. Следуя описанному выше принципу мы задаём перед каждым рисованием свои настройки и вызываем нужный метод. Например, для того, чтобы нарисовать жёлтый, круг мы включаем режим сглаживания, устанавливаем жёлтый цвет и вызываем метод drawCircle() с нужными координатами и заливаем окружность выбранным цветом. Получилось симпатичное солнышко.

Всегда соблюдайте очерёдность рисования. Если вы поместите данный код до заливки холста белым цветом, то ничего не увидите. У вас получится, что вы сначала нарисовали на стене солнце, а потом заклеили рисунок обоями.

Для рисования зелёного прямоугольника мы также задаём координаты и цвет. У нас получится красивая лужайка.

Далее выведем текст поверх лужайки, чтобы все видели, что она предназначена только для котов. Устанавливаем синий цвет, стиль заливки, режим сглаживания и размер прямоугольника, в который будет вписан наш текст.

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

И завершим нашу композицию выводом рисунка из ресурсов.

В данном примере я вручную подбирал размеры и координаты фигур для экрана свого телефона. В реальных приложениях необходимо сначала вычислить размеры экрана у пользователя, а потом уже выводить фигуры в соответствии с полученными результатами. Иначе получится так, что некоторые элементы композиции просто не попадут на экран при вращении устройства. Допустим, в альбомном режиме вы установите у точки X значение 800, но в портретном режиме ширина экрана будет, скажем, 480, и точка окажется вне поле зрения. Поэтому следует позаботиться о вычислениях размеров экрана и плясать от этой печки. Ниже представлен немного переделанный вариант для общего понимания.

Финальный рисунок выглядит следующим образом в двух ориентациях. Вы можете доработать приложение, уменьшив размеры кота и т.д.

Источник

Класс Canvas

Класс android.graphics.Canvas (Холст) предоставляет методы для рисования, которые отображают графические примитивы на исходном растровом изображении. При этом надо сначала подготовить кисть (класс Paint), который позволяет указывать, как именно графические примитивы должны отображаться на растровом изображении (цвет, обводка, стиль, сглаживание шрифта и т.д.).

Android поддерживает полупрозрачность, градиентные заливки, округлённые прямоугольники и сглаживание. Из-за ограниченных ресурсов векторная графика пока что не поддерживается, вместо этого используется традиционная растровая перерисовка.

Canvas работает с пикселями, поэтому следует заботиться о конвертации единиц dp в px и наоборот при необходимости. Начало координат находится в левом верхнем углу.

Получить доступ к холсту можно через объект Bitmap или компонент View. Очень часто разработчики создают свой собственный компонент, наследуясь от View, и рисуют на его холсте для реализации своих замыслов.

Методы

Ниже представлены некоторые методы класса Canvas, которые что-то рисуют.

  • drawARGB()/drawRGB()/drawColor(). Заполняет холст сплошным цветом.
  • drawArc(). Рисует дугу между двумя углами внутри заданной прямоугольной области.
  • drawBitmap(). Рисует растровое изображение на холсте. Вы можете изменять внешний вид целевой картинки, указывая итоговый размер или используя матрицу для преобразования.
  • drawBitmapMesh(). Рисует изображение с использованием сетки, с помощью которой можно управлять отображением итоговой картинки, перемещая точки внутри неё.
  • drawCircle(). Рисует круг/окружность с определённым радиусом вокруг заданной точки.
  • drawLine(s)(). Рисует линию (или последовательность линий) между двумя точками.
  • drawOval(). Рисует овал на основе прямоугольной области.
  • drawPaint(). Закрашивает весь холст с помощью заданного объекта Paint.
  • drawPath(). Рисует указанный контур, используется для хранения набора графических примитивов в виде единого объекта.
  • drawPicture(). Рисует объект Picture внутри заданного прямоугольника.
  • drawPoint(). Рисует точку в заданном месте.
  • drawPosText(). Рисует текстовую строку, учитывая смещение для каждого символа.
  • drawRect(). Рисует прямоугольник.
  • drawRoundRect(). Рисует прямоугольник с закруглёнными углами.
  • drawText(). Рисует текстовую строку на холсте. Шрифт, размер, цвет и свойства отображения текста задаются в соответствующем объекте Paint.
  • drawTextOnPath(). Рисует текст, который отображается вокруг определённого контура.
  • drawVertices(). Рисует набор треугольников в виде совокупности вершинных (вертексных) точек.
  • rotate() и restore(). Вращение холста
  • Методы scale() и translate(). Изменение и перемещение координатной системы
Читайте также:  Плеер для андроид плеер по папкам для андроид

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

Метод drawArc()

В API 21 появилась перегруженная версия метода, в котором можно указать координаты двух точек вместо RectF.

Метод drawArc() позволяет рисовать дуги и сектора. Ниже приводится код для трёх вариантов: сектор с заливкой (похож на PacMan), сектор без заливки (контур) и часть дуги:

Метод drawBitmap()

Вывести готовое изображение просто.

Метод drawCircle()

Первые два аргумента определяют координаты центра окружности/круга, следующий аргумент — её радиус в пикселах, последний — объект Paint. В зависимости от выбранного стиля кисти можно нарисовать закрашенный круг или только окружность.

Нарисуем зелёный круг.

drawLine(s)()

Простой метод — указываем начальные и конечные координаты отрезка.

Метод drawOval()

Метод drawOval() рисует овалы. Естественно, если вы зададите одинаковые размеры ширины и высоты, то получите круг/окружность.

Если вам нужно наклонить овал в ту или иную сторону, то поверните холст на требуемый угол с помощью метода rotate(). Не забудьте потом повернуть холст обратно, что следующие фигуры выводились нормально.

Повернём синий овал из предыдущего примера:

В API 21 появилась перегруженная версия метода, в котором можно указать координаты двух точек вместо RectF:

Метод drawPaint()

Метод позволяет закрасить весь холст одним цветом.

Метод drawRect()

У метода существует три перегруженные версии для рисования прямоугольника. Рассмотрим один из них:

Метод drawRoundRect()

Для рисования прямоугольников с закруглёнными углами используется метод drawRoundRect (RectF rect, float rx, float ry, Paint paint).

В параметрах указываются ограничивающий прямоугольник, радиусы овалов для скругления углов и кисть.

Реализуем три разных способа:

В API 21 появилась перегруженная версия метода, в котором можно указать координаты двух точек вместо RectF.

Метод drawPath()

Для рисования соединённых отрезков можно использовать метод drawPath(), указав в параметрах настройки для рисования и массив координат точек. Для удобства добавим в класс Draw2D новый класс Pt, который позволит быстро создать массив точек с заданными координатами. Далее настраиваем объекты для рисования и формируем путь через созданный массив. В результате получим кошкин дом.

Путь можно составлять не только из точек, но и из фигур, например, дуг. Сначала формируем дугу, добавляем её в путь при помощи метода Path.addArc(), повторяем операцию снова несколько раз, а в конце выводим окончательный вариант:

Можно нарисовать символ парашюта:

Метод drawPoint()

Простой метод для рисования точки в нужно месте указанной кистью. Для координат используются значения типа float.

Метод drawText()

С помощью метода drawText() можно выводить текст в заданной позиции. Добавим сначала несколько эффектов, чтобы казалось, что текст парит над поверхностью:

Центрируем текст

Есть небольшая тонкость, если вам захочется вывести текст в центре холста. Проблем с вычислением центра холста и размером текста нет. Центр можно найти, разделив пополам значения ширины и высоты холста. А ширину и высоту текста можно узнать через метод кисти getTextBounds(), который возвращает ограничивающий прямоугольник.

Но вычисление ширины текста через textBounds.width(); приводит к небольшому смещению. Лучше воспользоваться методом кисти measureText(). Тогда текст отцентрируется точнее.

Пример на Kotlin с дополнительной информацией.

Методы rotate() и restore()

Холст во время рисования можно вращать. Во многих ситуациях такой приём менее затратный по ресурсам, чем рисование самого объекта под углом. Суть в следующем: вы поворачиваете холст на нужный градус, рисуете фигуру, а затем возвращаете холст на место при помощи метода restore(), чтобы следующие фигуры рисовались в ожидаемых местах. Иначе остальные фигуры будут рисоваться уже относительно поворота.

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

Вращение происходит вокруг начальной точки холста (0, 0). Но можно также использовать перегруженную версию метода rotate(float degrees, float px, float py), в которой можно указать координаты точки поворота.

Методы scale() и translate()

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

Чтобы установить свою систему координат, нужно произвести трансформацию. В следующем примере мы установим координаты в диапазоне от 0 до 10 и нарисуем график в стандартном виде из точки 0,0 в левом нижнем углу в точку 10,10 в верхнем правом углу.

Для наглядности я добавил на оси несколько точек. Следует обратить внимание, что мы задали диапазон от 0 до 10 и все размеры должны масштабироваться в новых величинах, в том числе и ширина обводки в методе setStrokeWidth(). Поэтому значения должны быть достаточно маленькими, иначе толщина обводки может просто оказаться больше самой фигуры. Кстати, в некоторых случаях с текстом и другими методами рисование масштабирование может сыграть злую шутку и дробные значения не позволят увидеть текст и некоторые линии. В этих случаях приходиться создавать цепочку преобразований, когда временно масштаб увеличивается до нормальных размеров, рисуется текст с подходящим размером шрифта, затем опять всё уменьшается и т.д. Это долгая история.

Читайте также:  Карты оффлайн для андроид какие лучше

Источник

Полный список

— рисуем фигуры
— выводим текст

На прошлом уроке разобрались, как достучаться до канвы. Теперь попробуем поработать с ней, рассмотрим методы рисования точки, линии, круга, дуги, овала, прямоугольника и текста.

Для рисования используются методы draw*. Если посмотреть их в хелпе можно обратить внимание, что одним из их параметров является объект Paint. В этом объекте задаются графические характеристики рисования. Т.е. можно считать, что это кисть, которой будут рисоваться ваши фигуры. Через него вы сообщаете канве цвет и толщину линии для рисования.

Project name: P1421_DrawingFigure
Build Target: Android 2.3.3
Application name: DrawingFigure
Package name: ru.startandroid.develop.p1421drawingfigure
Create Activity: MainActivity

Смотрим класс DrawView. В конструкторе создаем объект Paint, которым будем рисовать фигуры, и объект Rect, который нам понадобится для рисования прямоугольника. Тут сразу обращу внимание, что создавать объекты крайне желательно за пределами метода onDraw, т.к. при частой прорисовке у вас постоянно будут создаваться новые объекты, а это является лишней нагрузкой на сборщик мусора и может замедлить работу приложения. Поэтому создаем мы объекты всего один раз, в конструкторе.

В методе onDraw мы сначала закрашиваем всю канву цветом. Есть различные реализации метода закраски:

drawRGB – на вход требует три компонента RGB (red, green, blue: смешением этих трех цветов можно получать другие цвета и их оттенки).

drawARGB – аналогичен drawRGB, но добавляет использование прозрачности (alpha). alpha + RGB = ARGB.

drawColor – на вход требует ARGB-значение в десятичной системе. Для удобства в классе Color есть несколько констант-цветов. Одну из них (Color.GREEN) мы использовали с этим методом на прошлом уроке.

Если хотите посмотреть, как выглядят различные RGB комбинации, просто загуглите фразу: «таблица цветов».

Мы в нашем приложении используем метод drawARGB и передаем ему значения: прозрачность (80), уровень красного (102), уровень зеленого (204), уровень синего (255). В итоге получаем канву, закрашенную вполне себе приятным для глаз цветом.

Далее настраиваем нашу кисть, она же Paint. Напомню, что эти настройки будут применены к рисованию фигур.

Метод setColor позволяет указать цвет (аналогично методу drawColor у канвы). Кроме этого, у Paint есть метод для указания ARGB – setARGB.

Метод setStrokeWidth позволяет указать толщину линий при рисовании. Мы укажем 10.

Начинаем рисовать объекты.

drawPoint – нарисует точку с координатами (50,50)

drawLine – нарисует линию из точки (100,100) в точку (500,50)

drawCircle – нарисует круг в точке (100,200) с радиусом 50

drawRect – нарисует прямоугольник с левым верхним углом в точке (200,150) и нижним правым углом в точке (400,200)

Далее идет другая реализация метода drawRect. Он принимает на вход объект Rect, в котором ранее были указаны координаты прямоугольника методом set. В итоге метод нарисует нам прямоугольник с верхним левым углом в точке (250,300) и нижним правым в точке (350,500).

Также есть реализация drawRect, которая на вход требует объект RectF – это аналог Rect, но значения используются не int, а float.

И, как вы наверно заметили, все эти draw* методы требуют на вход объект Paint. Это логично, т.к. канва должна знать толщину и цвет линий, которыми мы собрались рисовать.

Все сохраняем и запускаем приложение.

Видим такую картину:

Нулевая точка координат расположена в левом верхнем углу экрана и от нее идет отсчет вправо по оси X и вниз по оси Y. Видим нарисованные нами точку, линию, круг и два прямоугольника.

С этим все понятно. Давайте посмотрим другие методы рисования и будем менять некоторые используемые объекты в процессе.

Перепишем класс DrawView:

Предлагаю вам сразу запустить приложение и посмотреть результат, так мои пояснения будут проще восприниматься.

Смотрим метод onDraw. Первые три строки не менялись, повторяться не буду.

drawPoints – рисует множество точек. Их координаты заданы в виде float массива следующим образом . Соответственно, будут нарисованы точки (x1,y1), (x2,y2), … В нашем примере мы используем массив points.

Есть также следующая реализация этого метода: drawPoints (float[] pts, int offset, int count, Paint paint). Она позволяет указать с какого (offset) по порядку значения в массиве начинать формировать точки и сколько (count) значений брать. Тут не запутайтесь, идет выборка именно значений массива, а не получившихся точек.

drawLines – рисует множество линий. Их координаты заданы в виде float массива следующим образом . Соответственно будут нарисованы линии (x1,y1)-(x2,y2), (x3,y3)-(x4,y4), … В нашем примере используем массив points1.

Аналогично точкам, у этого метода также есть реализация с отступом и количеством: drawLines (float[] pts, int offset, int count, Paint paint), где offset – это отступ, указывающий с какого значения массива брать значения для формирования точек, а count – количество значений, которое необходимо взять.

Методом setColor сменим для разнообразия цвет кисти на зеленый. Тут важно понимать, что все ранее нарисованные объекты останутся красными. А вот последующие будут нарисованы уже зеленым цветом.

drawRoundRect рисует обычный прямоугольник, но со скругленными углами. В объекте rectf мы передаем данные по расположению прямоугольника. Далее два числовых параметра позволяют нам задать радиус скругления по оси X и Y. Тут не смогу объяснить словами про эти радиусы, просто позадавайте различные значения и посмотрите на результат. Чем выше значения, тем более закруглены углы.

Читайте также:  Android options menu button

Далее методом offset выполняем смещение в объекте rectf. На вход передаем смещение по оси X (0) и по оси Y (150). Т.е. был RectF со значениями (700,100,800,150), а стал (700 + 0, 100 + 150, 800 + 0, 150 + 150). Т.е. просто опускаем прямоугольник вниз на 150.

Эта процедура никак не влияет на фигуры, которые уже были нарисованы с использованием этого RectF объекта. Они где были, там и остаются.

drawOval рисует овал, который занимает все пространство в переданном ему прямоугольнике (rectf).

Далее снова меняем координаты объекта rectf, только на этот раз методом offsetTo. Он не добавляет координаты к имеющимся, а устанавливает новую верхнюю левую точку прямоугольника. И прямоугольник смещается к ней, сохраняя при этом свои размеры.

Далее меняем размер прямоугольника rectf методом inset. На вход метод принимает две дельты, на которые он уменьшит прямоугольник по горизонтали (0) и вертикали (-25). Уменьшит на -25 означает, увеличение на 25.

Причем, изменения размера происходят с обоих сторон. Т.е. если меняем размер горизонтально (первый параметр метода): левая и правая сторона приближаются к центру на указанное значение дельты, если дельта положительная и отдаляются от центра, если дельта отрицательная. По вертикали (второй параметр метода) – аналогично относительно центра ведут себя верхняя и нижняя стороны.

Выполнив rectf.inset(0, -25) я увеличиваю размер прямоугольника rectf по вертикали на 25 и вверх и вниз. Итого, размер по вертикали увеличивается на 50. Горизонтальный не меняется.

drawArc – рисует дугу (или можно еще сказать — часть круга), которая занимает предоставленный ей прямоугольник rectf. Далее идут два угловых параметра: начало и длина, в нашем случае это 90 и 270 градусов.

Начало – угол, с которого дуга начинает рисоваться. Отсчет ведется по часовой стрелке от точки «3 часа», если рассматривать часовой циферблат. Т.е. если от трех часов отложить угол 90 градусов, получится шесть часов. С этой точки и начнется рисоваться дуга.

Длина – это угол рисуемой дуги. Т.е. полный круг – это 360 градусов. Соответственно 270 – три четверти круга. Если мы отложим три четверти круга от 6 часов, то получим 3 часа. Такая дуга и должна получится: от шести до трех часов по часовой стрелке.

Следующий boolean параметр определяет, как будут соединены две крайние точки дуги. Т.е. если рассматривать наш пример, то это точки 6 и 3 часа. Между ними по часовой проходит дуга, но чтобы получилась замкнутая фигура, необходимо соединить между собой эти точки. Тут два варианта: от каждой точки будет проведена прямая к центру круга и в итоге через центр дуга замкнется, либо просто проводится прямая между этими точками. Соответственно если параметр true – то точки соединяются через центр, если false – то между собой. В нашем случае – это true.

Далее опускаем прямоугольник на 150 вниз. И снова рисуем такую же дугу, но теперь с параметром false. Концы дуги будут соединены между собой напрямую.

Далее устанавливаем ширину линии в 3 px. И рисуем вертикальную линию с X = 150. Она понадобится, чтобы показать выравнивание текста, который сейчас будем выводить.

Меняем цвет кисти на синий.

Методом setTextSize устанавливаем размер шрифта в 30. Т.е. данные шрифта для текста задаются в той же самой кисти, которой мы только что фигуры рисовали.

drawText рисует текст: «text left». С параметрами все просто: сам текст и координаты X и Y. Также существует несколько аналогов drawText, которые позволяют выводить не весь текст, а его часть.

Метод setTextAlign настраивает горизонтальное выравнивание текста. По умолчанию оно равно Paint.Align.LEFT. И с ним у нас вывелся первый текст. Причем текст вывелся справа. Т.е. в данном случае LEFT означает не «текст будет слева от точки», а «точка будет слева от текста». Вполне можно и запутаться.

Меняем выравнивание на Paint.Align.CENTER. Теперь выравнивание по центру. Рисуем текст «text center».

Далее снова меняем выравнивание на Paint.Align.RIGHT и рисуем текст «text right».

Мы нарисовали три текста указывая одну X-координату = 150. Но разное горизонтальное выравнивание раскидало их по разные стороны. Ранее нарисованная зеленая линия с X = 150 позволяет это четко увидеть.

И напоследок рассмотрим еще пару моментов.

Перепишем класс DrawView:

Получится такая картинка

Методы getWidth и getHeight позволяют получить ширину и высоту канвы. Мы выводим эту инфу на экран методом darwText.

Далее выводим три прямоугольника с разными стилями рисования, которые указываем методом setStyle:

Paint.Style.FILL – прямоугольник закрашивается изнутри, а его грани не рисуются

Paint.Style.STROKE – рисуются только грани прямоугольника, внутри закраски нет

Paint.Style.FILL_AND_STROKE – есть и закраска внутри и грани

По умолчанию используется стиль Paint.Style.FILL.

Чтобы лучше понять все вышеизложенные аспекты, советую вам самостоятельно поэкспериментировать с ними.

На следующем уроке:

— работаем с Path

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

Оцените статью