Статьи

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

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

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


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


Приложение для рисования

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


Запустите новый проект Android в Eclipse, выбрав имена приложений и пакетов. Мы используем минимальный уровень API 14 и цель 17 для кода в этом руководстве.

Чертежный проект

Позвольте Eclipse создать пустой основной Activity и макет — вы можете использовать имена по умолчанию.

Класс рисования и макет

Откройте файл манифеста проекта и перейдите на вкладку редактирования XML. Ваши уровни активности и SDK уже должны быть установлены. Добавьте следующее к открывающему тегу элемента Activity, заставляя приложение использовать только портрет:

1
android:screenOrientation=»portrait»

Прежде чем мы начнем создавать интерфейс, давайте определим некоторые числа, которые мы будем использовать на протяжении всей серии. В папке «res / values» вашего приложения, если Eclipse еще не создал его, добавьте файл «dimensions.xml» — если он уже существует, вы можете просто добавить в него новые значения. План должен быть следующим:

1
2
<resources>
</resources>

Если Eclipse создал файл, возможно, в нем уже есть некоторые значения. Мы собираемся использовать три возможных размера кисти / ластика: маленький, средний и большой. Нам необходимо определить размер для каждого из них как измерение, так и целочисленное значение, чтобы мы могли использовать эти измерения как в макете XML, так и в рисуемых ресурсах и коде Java:

1
2
3
4
5
6
7
<!— Brush sizes —>
<dimen name=»small_brush»>10dp</dimen>
<integer name=»small_size»>10</integer>
<dimen name=»medium_brush»>20dp</dimen>
<integer name=»medium_size»>20</integer>
<dimen name=»large_brush»>30dp</dimen>
<integer name=»large_size»>30</integer>

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


Мы собираемся определить пользовательский класс View, в котором будет происходить рисование. В исходном пакете вашего приложения создайте новый класс. Назовите его «DrawingView» и выберите «android.view.View» в качестве суперкласса. Новый класс должен иметь следующую схему:

1
2
3
4
public class DrawingView extends View
{
 
}

В вашем новом классе View вам потребуются следующие операторы импорта в дополнение к импорту View, который Eclipse должен был добавить для вас:

1
2
import android.content.Context;
import android.util.AttributeSet;

Добавьте метод конструктора к классу:

1
2
3
4
public DrawingView(Context context, AttributeSet attrs){
    super(context, attrs);
    setupDrawing();
}

Мы добавим экземпляр пользовательского представления в файл макета XML. Добавьте указанный вспомогательный метод в класс:

1
2
3
private void setupDrawing(){
//get drawing area setup for interaction
}

Мы реализуем этот метод в следующей части серии, а также добавим другие методы в класс.


Откройте XML-файл строк res / values ​​вашего приложения и добавьте несколько текстовых строк, которые мы будем использовать в макете:

1
2
3
4
5
<string name=»start_new»>New</string>
<string name=»brush»>Brush</string>
<string name=»erase»>Erase</string>
<string name=»save»>Save</string>
<string name=»paint»>Paint</string>

Откройте основной файл макета приложения и перейдите на вкладку XML для редактирования кода. Содержимое экрана «Активность» будет проще всего реализовать с помощью линейных макетов. Замените содержимое файла макета следующим текстом:

1
2
3
4
5
6
7
8
9
<LinearLayout xmlns:android=»http://schemas.android.com/apk/res/android»
    xmlns:tools=»http://schemas.android.com/tools»
    android:layout_width=»match_parent»
    android:layout_height=»match_parent»
    android:background=»#FFCCCCCC»
    android:orientation=»vertical»
    tools:context=».MainActivity» >
 
</LinearLayout>

Мы устанавливаем вертикальную ориентацию и серый цвет фона.

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

1
2
3
4
5
6
<LinearLayout
    android:layout_width=»wrap_content»
    android:layout_height=»50dp»
    android:layout_gravity=»center»
    android:orientation=»horizontal» >
</LinearLayout>

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

Новая кнопка
Кнопка кисти
Кнопка Ластик
Кнопка Сохранить

Скопируйте изображения в папку (и) для рисования вашего приложения — если вы создаете свое собственное, вы можете ориентироваться на определенные плотности Чтобы завершить серию уроков, не ориентируясь на конкретную плотность экрана, вы можете просто создать папку с именем «drawable» и добавить в нее все свои ресурсы для рисования.

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

1
2
3
4
5
6
<ImageButton
    android:id=»@+id/new_btn»
    android:layout_width=»wrap_content»
    android:layout_height=»fill_parent»
    android:contentDescription=»@string/start_new»
    android:src=»@drawable/new_pic» />

Мы будем использовать идентификатор для ответа на нажатия кнопок в классе «Активность». Мы указываем новое изображение значка кнопки в качестве источника для ImageButton и добавляем строку описания содержимого.

Затем добавьте кнопку кисти:

1
2
3
4
5
6
<ImageButton
    android:id=»@+id/draw_btn»
    android:layout_width=»wrap_content»
    android:layout_height=»fill_parent»
    android:contentDescription=»@string/brush»
    android:src=»@drawable/brush» />

Теперь добавьте кнопку ластика:

1
2
3
4
5
6
<ImageButton
    android:id=»@+id/erase_btn»
    android:layout_width=»wrap_content»
    android:layout_height=»fill_parent»
    android:contentDescription=»@string/erase»
    android:src=»@drawable/eraser» />

При нажатии на кнопку кисти или ластика пользователю будет предложено выбрать размер — мы реализуем это позже. Затем добавьте кнопку сохранения:

1
2
3
4
5
6
<ImageButton
    android:id=»@+id/save_btn»
    android:layout_width=»wrap_content»
    android:layout_height=»fill_parent»
    android:contentDescription=»@string/save»
    android:src=»@drawable/save» />

Вот и все для верхних кнопок управления Linear Layout.

После верхней кнопки Linear Layout, но все еще внутри внешнего Linear Layout в файле, давайте теперь добавим экземпляр созданного нами пользовательского класса представления:

01
02
03
04
05
06
07
08
09
10
<com.example.drawingfun.DrawingView
    android:id=»@+id/drawing»
    android:layout_width=»fill_parent»
    android:layout_height=»0dp»
    android:layout_marginBottom=»3dp»
    android:layout_marginLeft=»5dp»
    android:layout_marginRight=»5dp»
    android:layout_marginTop=»3dp»
    android:layout_weight=»1″
    android:background=»#FFFFFFFF» />

Как видите, вы можете добавить пользовательский вид к своим макетам почти так же, как и стандартные элементы пользовательского интерфейса Android. Мы устанавливаем общие свойства макета, белый фон для рисования и предоставляем идентификатор для ссылки на представление в Java. Получив ссылку на этот экземпляр пользовательского класса View, наша Activity сможет получить доступ к методам, которые мы определили в объявлении класса View, которое мы создали.

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

1
2
3
4
5
6
<LinearLayout
    android:layout_width=»wrap_content»
    android:layout_height=»wrap_content»
    android:layout_gravity=»center»
    android:orientation=»vertical» >
</LinearLayout>

Этот элемент будет содержать две строки кнопок, поэтому введите для них еще две линейные схемы. Поместите следующее в тот, который вы только что добавили:

01
02
03
04
05
06
07
08
09
10
11
12
13
<!— Top Row —>
<LinearLayout
    android:id=»@+id/paint_colors»
    android:layout_width=»wrap_content»
    android:layout_height=»wrap_content»
    android:orientation=»horizontal» >
</LinearLayout>
<!— Bottom Row —>
<LinearLayout
    android:layout_width=»wrap_content»
    android:layout_height=»wrap_content»
    android:orientation=»horizontal» >
</LinearLayout>

Первая строка имеет идентификатор, потому что мы собираемся использовать его в Java, когда приложение начнет устанавливать первый цвет по умолчанию, выбранный так, чтобы пользователь мог сразу начать рисовать. Для каждого цвета мы будем использовать следующую структуру ImageButton :

1
2
3
4
5
6
7
8
9
<ImageButton
    android:layout_width=»@dimen/large_brush»
    android:layout_height=»@dimen/large_brush»
    android:layout_margin=»2dp»
    android:background=»#FF660000″
    android:contentDescription=»@string/paint»
    android:onClick=»paintClicked»
    android:src=»@drawable/paint»
    android:tag=»#FF660000″ />

Пока не добавляйте это в свой файл макета — мы сделаем это в ближайшее время, а пока посмотрим на код. Мы используем одно из значений измерения, которое мы определили для цветной кнопки. Обратите внимание, что атрибуты background и tag совпадают — фон для появления кнопки в пользовательском интерфейсе, а тег — для того, чтобы мы могли установить цвет краски в соответствии с тем, что пользователь щелкнул в коде Activity Java. Элемент включает метод для выполнения по нажатию кнопки — мы реализуем это в классе Activity в следующий раз. Мы также указываем рисование с именем «краска». Добавьте это в проект сейчас, создав новый файл в папке (-ях) для рисования проекта и назвав его «paint.xml». Введите следующий код в новый файл для рисования:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<layer-list xmlns:android=»http://schemas.android.com/apk/res/android» >
<item>
    <shape android:shape=»rectangle» >
        <stroke
            android:width=»4dp»
            android:color=»#FF999999″ />
        <solid android:color=»#00000000″ />
        <padding
            android:bottom=»0dp»
            android:left=»0dp»
            android:right=»0dp»
            android:top=»0dp» />
    </shape>
</item>
<item>
    <shape xmlns:android=»http://schemas.android.com/apk/res/android» >
        <stroke
            android:width=»4dp»
            android:color=»#FF999999″ />
        <solid android:color=»#00000000″ />
        <corners android:radius=»10dp» />
    </shape>
</item>
</layer-list>

Это менее сложно, чем кажется на первый взгляд. Чтобы создать внешний вид кнопки с закругленными углами, мы используем два слоя Drawable Shape Drawables, один контур в виде прямоугольника, а другой — округленный штрих. Штрихи имеют серый цвет с прозрачностью посередине, через которую будет виден цвет фона для каждой кнопки (цвет фона — это цвет, представленный кнопкой).

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<ImageButton
    android:layout_width=»@dimen/large_brush»
    android:layout_height=»@dimen/large_brush»
    android:layout_margin=»2dp»
    android:background=»#FF660000″
    android:contentDescription=»@string/paint»
    android:onClick=»paintClicked»
    android:src=»@drawable/paint»
    android:tag=»#FF660000″ />
 
<ImageButton
    android:layout_width=»@dimen/large_brush»
    android:layout_height=»@dimen/large_brush»
    android:layout_margin=»2dp»
    android:background=»#FFFF0000″
    android:contentDescription=»@string/paint»
    android:onClick=»paintClicked»
    android:src=»@drawable/paint»
    android:tag=»#FFFF0000″ />
 
<ImageButton
    android:layout_width=»@dimen/large_brush»
    android:layout_height=»@dimen/large_brush»
    android:layout_margin=»2dp»
    android:background=»#FFFF6600″
    android:contentDescription=»@string/paint»
    android:onClick=»paintClicked»
    android:src=»@drawable/paint»
    android:tag=»#FFFF6600″ />
 
<ImageButton
    android:layout_width=»@dimen/large_brush»
    android:layout_height=»@dimen/large_brush»
    android:layout_margin=»2dp»
    android:background=»#FFFFCC00″
    android:contentDescription=»@string/paint»
    android:onClick=»paintClicked»
    android:src=»@drawable/paint»
    android:tag=»#FFFFCC00″ />
 
<ImageButton
    android:layout_width=»@dimen/large_brush»
    android:layout_height=»@dimen/large_brush»
    android:layout_margin=»2dp»
    android:background=»#FF009900″
    android:contentDescription=»@string/paint»
    android:onClick=»paintClicked»
    android:src=»@drawable/paint»
    android:tag=»#FF009900″ />
 
<ImageButton
    android:layout_width=»@dimen/large_brush»
    android:layout_height=»@dimen/large_brush»
    android:layout_margin=»2dp»
    android:background=»#FF009999″
    android:contentDescription=»@string/paint»
    android:onClick=»paintClicked»
    android:src=»@drawable/paint»
    android:tag=»#FF009999″ />

Каждая кнопка идентична, кроме цветов, определенных в фоне и атрибутах тега. Добавьте следующие шесть в макет нижнего ряда:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<ImageButton
    android:layout_width=»@dimen/large_brush»
    android:layout_height=»@dimen/large_brush»
    android:layout_margin=»2dp»
    android:background=»#FF0000FF»
    android:contentDescription=»@string/paint»
    android:onClick=»paintClicked»
    android:src=»@drawable/paint»
    android:tag=»#FF0000FF» />
 
<ImageButton
    android:layout_width=»@dimen/large_brush»
    android:layout_height=»@dimen/large_brush»
    android:layout_margin=»2dp»
    android:background=»#FF990099″
    android:contentDescription=»@string/paint»
    android:onClick=»paintClicked»
    android:src=»@drawable/paint»
    android:tag=»#FF990099″ />
 
<ImageButton
    android:layout_width=»@dimen/large_brush»
    android:layout_height=»@dimen/large_brush»
    android:layout_margin=»2dp»
    android:background=»#FFFF6666″
    android:contentDescription=»@string/paint»
    android:onClick=»paintClicked»
    android:src=»@drawable/paint»
    android:tag=»#FFFF6666″ />
 
<ImageButton
    android:layout_width=»@dimen/large_brush»
    android:layout_height=»@dimen/large_brush»
    android:layout_margin=»2dp»
    android:background=»#FFFFFFFF»
    android:contentDescription=»@string/paint»
    android:onClick=»paintClicked»
    android:src=»@drawable/paint»
    android:tag=»#FFFFFFFF» />
 
<ImageButton
    android:layout_width=»@dimen/large_brush»
    android:layout_height=»@dimen/large_brush»
    android:layout_margin=»2dp»
    android:background=»#FF787878″
    android:contentDescription=»@string/paint»
    android:onClick=»paintClicked»
    android:src=»@drawable/paint»
    android:tag=»#FF787878″ />
 
<ImageButton
    android:layout_width=»@dimen/large_brush»
    android:layout_height=»@dimen/large_brush»
    android:layout_margin=»2dp»
    android:background=»#FF000000″
    android:contentDescription=»@string/paint»
    android:onClick=»paintClicked»
    android:src=»@drawable/paint»
    android:tag=»#FF000000″ />

Измените цвета, если хотите, но убедитесь, что вы используете одно и то же значение цвета в качестве фона и тегов для каждой кнопки. Теперь вы должны увидеть макет на вкладке «Графический макет» в Eclipse:

Дизайн приложения для рисования

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

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