Android studio canvas drawline

Класс 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, который позволит быстро создать массив точек с заданными координатами. Далее настраиваем объекты для рисования и формируем путь через созданный массив. В результате получим кошкин дом.

Читайте также:  Ошибка com android setting произошла ошибка

Путь можно составлять не только из точек, но и из фигур, например, дуг. Сначала формируем дугу, добавляем её в путь при помощи метода 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(). Поэтому значения должны быть достаточно маленькими, иначе толщина обводки может просто оказаться больше самой фигуры. Кстати, в некоторых случаях с текстом и другими методами рисование масштабирование может сыграть злую шутку и дробные значения не позволят увидеть текст и некоторые линии. В этих случаях приходиться создавать цепочку преобразований, когда временно масштаб увеличивается до нормальных размеров, рисуется текст с подходящим размером шрифта, затем опять всё уменьшается и т.д. Это долгая история.

Источник

Android draw Line Chart with Canvas

For Android Development the Canvas Framework is the one of most important technology that you can learn, however is one of the most underestimated too. In this article I will explain how to create a simple Line Chart with Canvas, and how you can simplify the drawing process.

When you create a View and override the onDraw(…) you earn all power of that View, and all responsibilities too. An important responsibility is not put much process in this method, because it is called in every state of a view, every invalidade(…), requestLayout(…), onSizeChanged(..), etc… If it have a lot of process like calculations, loops or object instantiation, then your application will have Main Thread problems, and lost of performance.

I will show below a strategy for separate your view in the data responsibility, and drawing responsibility. In this way it’s easy to pass and update the content of your chart.

For the Data content we need to create an Adapter that you pass and update the Chart data, and notify when the data has changed.

I create an abstract class with some common implementations that call’s ChartAdapter:

This class has some functions to be implemented by your child:

To notify the content change I used the DataSetObservable, but you can use any observer you want like LiveData an RX frameworks.

Читайте также:  Операционная система vidaa или андроид для телевизора что лучше

For the LineChart the adapter implementation is:

Note that we receive a FloatArray as parameter that represents your line chart(Y columns). The abstract methods getItem(…), getY(…) was implemented returning the Y data. The other methods is just to set new data and notify the super.

Now we have the data layer created, and need to consume it in the view. I will not explain in this post how to get and set attrs in a View, but will create an article talking about that.

To convert data in pixel I use an class called ScaleHelper, that the implementation will help a lot.

This class will return the respective pixel value of the Chart Data based on the view content rect. Note that contentRect represents the view size, and with this information the Helper calculate the View width and heigth.

Now we have the View’s Adapter, then we need to create the View. The first thing we need to do is calculate where canvas will draw our data and the space in view that we can use. We need to override two View Methods to know it.

In this two methods we receive a size changed delegation, then we set the View limits calculated with View paddings and dimensions. Every time when this methods are called we need to calculate and redraw our canvas.

The next step is use the Rect to create a Canvas Path with all points to draw. Using our ScaleHelper we can get the x and y point in View to our Adapter Data.

We are using two Path methods moveTo(…) to put our path in the first position, and lineTo(…) to create a line between the first point to second. Then we call invalidate() method to call View redrawing. In onDraw(…) method we call Canvas drawPath(…) method to put in View our path.

We need to note some that all callculations are done before onDraw(…). It’s important to know that this method is called after all View change (Size, padding, lifecycle), then put heavy processes here will result in main thread performance problems.

This is the visual result of our chart. We can use Paint to draw any color and style. In next articles I will show how to use attr’s in a Custom View, and how to take the next level with Canvas

Any doubt let me know in comments please. Thanks!!

Источник

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

— работаем с Path

На прошлом уроке мы рассмотрели простые фигуры. Но кроме них мы имеем возможность создавать сложные фигуры с помощью объекта Path. Этот объект позволяет нам создать составную фигуру, состоящую из линий, кривых и простых фигур.

Project name: P1431_DrawingPath
Build Target: Android 2.3.3
Application name: DrawingPath
Package name: ru.startandroid.develop.p1431drawingpath
Create Activity: MainActivity

Простые фигуры

Кодим в MainActivity.java:

Метод reset очищает path.

Метод moveTo – ставит «курсор» в указанную точку. Далее рисование пойдет от нее.

lineTo – рисует линию от текущей точки до указанной, следующее рисование пойдет уже от указанной точки

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

Далее перемещаем точку и снова рисуем две линии, и закрываем подфигуру методом close. Методом moveTo мы сообщили, что начали рисовать новую подфигуру и эта точка является начальной, а когда вызываем close – рисуется линия от последней точки до начальной. Т.е. фигура закрывается. Таким образом, нарисовав две линии и вызвав метод close, мы получили треугольник.

Далее методами addRect и addCircle к объекту path добавляем квадрат и круг. Параметры тут стандартные, рассмотрены нами на прошлых уроках, кроме последнего: направления. Здесь есть два варианта: Path.Direction.CW (по часовой) и Path.Direction.CCW (против часовой). Т.е. вы задаете направление рисования линий квадрата или фигуры. Как это можно использовать, рассмотрим чуть позже.

Выводим получившийся path на экран ченым цветом.

Далее работаем с другим Path-объектом: path1. Добавляем в него две пересекающиеся линии. Выводим path1 зеленым цветом. Он у нас получился нарисован поверх path.

Теперь методом addPath добавляем path1 к path. Т.е. к Path можно добавлять не только фигуры и линии, но и Path-объекты. Смещаем итоговый path на 500 вправо и 100 вниз методом offset, меняем цвет на синий и выводим результат.

В хелпе есть еще несколько методов add* для добавления фигур, которые мы прошли в прошлом уроке. С ними все аналогично.

Читайте также:  Андроид приставка с rca выходом

Кривые

Path дает нам возможность рисовать не только прямые, но и кривые линии, а именно квадратичные и кубические кривые Безье. Википедия дает очень хорошие GIF-ки на эту тему.

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

Рассмотрим сначала зеленую кривую.

Сначала рисуем черную линию (100,100) – (600,100). Делаем это только для наглядности, чтобы видеть, какой была бы линия, если бы мы из нее кривую не сделали.

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

Теперь рисуем кривую, используя Path. Становимся в точку (100,100) методом moveTo. Метод quadTo рисует кривую из текущей точки (100,100) в точку (600,100) (т.е. те же координаты, что и черной линии). А точка (point1.x, point1.y) позволяет задать изгиб кривой. Проще говоря, кривая будет отклонена в сторону этой точки.

Аналогично рисуем синюю кривую. Сначала черным цветом прямой оригинал. Затем точки отклонения. Затем искривляем. Метод cubicTo рисует кривую из текущей точки (400,400) в точку (1100,400). А точки (point21.x, point21.y) и (point22.x, point22.y) позволяют задать изгиб кривой. Проще говоря, кривая будет отклонена в сторону этих точек.

На получившемся результате видно, что кривые тянутся к точкам, которые показаны кружками. Для зеленой кривой, нарисованной методом quadTo – это одна точка. А метод cubicTo позволил нам задать две такие точки для синей линии.

Также обратите внимание, что при создании объекта Paint я использовал флаг Paint.ANTI_ALIAS_FLAG. Он сглаживает кривые при рисовании. Попробуйте его убрать и сравнить результат.

В качестве задания предлагаю вам вспомнить Урок 102 про касания и сделать приложение, в котором будет нарисована прямая, а касаясь экрана пальцем ее можно будет искривлять в сторону точки касания.

Относительные методы

Методы moveTo, lineTo, quadTo, cubicTo имеют одноименные аналоги, но начинающиеся с буквы r: rMoveTo, rLineTo, rQuadTo, rCubicTo. Отличие r-методов в том, что они используют не абсолютные, а относительные (relative – отсюда и буква r) координаты.

Например, если метод lineTo(100,200) рисовал нам линию от текущей точки в точку (100,200), то rLineTo(100,200) нарисует линию от текущей точки в точку, которая правее текущей на 100 и ниже на 200.

Текст по фигуре

Теперь посмотрим, как можно использовать направление рисования, которое мы задавали в методах addRect и addCircle

Видим четыре текста, которые нарисованы в виде круга. Разберемся, как это сделано.

Добавляем к Path круг методом addCircle, используя направление по часовой — Path.Direction.CW. Далее методом drawTextOnPath рисуем черным цветом текст по контуру path-фигуры. Как видим, текст идет по часовой стрелке. Сам круг при этом не рисуется.

Далее очишаем path и добавляем к нему новый круг, используя направление против часовой Path.Direction.CCW. В нем текст пойдет против часовой стрелки. И синим цветом рисуем и текст и круг.

А теперь рассмотрим параметры drawTextOnPath на зеленой и красной фигурах. Будем использовать тот же path, который нарисовали синим цветом. Только методом offset будем перемещать его на новое место.

У метода drawTextOnPath третий параметр означает длину отступа от старта фигуры. В зеленом круге мы задали этот отступ равным 100. Видно, что по сравнению с синим кругом, текст здесь имеет отступ по окружности от начала.

Четвертый параметр метода drawTextOnPath позволяет указать отступ текста от фигуры. В красном круге мы указали его равным 30. И видим, что текст удален от круга наружу. Если задать отрицательное значение, то текст будет смещен внутрь.

Обратите внимание, что в Path вообще не используется объект Paint. Т.е. Path — это просто фигура. И она ничего не знает про то, какой кистью она будет нарисована. Кисть задается и используется уже непосредственно при рисовании фигуры на канве.

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

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

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

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

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

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

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

Источник

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