Как стать автором
Обновить

Создание мобильного приложения для рисования на Android Studio

Уровень сложностиПростой
Время на прочтение7 мин
Количество просмотров6.7K

Или как не сойти с ума в поисках решения простейшей проблемы будучи новичком.

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

Я не думаю, что данную статью будут читать профессиональные разрабы (иначе меня забросают помидорами). Статья в первую очередь нужна для новичков. Здесь не будет глубоких разъяснений почему так или не так. Здесь не будет самописных библиотек или чего-то заумного. Новичкам стоит лишь повторять то что написано в статье как в алгоритме. Для тех кто хочет видеть это в видео-формате от индуса, в конце статьи будет ссылка. Опытным Джавистам и разрабам на Андроид Студио - большое спасибо что уделяете внимание новичкам, будем благодарны за помощь и совет.

Для начала о ресурсах которые мы будем использовать. Наш друг из Индии любезно заготовил нам пару картинок в .xml формате и дал на них ссылку под видео, оригинальная ссылка на его гугл диск работать перестала, поэтому для вас будет его копия.
https://drive.google.com/drive/folders/1lv3pwm4YSr1q-LdTnvdQSvCvWImRg7ow?usp=sharing

За картинку со знаком download
За картинку со знаком download

Далее-библиотеки. Нам нужны библиотеки:

  • SignatureView, которая собственно и будет позволять нам рисовать на экране https://github.com/zahid-ali-shah/SignatureView

  • AmbilWarna для выбора цвета нашей "ручки".
    https://github.com/yukuku/ambilwarna

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

В основном алгоритм их подключения и не сильно от остальных отличается. Берем те зависимости которые указаны в описании библиотеки на гитхабе, в нашем случае это зависимости: 'com.github.yukuku:ambilwarna:2.0.1' и 'com.kyanogen.signatureview:signature-view:1.2'. Заходим в Андроид студио, во ВТОРОЙ файл build.grandle(Module :app) и при помощи "implementation" вписываем две эти зависимости в dependencies.

Примерно таким образом.
Примерно таким образом.

Но, как и в анекдоте про Чапая и Петьку, есть нюанс. Библиотека SignatureView так просто не заработает. Заходим в файл settings.grandle и, первое, дописываем в repositiories jcenter(), второе, в конце файла приписываем include 'SignatureView-Example', 'signature-view'

Примерно так.
Примерно так.

(Только что вы сделали за пару минут то, что мой хилый мозг придумывал пол для.) После чего, мы все это дело синхронизируем, при помощи кнопки "Sync now" в правом верхнем углу. Ура, библиотеки подключены!

Теперь к объектам на сцене. Можете забить на режим дизайна, сразу переключайтесь либо в сплит (чтобы сразу видеть что меняется на сцене), либо в режим кода. Удаляйте TextView и замените те страшные строчки в самом первом объекте на Relative Layout.

Вот так.
Вот так.

Возвращаемся к нашему SignatureView на гитхабе и копируем следующие строки, вставляем в пространство между RelativeLayout:

<com.kyanogen.signatureview.SignatureView
        android:id="@+id/signature_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/optionsHolder"
        android:layout_marginBottom="0dp"
        app:backgroundColor="#ffffff"
        app:enableSignature="true"
        app:penColor="#000000"
        app:penSize="5dp"/>

Уже этот кусок кода позволит нам рисовать на экране.

Таким вот образом
Таким вот образом

Отвлечемся на секунду для того, чтобы закинуть ассеты картинок. В папку drawable, что находится в папке res, закидываем наши скачанные ассеты. Готово, теперь в ресурсах будут отображаться 2 эти картинки.

Обратно к Xml. Теперь надо сделать панельку с кнопками и другими управляющими элементами. Для этого будем использовать:

  • Слайдер для увеличения/уменьшения кисти

  • 2 кнопки. Одна меняет цвет нашей кисти, вторая стирает все что было нарисовано.

Создаем LinearLayout со следующими параметрами:

        android:id="@+id/optionsHolder"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:gravity="center"
        android:layout_alignParentBottom="true"

и еще 2 внутри него с:

            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_margin="4dp"
            //для первого
            android:layout_gravity="end"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_margin="4dp"
            //для второго

Самый главный Linear нам нужен для того чтобы обернуть в него 2 другие. Первый будет содержать слайдер, второй - 2 кнопки.

Вот таким вот образом.
Вот таким вот образом.

Переключаем все внимание на первый внутренний Linear. В нем надо создать SeekBar и TextView. Итоговый вариант первого внутреннего Linear'a:

      <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_margin="4dp"
            >
            <SeekBar
                android:layout_weight="1"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="8dp"
                android:id="@+id/penSize">
            </SeekBar>
            <TextView
                android:id="@+id/TxtPenSize"
                android:textColor="@color/black"
                android:text="5dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
            </TextView>

        </LinearLayout>

При работе в режиме сплит вы увидите следующее:

Ко второму Linear'у. Создаем 2 ImageButton, со следующими параметрами. Для первого:

                android:id="@+id/btnEraser"
                android:layout_width="0dp"
                android:layout_height="70dp"
                android:background="@color/white"
                android:scaleType="center"
                android:layout_weight="1"
                android:src="@drawable/ic_eraser"
//это будет кнопка стирания всего с экрана

Для второго:

                android:id="@+id/btnColor"
                android:layout_width="0dp"
                android:layout_height="70dp"
                android:background="@color/white"
                android:scaleType="center"
                android:layout_weight="1"
                android:src="@drawable/ic_color"
//это будет кнопка смены цвета ручки.

Итоговый вариант Xml кода:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.kyanogen.signatureview.SignatureView
        android:id="@+id/signature_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/optionsHolder"
        android:layout_marginBottom="0dp"
        app:backgroundColor="#ffffff"
        app:enableSignature="true"
        app:penColor="#000000"
        app:penSize="5dp"/>
    <LinearLayout
        android:id="@+id/optionsHolder"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:gravity="center"
        android:layout_alignParentBottom="true">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_margin="4dp">
            <SeekBar
                android:layout_weight="1"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="8dp"
                android:id="@+id/penSize">
            </SeekBar>
            <TextView
                android:id="@+id/TxtPenSize"
                android:textColor="@color/black"
                android:text="5dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
            </TextView>
        </LinearLayout>
        <LinearLayout
            android:layout_gravity="end"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_margin="4dp">
            <ImageButton
                android:id="@+id/btnEraser"
                android:layout_width="0dp"
                android:layout_height="70dp"
                android:background="@color/white"
                android:scaleType="center"
                android:layout_weight="1"
                android:src="@drawable/ic_eraser">
            </ImageButton>
            <ImageButton
                android:id="@+id/btnColor"
                android:layout_width="0dp"
                android:layout_height="70dp"
                android:background="@color/white"
                android:scaleType="center"
                android:layout_weight="1"
                android:src="@drawable/ic_color">
            </ImageButton>
        </LinearLayout>
    </LinearLayout>
</RelativeLayout>

Сам интерфейс программы будет таким:

Ура, мы закончили с интерфейсом! Устали? Я тоже, но осталось чуть-чуть (нет).

Теперь к любимой части, java коду.

Для начала импорт необходимого всего(библиотек):

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;

import android.os.Bundle;
import android.view.View;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import com.kyanogen.signatureview.SignatureView;
import yuku.ambilwarna.AmbilWarnaDialog;

Теперь объявляем все переменные, необходимые нам:

    SignatureView signatureView;// объект для того чтобы рисовать
    ImageButton imgEraser,imgColor;// 2 объекта кнопок
    SeekBar seekBar;// слайдбар для изменения размера ручки
    TextView txtpensize;// текст для пояснения
    int defaultcolor;// стандартный цвет который мы используем на данный момент

Ну а теперь крепим все это к объектам из .XML, через ID-шников, которые мы им уже дали в коде XML

        signatureView=findViewById(R.id.signature_view);//метод findViewById делает возможным поиск по айди элемента в XML
        imgEraser=findViewById(R.id.btnEraser);
        imgColor= findViewById(R.id.btnColor);
        seekBar=findViewById(R.id.penSize);
        txtpensize=findViewById(R.id.TxtPenSize);

        defaultcolor= ContextCompat.getColor(MainActivity.this,R.color.black);//просто черный цвет

Далее к основному коду. Для начала Seek Bar. Обращаемся к seekBar.setOnSeekBarChangeListener и видим следующую картину:

Здесь нам нужена только функция onProgressChanged, где мы пишем следующие строки:

                txtpensize.setText(progress+"dp");//то что мы будем видеть как подсказку
                signatureView.setPenSize(progress);//смена размера кисти через функции библиотеки
                seekBar.setMax(50);//максимальное значение seekbara

Далее кнопка для стирания всего с экрана. Для этого обращаемся к imgEraser.setOnClickListener, а точнее к функции внутри него - public void onClick(View v) после чего пишем- signatureView.clearCanvas();. По итогу мы получим:

Теперь к смене цвета. Для начала, за пределами функции OnCreate, создаем функцию openColorPicker. Создаем там новый AmbilWarnaDialog:

 AmbilWarnaDialog ambilWarnaDialog = new AmbilWarnaDialog(this, defaultcolor, new AmbilWarnaDialog.OnAmbilWarnaListener()

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

Теперь вернемся к функции OnCreate и дополняем его следующими строками для вызовы данной функции и смены цвета:

imgColor.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                openColorPicker();
            }
        });

Ура! Вы сделали приложение для простейшего рисования для андроид устройств (меня наконец-то покормят!). Осталось только скомпилировать код и установить на любое андроид устройство.

Извиняюсь за ублюдский шортс, ютуб не дает сохранить видео не в формате шортс(:). На моей демонстрации черный цвет из-за темы телефона (инверсия цветов), на ваших устройствах все будет ОК.

На этом все. Как и обещал - ссылка на индуса-учителя-ситха: https://youtu.be/xGrOHLk60q8, надеюсь, он будет полезен вам (научите делать якоря и оглавление для статьи, а то у меня лапки).

Теги:
Хабы:
Всего голосов 2: ↑2 и ↓0+2
Комментарии4

Публикации

Истории

Работа

Java разработчик
347 вакансий

Ближайшие события

7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
22 – 24 ноября
Хакатон «AgroCode Hack Genetics'24»
Онлайн
28 ноября
Конференция «TechRec: ITHR CAMPUS»
МоскваОнлайн
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань