четверг, 17 июня 2010 г.

Pragmatic Android, part #2

Следующий простой шаг – вывод About; надо просто отреагировать на нажатие кнопки About показом нового окна с какой-то текстовкой, картинкий, урлами, номером версии и прочим.

Начать стоит с создания формы:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:padding="10dip">
  <TextView
    android:id="@+id/about_content"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/about_text" />
</ScrollView>

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

        <activity android:name = ".About"
                  android:label = "@string/about_title"
                  android:theme = "@android:style/Theme.Dialog">
        </activity>

Для того, чтобы форма выглядела “красивее”, используется тема (смотреть доку здесь - C:/Program Files/eclipse/android-sdk-windows/docs/reference/android/R.style.html#Theme, ну это она у меня тут установлена конечно), вот разница между формами с использованием темы и без:

scr-17.06-2 scr-17.06

Ресурс для формы есть, надо создать файл About.java и настроить ее появление:

package org.example.sudoku;

import android.app.Activity;
import android.os.Bundle;

public class About extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.about);
	}
}

Форма определена, внешний вид устраивает, приложение о ней в курсе – надо как-то ее показать. Для того, чтобы основная форма могла реагировать на событие “кнопка нажалась”, добавим в ее класс реализацию интерфейса OnClickListener (“Interface definition for a callback to be invoked when a view is clicked”), для этого в файле Sudoke.java меняем следующее: добавляем строки импорта соответствующих классов и добавляем в описание класса реализацию интерфейса OnClickListener. Короче, файл должен выглядеть после добавлений так:

package org.example.sudoku;

import android.app.Activity;
import android.os.Bundle;
import android.content.Intent;
import android.view.View; 
import android.view.View.OnClickListener;

// добавляем реализацию интерфейса OnClickListener
public class Sudoku extends Activity implements OnClickListener{
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        // настраиваем кнопку About - сообщаем ей, что ее клики 
        // будет обрабатывать класс Sudoku
        
        findViewById(R.id.exit_button).setOnClickListener(this);

        // или более формально так:
        View aboutButton = findViewById(R.id.about_button);
        aboutButton.setOnClickListener(this);
  // в R.id находится список идентификаторов наших ресурсов, 
  // например кнопки About, метод findViewById находит обьект по его
  // идентификатору; обьявляется переменная типа View с именем 
  // aboutButton, которой и присваивается найденная по id кнопка
  // затем вызывается метод setOnClickListener у кнопки, которому
  // передается указатель на обьект, который должен реагировать на клики
  // - в нашем случае this означает саму главную форму
  // но ссылка на кнопку в общем ни для чего больше не нужна,
  // так что можно использовать и первый вариант 
    }
 
   
    @Override
    public void onClick(View v) {
    // это реализация интерфейса OnClickListener - у него согл. доке
    // всего один абстрактный метод, который надо определить
    // как только юзер кликнет по кнопку About приложение определит, 
    // что "слушает" клики для этого обьекта форма Sudoku и вызовет у нее метод
    // onClick, передав ему указатель на кликнутый обьект
    // остается только посмотреть, что за обьект нам сюда дали и выполнить
    // для него какие-то действия
    	switch (v.getId()) {
    	case R.id.about_button:
           	// Intent (намерения) могут быть глобальными (типа "отсылка почты")
	// или приватными (действующими внутри приложения)
	// здесь - последнее
    		Intent i = new Intent(this, About.class);
	// намерение здесь "однозначное" (Explicit) - получает класс, 
	// экземпляр которого хотим создать, а затем запускаем его
	// (этот класс, в данном случае форму)
    		startActivity(i);
    		break;
	case R.id.exit_button:
		finish();
		break;
    	}
    	
    }
}

Ну теперь программа уже на что-то похожа – можно крутить телефон в руках, ориентация автоматически меняется, при начатии на About получаем окошко с описанием программы, при нажатии на Exit – выходим из игры

Как в настоящих играх при старте надо спросить об уровне сложности; для начала надо добавить текстовок (в strings.xml):

<string name="new_game_title">Difficulty</string>
<string name="easy_label">Easy</string>
<string name="medium_label">Medium</string>
<string name="hard_label">Hard</string>

Дальше надо создать файл res/values/arrays.xml и добавить туда массив со значениями уровней сложности:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <array name="difficulty">
    <item>@string/easy_label</item>
    <item>@string/medium_label</item>
    <item>@string/hard_label</item>
  </array>
</resources>

Надо добавить обработчик для кнопки New Game, в котором будет вызываться функция openNewGameDialog, выглядит она так:

private void openNewGameDialog() {
	new AlertDialog.Builder(this)
    		.setTitle(R.string.new_game_title)
    		.setItems(R.array.difficulty,
    			new DialogInterface.OnClickListener() {
    			public void onClick(DialogInterface dialoginterface,  int i) {
    				startGame(i);
    			}
    		})
    		.show();    	
    }    

Ненавижу тех, кто придумал такие языки – оно же совершенно не читабельно; в этой функции строится AlertDialog, заголовок которого берется из строкового ресурса new_game_title, а содержание – из массива; клики должен обрабатывать метод, который тут же обьявлен и реализован – параметра i (который является индексом выбранного значения в массиве) будет передан в функцию startGame, которая собственно начнет новую игру

private static final String TAG = "Sudoku" ;
private void startGame(int i) {
	Log.d(TAG, "clicked on " + i);
    	//	Start game etc...
}

Пока эта функция ничего не делает, кроме вывода в лог сообщения; лог можно увидеть, если пройтись по меню eclipse: Window –> Show View –> Other… –> Android –> LogCat:

scr-17.06-3

Комментариев нет:

Отправить комментарий