Есть несколько обьектов в Android SDK, с которыми разработчик будет плотно и перманентно работать: activities, intents, services и content providers.
Я в шоке, это надо же было выбрать такие термины, которые не переводятся на русский нормально.. “настроим нашу активность” – ну это же бред (говорить с придыханием, © не мой)
Ну фиг с ними, с терминами, ладно уж..
Activity: это экран и элементы интерфейса на нем; я про себя называю это “форма” – привычка из делфи, все лучше, чем “активность”.. Приложение создает одну или несколько форм для всяческих своих нужд, форма должна позаботится о сохранности данных, с которыми она работает, если вдруг она вытесняется на задний план (где она может быть “убита” системой в случае нехватки ресурсов – и сделать это “без обьявления войны”)
Intents: “намерение, умысел”, еще один дурацкий термин.. намерение – это механизм описания специфического действия, например “отправка почты”: если я хочу из своего приложения отправить письмо, я должен обьявить о намерении сделать это; с другой стороны, я могу написать почтовый клиент и зарегистрировать его в системе как приложение, способное выполнить намерение “отправить почту”. Когда кто-то захочет отправить почту, ему будет предложен список программ, способных на это – в т.ч. и моя
Services: наконец нормальный термин. Сервис – это задача, которая выполняется фоново без участия/взаимодействия пользователя. Пример – мр3-плеер: скажем я хочу слушать музыку и читать книжку, если бы плеер был “обычной” программой, то при переключении на читалку музыка остановилась бы. Но если сделать сервис, который будет играть музыку – это решает проблему: некая программа взаимодействует с сервисом и дает ему список файлов для проигрывания и команду начать проигрывание; после этого сервис в фоне играет музыку, я переключаюсь на читалку, а музыка играет; если я захочу ее остановить или переключить трек – я вызову программу-плеер, которая даст соотв. команду сервису
Content Providers: контент-провайдер реализует api для работы с данными; приложения ничего не знают друг о друге, вот для обмена данными и используются контент-провайдеры – скажем, чтобы получить данные о контактах
Это имхо вся теория, которая нужна; а если нет, то я не виноват. Дальше практика – автор книги (и я за ним) шаг за шагом покажет, как написать игру Судоку для андроида (и может быть я ее наконец хоть раз решу)
Написание почти любой программы состоит из 2-х частей: программа должна как-то выглядеть (дизайн) и программа должна что-то делать (код)
Что касается дизайна, то лучше делфи конечно никто ничего не придумал (а самый запутанный способ рисования интерфейсов – имхо в маке с их х-кодом и интерфейс-билдером.. хотя это наверное просто смотря с чем сравнивать); для андроида вроде тоже есть какие-то wysiwyg-тулзы для проектирования интерфейса, но я так понимаю, что это поделки-самоделки, которыми пользуются чуть-ли не только сами авторы.. хотя я не спец и могу сильно ошибаться
В любом случае это отступление; интерфейс может быть создан в коде или с использованием декларативного метода, Google сильно советует последний способ (кроме очевидного соображения, что такой способ намного проще “читается”). Способ заключается в следующем: форма описывается xml-файлом, в котором указывается, какие контролы как расположены. Затем при компиляции вызывается компилятор ресурсов, который на основе xml-файлов создаст специальные данные, которые и будут использоваться приложением
Все, я начинаю что-то наконец делать: создаю в eclipse новый проект:
Жму Finish, попадаю в eclipse и после небольшой паузы (среда прекомпилирует какие-то ресурсы) могу запустить свой первый проект – Run –> Run as –> Android Application; запустится эмулятор и через какое-то время (запускается он не мгновенно) я получу “виртуальный” телефон, разлочив который увижу свою программу:
Эмулятор ведет себя как настоящий телефон и закрыть его – значит выключить телефон; а включить любой телефон занимает какое-то время (все такие операционная система стартует), так что лучшие собаководы рекомендуют: эмулятор запускается утром и выключается вечером.
При создании нового проекта автоматически была добавлена единственная форма, которую и видим на экране; логично изменить ее так, чтобы мы увидели привычный для игр интерфейс – кнопки New Game и Exit по крайней мере. Пока же при запуске инифиализируется “форма по умолчанию”, которая заполняет собой экран, делается это в переопределенном методе OnCreate:
1: package org.example.sudoku;
2:
3: import android.app.Activity;
4: import android.os.Bundle;
5:
6: public class Sudoku extends Activity {
7: /** Called when the activity is first created. */
8: @Override
9: public void onCreate(Bundle savedInstanceState) {
10: super.onCreate(savedInstanceState);
11: setContentView(R.layout.main);
12: }
13: }
Если посмотреть на файл AndroidManifest.xml (а этот файл обязательно должен быть в каждой android-программе), то увидим:
1: <?xml version="1.0" encoding="utf-8"?>
2: <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3: package="org.example.sudoku"
4: android:versionCode="1"
5: android:versionName="1.0">
6: <application android:icon="@drawable/icon" android:label="@string/app_name">
7: <activity android:name=".Sudoku"
8: android:label="@string/app_name">
9: <intent-filter>
10: <action android:name="android.intent.action.MAIN" />
11: <category android:name="android.intent.category.LAUNCHER" />
12: </intent-filter>
13: </activity>
14:
15: </application>
16: <uses-sdk android:minSdkVersion="7" />
17:
18: </manifest>
Здесь перечислены все (пока одна) формы (activities), принадлежащие приложению, и намерения, которые они готовы реализовать – так что при запуске показывается форма Sudoku
Ее дизайн описан в файле main.xml, который можно найти в разделе Sudoku/res/layout в списке проектов в eclipse; вообще в эту “папку” кладуться xml-файлы, которые описывают внешний вид форм; в OnCreate вызывается родительский OnCreate, а потом указывается, какую форму использовать: setContentView(R.layout.main). R - это класс, который создается и управляется автоматически средой разработки (android-плагином для eclipse), в него автоматически добавляются (и удаляются) идентификаторы ресурсов проекта (а ресурсы – это все, кроме кода – xml-файлы с описанием форм, xml-файлы со строчными ресурсами, картинки, звуки и т.д.)
Открываем main.xml:
1: <?xml version="1.0" encoding="utf-8"?>
2: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3: android:orientation="vertical"
4: android:layout_width="fill_parent"
5: android:layout_height="fill_parent"
6: >
7: <TextView
8: android:layout_width="fill_parent"
9: android:layout_height="wrap_content"
10: android:text="@string/hello"
11: />
12: </LinearLayout>
Разбираться с xml-форматом я не буду (я его ненавижу и не всегда понимаю, и уж точно не понимаю, как кому-то может нравится с ним что-то делать); этот файл описывает Layout (планировку) формы, планировка может быть нескольких видов:
- FrameLayout: дочерние элементы располагаются из левого верхнего угла экрана
- LinearLayout: дочерние элементы выстраиваются в одинарный столбец (используется чаще всего)
- RelativeLayout: относительное расположение дочерних элементов друг к другу и к родителю
- TableLayout: табличное размещение элементов
В нашем случае предполагается, что форма располагается вертикально и занимает в ширину и высоту все допустимое пространство; дочерних элементов всего один – текстовое поле, которое в ширину занимает все пространство родителя, а в высоту столько, сколько нужно, чтобы отобразить содержимое; содержимое берется из строкового ресурса (файл strings.xml)
Модифицируем стартовую форму:
1: <?xml version="1.0" encoding="utf-8"?>
2: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3: android:orientation="vertical"
4: android:layout_width="fill_parent"
5: android:layout_height="fill_parent">
6: <TextView
7: android:layout_width="fill_parent"
8: android:layout_height="wrap_content"
9: android:text="@string/main_title" />
10: <Button
11: android:layout_width="fill_parent"
12: android:layout_height="wrap_content"
13: android:text="@string/continue_label" />
14: <Button
15: android:layout_width="fill_parent"
16: android:layout_height="wrap_content"
17: android:text="@string/new_game_label" />
18: <Button
19: android:layout_width="fill_parent"
20: android:layout_height="wrap_content"
21: android:text="@string/about_label" />
22: <Button
23: android:layout_width="fill_parent"
24: android:layout_height="wrap_content"
25: android:text="@string/exit_label" />
26: </LinearLayout>
и файл строковых ресурсов strings.xml:
1: <?xml version="1.0" encoding="utf-8"?>
2: <resources>
3: <string name="app_name">Sudoku</string>
4: <string name="main_title">Android Sudoku</string>
5: <string name="continue_label">Continue</string>
6: <string name="new_game_label">New Game</string>
7: <string name="about_label">About</string>
8: <string name="exit_label">Exit</string>
9: </resources>
После чего смотрим результат:
Можно покастомизировать еще немного: сделать фон окна другим, для этого сначала надо определить ресурс для этого – добавить в /res/values файл colors.xml и написать туда:
1: <?xml version="1.0" encoding="utf-8"?>
2: <resources>
3: <color name="background">#3500ffff</color>
4: </resources>
теперь можно использовать:
1: <?xml version="1.0" encoding="utf-8"?>
2: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3: android:background="@color/background"
4: android:layout_height="fill_parent"
5: android:layout_width="fill_parent"
6: android:padding="30dip"
7: android:orientation="horizontal">
8: <LinearLayout
9: android:orientation="vertical"
10: android:layout_height="wrap_content"
11: android:layout_width="fill_parent"
12: android:layout_gravity="center">
13: <TextView
14: android:text="@string/main_title"
15: android:layout_height="wrap_content"
16: android:layout_width="wrap_content"
17: android:layout_gravity="center"
18: android:layout_marginBottom="25dip"
19: android:textSize="24.5sp" />
20: <Button
21: android:id="@+id/continue_button"
22: android:layout_width="fill_parent"
23: android:layout_height="wrap_content"
24: android:text="@string/continue_label" />
25: <Button
26: android:id="@+id/new_button"
27: android:layout_width="fill_parent"
28: android:layout_height="wrap_content"
29: android:text="@string/new_game_label" />
30: <Button
31: android:id="@+id/about_button"
32: android:layout_width="fill_parent"
33: android:layout_height="wrap_content"
34: android:text="@string/about_label" />
35: <Button
36: android:id="@+id/exit_button"
37: android:layout_width="fill_parent"
38: android:layout_height="wrap_content"
39: android:text="@string/exit_label" />
40: </LinearLayout>
41: </LinearLayout>
Кроме того, что указан цвет для фона (android:background="@color/background"), изменилось расположение элементов: создается LinearLayout (линейная планировка), с высотой “по содержимому”, внутри которой текст и кнопки; у кнопок добавились идентификаторы (android:id="@+id/new_button"), по которым можно будет легко обращаться в дальнейшем (т.е. кнопка New Game будет искаться как по идентификатору R.id.new_button); добавились модификаторы размеров – размер текста и отступы
Размеры указываются в аппаратно-независимых пикселах (dp/dip) и масштабо-независимых пикселах (sp) – т.е. отступ в 30 dp будет одинаково выглядеть на разных телефонах – и с размером экрана 480 точек в высоту, и 800; dp используется для “расстояний”, а sp – для размера шрифтов
И уже этот элемент (который “линейная планировка”.. лучше наверное “линейный вид”) размещен еще в одном виде, занимающем все окно:
Следующая фишка: а если повернуть телефон в ландшафтный режим (на эмуляторе это делается Ctrl-F11 или клавишами Num-7 – Num-9 (с отключенным NumLock))? Хорошего мало, нижняя кнопка не влезает :(
Решается просто: в папке res создается папка layout-land – интуитивно понятно, что для ландшафтного режима описание вида будет браться отсюда; создаем в ней файл main.xml:
1: <?xml version="1.0" encoding="utf-8"?>
2: <LinearLayout
3: xmlns:android="http://schemas.android.com/apk/res/android"
4: android:background="@color/background"
5: android:layout_height="fill_parent"
6: android:layout_width="fill_parent"
7: android:padding="15dip"
8: android:orientation="horizontal">
9: <LinearLayout
10: android:orientation="vertical"
11: android:layout_height="wrap_content"
12: android:layout_width="fill_parent"
13: android:layout_gravity="center"
14: android:paddingLeft="20dip"
15: android:paddingRight="20dip">
16: <TextView
17: android:text="@string/main_title"
18: android:layout_height="wrap_content"
19: android:layout_width="wrap_content"
20: android:layout_gravity="center"
21: android:layout_marginBottom="20dip"
22: android:textSize="24.5sp" />
23: <TableLayout android:layout_height="wrap_content"
24: android:layout_width="wrap_content"
25: android:layout_gravity="center"
26: android:stretchColumns="*">
27: <TableRow>
28: <Button
29: android:id="@+id/continue_button"
30: android:text="@string/continue_label" />
31: <Button
32: android:id="@+id/new_button"
33: android:text="@string/new_game_label" />
34: </TableRow>
35: <TableRow>
36: <Button
37: android:id="@+id/about_button"
38: android:text="@string/about_label" />
39: <Button
40: android:id="@+id/exit_button"
41: android:text="@string/exit_label" />
42: </TableRow>
43: </TableLayout>
44: </LinearLayout>
45: </LinearLayout>
Линейный вид на все окно, внутри которого – текстовка и табличный вид, внутри которого – 2 столбца с кнопками:
Ориентация корректно меняется при вращении устройства, при этом надо иметь в виду, что вид на самом деле пересоздается заново, при этом возникает события OnPause и т.д., где надо сохранить данные и восстановить их при создании вида в новой ориентации
Я устал писать…
Комментариев нет:
Отправить комментарий