Android studio рисование пальцем

SurfaceView

Класс SurfaceView предоставляет объект Surface, который поддерживает рисование в фоновом потоке и дает возможность использовать OpenGL для трехмерной графики. Это отличный вариант для насыщенных графикой элементов, которые нуждаются в частых обновлениях или должны отображать сложную графическую информацию, как в случае с играми и трехмерной визуализацией.

Найти данный элемент можно в разделе Advanced.

В основе SurfaceView объект Surface, а не Canvas. Это важно, потому как Surface поддерживает рисование из фоновых потоков. Данное отличие особенно полезно для ресурсоемких операций или быстрых обновлений, а также когда необходимо обеспечить высокую частоту изменения кадров (использование трехмерной графики, создание игр или предпросмотр видеопотока с камеры в режиме реального времени.

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

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

Применяя OpenGL, вы можете рисовать на Surface любые поддерживаемые двумерные или трехмерные объекты, получая при этом все выгоды от аппаратного ускорения (если таковое имеется). Таким образом, вы значительно повышаете производительность, если сравнивать с теми же операциями, выполненными на двумерном Canvas.

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

Создание нового объекта SurfaceView

Чтобы создать данный тип, наследуйте класс SurfaceView и реализуйте интерфейс SurfaceHolder.Callback, описывающий функцию обратного вызова. Он уведомляет представление о том, что исходный объект Surface был создан/уничтожен/модифицирован и передает в объект SurfaceHolder ссылку, содержащую допустимый экземпляр Surface.

Типичный шаблон проектирования SurfaceView предусматривает классы, производные от Thread, которые принимают ссылку на текущий объект SurfaceHolder и немедленно его обновляют.

SurfaceView с поддержкой касаний

Напишем простой пример использования SurfaceView, на котором можно рисовать линии.

Запустив проект, вы можете рисовать пальцем по экрану.

Гроза эпилептиков

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

В примере реализовано:

  • новый класс MySurfaceView, наследующий от SurfaceView и реализующий интерфейс SurfaceHolder.Callback
  • используются методы surfaceCreated(), surfaceDestroyed(), surfaceChanged() для SurfaceHolder.Callback
  • используется класс Thread для SurfaceView

Поймай меня

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

Этот же пример, но с использованием разметки FrameLayout, внутри которой находится SurfaceView, находится здесь. Не буду приводить код.

Продолжение серии примеров — Exercise of SurfaceView: SurfaceView overlap with a LinearLayout. Здесь появляется возможность выбрать цвет точки.

Отскакивающие значки

Ещё один пример — при касании экрана в области SurfaceView будет появляться новая картинка, которая будет двигаться внутри контейнера, отскакивая от стенок.

Источник

Работа с SurfaceView в Android

Здравствуйте, Хабравчане!
При работе с 2D графикой в Android отрисовку можно выполнять используя Canvas. Проще всего это сделать с помощью своего класса, унаследованного от View. Необходимо просто описать метод onDraw(), и использовать предоставленный в качестве параметра canvas для выполнения всех необходимых действий. Однако этот подход имеет свои недостатки. Метод onDraw() вызывается системой. Вручную же можно использовать метод invalidate(), говорящий системе о необходимости перепрорисовки. Но вызов invalidate() не гарантирует незамедлительного вызова метода onDraw(). Поэтому, если нам необходимо постоянно делать отрисовку (например для какой-либо игры), вышеописанный способ вряд ли стоит считать подходящим.

Читайте также:  Как включить фоновый режим android

Существует еще один подход — с использованием класса SurfaceView. Почитав официальное руководство и изучив несколько примеров, решил написать небольшую статью на русском, которая возможно поможет кому-то быстрее освоиться с данным способом выполнения отрисовки. Статья рассчитана на новичков. Никаких сложных и хитрых приемов здесь не описано.

Класс SurfaceView

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

Вся реализация сводится к двум основным моментам:

  1. Создание класса, унаследованного от SurfaceView и реализующего интерфейс SurfaceHolder.Callback
  2. Создание потока, который будет управлять отрисовкой.

Создание класса

Как было сказано выше, нам потребуется свой класс, расширяющий SurfaceView и реализующий интерфейс SurfaceHolder.Callback. Этот интерфейс предлагает реализовать три метода: surfaceCreated(), surfaceChanged() и surfaceDestroyed(), вызываемые соответственно при создании области для рисования, ее изменении и разрушении.
Работа с полотном для рисования осуществляется не напрямую через созданный нами класс, а с помощью объекта SurfaceHolder. Получить его можно вызовом метода getHolder(). Именно этот объект будет предоставлять нам canvas для отрисовки.

В конструкторе класса получаем объект SurfaceHolder и с помощью метода addCallback() указываем что хотим получать соответствующие обратные вызовы.
В методе surfaceCreated(), как правило, необходимо начинать выполнять отрисовку, а в surfaceDestroyed() наоборот завершать ее. Оставим пока тела этих методов пустыми и реализуем поток, отвечающий за отрисовку.

Реализация потока отрисовки

Создадим класс, унаследованный от Thread. В конструкторе он будет принимать два параметра: SurfaceHolder и Resources для загрузки картинки, которую мы будем рисовать на экране. Также в классе нам понадобится переменная-флаг, указывающая на то, что производится отрисовка и метод для установки этой переменной. Ну и, конечно, потребуется переопределить метод run().
В итоге получим следующий класс:

Для того, чтобы результат не выглядел совсем уж пресно, загруженную картинку увеличим в три раза, и немного сместим к центру экрана. Сделаем это при помощи матрицы преобразований. Также, не чаще чем раз в 30 миллисекунд, будем поворачивать картинку на 2 градуса вокруг ее центра. Само рисование на canvas лучше, конечно, вынести в отдельный метод, но в данном случае мы всего лишь очищаем экран и рисуем изображение. Так что можно оставить как есть.

Начало и завершение отрисовки

Теперь, после того как мы написали поток, управляющий отрисовкой, вернемся к редактированию нашего класса SurfaceView. В методе surfaceCreated() создадим поток и запустим его. А в методе surfaceDestroyed() завершим его работу. В итоге класс MySurfaceView примет следующий вид:

Следует отметить, что создание потока должно выполняться в методе surfaceCreated(). В примере LunarLander из официальной документации создание потока отрисовки происходит в конструкторе класса, унаследованного от SurfaceView. Но при таком подходе может возникнуть ошибка. Если свернуть приложение нажатием клавиши Home на устройстве, а затем снова открыть его, то возникнет исключительная ситуация IllegalThreadStateException.

Читайте также:  Карты для гуру мапс андроид

Activity приложения может выглядеть следующим образом:

Результат работы программы выглядит так (из за вращения изображение немного размазано, но на устройстве выглядит вполне приемлемо):

Источник

Android SDK: создание приложения для рисования — сенсорное взаимодействие

Russian (Pусский) translation by Elen (you can also view the original English article)

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

Формат урока

Данный урок по созданию приложения для рисования будет состоять из трех частей:

Просмотр конечного результата

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

1. Подготовка к рисованию

Шаг 1

В прошлый раз мы создали класс с именем «DrawingView», который представляет собой пользовательский View для функций рисования, которые должны выполняться внутри. Мы создали схему объявления класса и метод с именем «setupDrawing» — вот сейчас мы сделаем это. В своем классе DrawingView добавьте следующие операторы импорта:

Затем добавьте некоторые переменные экземпляра в верхней части класса:

Когда пользователь прикасается к экрану и перемещает палец, чтоб рисовать, мы будем использовать Path для отслеживания его действий рисования на холсте. Как холст, так и рисунок поверх него представлены объектами Paint. Начальный цвет краски соответствует первому цвету в палитре, которую мы создали в последний раз, и которая будет первоначально выбрана при запуске приложения. Наконец, мы объявляем переменные для холста и растрового изображения: пути пользователя, нарисованные с помощью drawPaint , будут нарисованы на холсте, который нарисован canvasPaint .

Шаг 2

Давайте создадим в методе setupDrawing некоторые из этих переменных, чтобы установить класс для рисования. Сначала создайте объекты рисования Path и Paint:

Затем установите начальный цвет:

Теперь задайте начальные свойства пути:

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

Завершите метод setupDrawing , создав экземпляр объекта Paint:

На этот раз мы устанавливаем сглаживание, передавая параметр конструктору.

Шаг 3

Нам нужно переопределить несколько методов, чтобы сделать пользовательскую функцию View в виде чертежа. Во-первых, все еще находясь внутри класса DrawingView , переопределите метод onSizeChanged , который будет вызываться, когда пользовательскому View присваивается размер:

Внутри этого метода вызовите сначала метод суперкласса:

Теперь создайте холст для рисования и растрового изображения, используя значения ширины и высоты:

Шаг 4

Чтобы позволить классу функционировать как View чертежа пользователя, нам также необходимо переопределить метод onDraw , поэтому сейчас добавьте его в класс:

Внутри метода нарисуйте холст и путь рисования:

Пока мы еще не реализовали возможность для пользователя рисовать путь с помощью Paint, но как только мы это сделаем, он будет представлен в View. Каждый раз, когда пользователь рисует с помощью сенсорного взаимодействия, мы аннулируем View, заставляя выполняться метод onDraw .

2. Содействие рисованию

Шаг 1

Когда чертеж View находится на экране приложения, мы хотим, чтобы пользователь касался его для регистрации в качестве операций рисования. Для этого нам нужно проследить сенсорные события. В своем классе drawingView добавьте следующий метод:

Читайте также:  Установщик пакетов android не работает

Внутри метода извлеките X и Y позиции касания пользователя:

Шаг 2

Параметр MotionEvent в onTouchEvent методе позволит нам реагировать на определенные события прикосновения. Действия, в которых мы заинтересованы, чтобы применить рисование, — down , move и up . Добавьте оператор switch в метод для ответа на каждый из следующих:

Найдите минутку, чтобы просмотреть этот код. Когда пользователь касается View, мы перемещаемся в это положение, чтобы начать рисовать. Когда он двигает пальцем по View, мы рисуем путь вместе с его прикосновением. Когда он забирает свой палец от View, мы рисуем Path, и перезагружаем его для следующей операции рисования.

Шаг 3

После оператора switch завершите метод, сделав недействительным View и вернув истинное значение:

Вызов invalidate вызовет выполнение метода onDraw .

3. Выбор цветов

Шаг 1

Теперь давайте реализуем возможность пользователя выбирать цвета из палитры. В главном Activity приложения добавьте следующие импорты:

Добавьте в класс следующую переменную экземпляра:

Это представляет экземпляр пользовательского View, который мы добавили в макет. Внутри onCreate , после существующего кода, создайте эту переменную, извлекая ссылку на нее из макета:

Теперь у нас есть View, который отображается в Activity, на котором мы можем вызвать методы в классе DrawingView .

Шаг 2

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

Внутри onCreate мы теперь хотим получить первую кнопку цвета краски в области палитры, которая изначально будет выбрана. Сначала найдите Linear Layout, содержащуюся внутри:

Получите первую кнопку и сохраните ее как переменную экземпляра:

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

Добавьте этот файл в чертежи вашего приложения, указав ему имя «paint_pressed.xml» и введя следующую форму:

Это очень похоже на «paint.xml», который мы создали в последний раз, но с темным цветом вокруг краски.

Шаг 3

Теперь мы можем позволить пользователю выбирать цвета. Когда в последний раз мы создавали макет, мы указали атрибут onClick для кнопок цветовой палитры; теперь добавьте метод в свой основной класс Activity:

Внутри этого метода сначала убедитесь, что пользователь щелкнул цвет краски, который не выбран в данный момент:

Внутри блока if найдите тег, который мы установили для каждой кнопки в макете, представляя выбранный цвет:

Для установки цвета нам нужно использовать собственный класс View. Перейдите в класс DrawingView и добавьте следующий метод:

Внутри метода начните с аннулирования View:

Затем выполните анализ и установите цвет для рисования:

Вернемся к нашему основному Activity и в методе paintClicked , после получения тега цвета, вызовите новый метод на пользовательский чертежный объект View:

Теперь обновите пользовательский интерфейс, чтобы отобразить новую выбранную краску, и установите предыдущую версию в обычном режиме:

Вывод

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

Источник

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