Главная » Разработка для Android » Обработка событий, основанных на взаимодействии с пользователем

0

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

onKeyDown. Вызывается при нажатии  любой аппаратной  клавиши, включая  манипулятор D-pad,  клавиатуру, а также кнопки  для теле- фонного вызова, отмены звонка, возврата и управления камерой.

onKeyUp.  Вызывается, когда пользователь отпускает  нажатую  кла- вишу.

onTrackballEvent. Вызывается при перемещении  трекбола.

onTouchEvent. Вызывается при нажатии/отпускании сенсорного экрана или же при обнаружении движения.

В листинге 4.14 показан каркас класса, в котором переопределяются все обработчики  событий, отвечающие за взаимодействие с пользователем.

Листинг 4.14. Обработка  пользовательского ввода для Представления

@Override

public boolean onKeyDown(int keyCode, KeyEvent keyEvent) {

// Верните значение true, если событие было обработано. return true;

}

@Override

public boolean onKeyUp(int keyCode, KeyEvent keyEvent) {

// Верните значение true, если событие было обработано. return true;

}

@Override

public boolean onTrackballEvent(MotionEvent event ) {

// Получите тип действия, которое представлено данным событием. int actionPerformed = event.getAction();

// Верните значение true, если событие было обработано.

return true;

}

@Override

public boolean onTouchEvent(MotionEvent event) {

// Получите тип действия, которое представлено данным событием. int actionPerformed = event.getAction();

// Верните значение true, если событие было обработано.

return true;

}

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

Создание приложения Compass View

В следующем примере1 вы создадите новое Представление CompassView, наследуя класс View. Этот элемент будет выводить на экран традиционное изображение компаса (в виде розы ветров), указывая курс (направление). По завершении он должен выглядеть так, как показано на рис. 4.2.

ПРИМЕЧАНИЕ

В главе 14 вы будете использовать Представление CompassView со- вместно с аппаратным акселерометром, чтобы отображать текущее на- правление пользователя. В главе 15 изучите продвинутые методики для рисования на объекте Canvas, с помощью которых можно кардинальным образом улучшить внешний вид этого компаса.

1     Все фрагменты  кода в этом примере  — часть проекта Compass из главы 4, их можно за- грузить с сайта Wrox.com.

1. Создайте  новый проект под названием  Compass, а также Активность для вывода на экран вашего нового Представления CompassView. Затем выполните  новый класс CompassView,  наследующий  View. Создайте конструкторы, которые позволят получать экземпляры Представления как внутри  кода программы,  так и с помощью ресурса с разметкой. Добавьте новый метод initCompassView — он будет использоваться для инициализации элемента — и вызовите его внутри каждого кон- структора.

package com.paad.compass;

import android.content.Context;

import android.graphics.*;

import android.graphics.drawable.*;

import android.view.*;

import android.util.AttributeSet;

import android.content.res.Resources;

public class CompassView extends View {

public CompassView(Context context) {

super(context);

initCompassView();

}

public CompassView(Context context, AttributeSet attrs) {

super(context, attrs);

initCompassView();

}

public CompassView(Context context, AttributeSet ats, int defaultStyle) {

super(context, ats, defaultStyle);

initCompassView();

}

protected void initCompassView() {

setFocusable(true);

}

}

2. Элемент, отображающий компас, всегда должен представлять собой идеальную окружность, занимающую все доступное пространство Холста. Переопределите обработчик onMeasure, чтобы вычислить дли- ну короткой  грани, и вызовите  метод setMeasuredDimension, чтобы установить  высоту и ширину, используя полученное значение.

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

// Компас представляет собой окружность, занимающую все доступное

// пространство.

// Установите размеры элемента, вычислив короткую грань (высоту

// или ширину).

int measuredWidth = measure(widthMeasureSpec);

int measuredHeight = measure(heightMeasureSpec);

int d = Math.min(measuredWidth, measuredHeight);

setMeasuredDimension(d, d);

}

private int measure(int measureSpec) {

int result = 0;

// Декодируйте параметр measureSpec.

int specMode = MeasureSpec.getMode(measureSpec);

int specSize = MeasureSpec.getSize(measureSpec);

if (specMode == MeasureSpec.UNSPECIFIED) {

// Если границы не указаны, верните размер по умолчанию (200). result = 200;

} else {

// Так как вам нужно заполнить все доступное пространство,

// всегда возвращайте максимальный доступный размер. result = specSize;

}

return result;

}

3. Создайте два новых файла с ресурсами для хранения цветов и тексто- вых строк, которые будут использоваться при рисовании компаса.

3.1.Создайте ресурс со строками res/values/strings.xml.

<?xml version="1.0" encoding="utf-8"?>

<resources>

<string name="app_name">Compass</string>

<string name="cardinal_north">N</string>

<string name="cardinal_east">E</string>

<string name="cardinal_south">S</string>

<string name="cardinal_west">W</string>

</resources>

3.2. Создайте ресурс со значениями цветов res/values/colors.xml.

<?xml version="1.0" encoding="utf-8"?>

<resources>

<color name="background_color">#F555</color>

<color name="marker_color">#AFFF</color>

<color name="text_color">#AFFF</color>

</resources>

4. Теперь вернитесь к классу CompassView. Добавьте новое пустое свой- ство, чтобы хранить отображаемое направление, и создайте для него геттер и сеттер.

private float bearing;

public void setBearing(float _bearing) {

bearing = _bearing;

}

public float getBearing() {

return bearing;

}

5. Перейдите к методу initCompassView и получите ссылки на ресурсы, созданные на шаге 3. Сохраните  строковые значения  в виде свойств, используйте значения цветов для создания нового объекта Paint, при- надлежащего классу. Эти объекты вы примените позже при рисовании циферблата для компаса.

private Paint markerPaint; private Paint textPaint; private Paint circlePaint; private String northString; private String eastString; private String southString; private String westString; private int textHeight;

protected void initCompassView() {

setFocusable(true);

circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); circlePaint.setColor(r.getColor(R.color.background_color)); circlePaint.setStrokeWidth(1); circlePaint.setStyle(Paint.Style.FILL_AND_STROKE);

Resources r = this.getResources();

northString = r.getString(R.string.cardinal_north); eastString = r.getString(R.string.cardinal_east); southString = r.getString(R.string.cardinal_south); westString = r.getString(R.string.cardinal_west);

textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

textPaint.setColor(r.getColor(R.color.text_color));

textHeight = (int)textPaint.measureText("yY");

markerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

markerPaint.setColor(r.getColor(R.color.marker_color));

}

6. В завершение необходимо нарисовать циферблат компаса, используя объекты String  и Paint,  созданные в пункте 5. Следующий фрагмент кода сопровождается всего лишь краткими комментариями. В главе 15 вы можете найти больше подробностей о рисовании на объекте Canvas с использованием продвинутых эффектов.

6.1.В первую очередь начните с того, что переопределите метод onDraw в классе CompassView.

@Override

protected void onDraw(Canvas canvas) {

6.2.Найдите  центральную  точку элемента  управления и сохраните короткую грань в качестве радиуса компаса.

int px = getMeasuredWidth() / 2;

int py = getMeasuredHeight() /2 ;

int radius = Math.min(px, py);

6.3.С помощью метода drawCircle нарисуйте внешнюю границу и до- бавьте фон для циферблата. Воспользуйтесь объектом circlePaint, который создали в пункте 5.

// Нарисуйте фон

canvas.drawCircle(px, py, radius, circlePaint);

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

// Поворачивайте ракурс таким образом, чтобы

// "верх" всегда указывал на текущее направление. canvas.save();

canvas.rotate(-bearing, px, py);

6.5.Все, что теперь осталось сделать, — нарисовать  метки. Сделайте полный  поворот Холста, рисуя  отметки  каждые  15° и обозначая направления каждые 45°.

int textWidth = (int)textPaint.measureText("W");

int cardinalX = px-textWidth/2;

int cardinalY = py-radius+textHeight;

// Рисуйте отметки каждые 15°  и текст каждые 45°. for (int i = 0; i < 24; i++) {

// Нарисуйте метку.

canvas.drawLine(px, py-radius, px, py-radius+10, markerPaint);

canvas.save();

canvas.translate(0, textHeight);

// Нарисуйте основные точки if (i % 6 == 0) {

String dirString = "";

switch (i) {

case(0) : {

dirString = northString;

int arrowY = 2*textHeight;

canvas.drawLine(px, arrowY, px-5, 3*textHeight, markerPaint);

canvas.drawLine(px, arrowY, px+5, 3*textHeight, markerPaint);

break;

}

case(6) : dirString = eastString; break; case(12) : dirString = southString; break; case(18) : dirString = westString; break;

}

canvas.drawText(dirString, cardinalX, cardinalY, textPaint);

}

else if (i % 3 == 0) {

// Отображайте текст каждые 45°

String angle = String.valueOf(i*15);

float angleTextWidth = textPaint.measureText(angle);

int angleTextX = (int)(px-angleTextWidth/2); int angleTextY = py-radius+textHeight; canvas.drawText(angle, angleTextX, angleTextY, textPaint);

}

canvas.restore();

canvas.rotate(15, px, py);

}

canvas.restore();

}

7. Чтобы вывести компас на экран, отредактируйте ресурс с разметкой main.xml, заменив  TextView  на новосозданный элемент  Compass- View. Этот процесс более подробно описан в следующем разделе.

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"

android:layout_width="fill_parent" android:layout_height="fill_parent">

<com.paad.compass.CompassView android:id="@+id/compassView" android:layout_width="fill_parent" android:layout_height="fill_parent"

/>

</LinearLayout>

8. Запустив Активность, вы должны увидеть на экране CompassView. Что- бы узнать, как связать CompassView с аппаратным компасом в устрой- стве, перейдите к главе 14.

Использование нестандартных элементов управления

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

Листинг 4.15. Использование нестандартного Представления

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState); CompassView cv = new CompassView(this); setContentView(cv);

cv.setBearing(45);

}

Чтобы использовать этот же элемент внутри ресурса, укажите  полное имя класса при создании  нового узла в описании  разметки,  как показано в следующем фрагменте  XML-кода:

<com.paad.compass.CompassView android:id="@+id/compassView" android:layout_width="fill_parent" android:layout_height="fill_parent"

/>

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

@Override

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);

CompassView cv = (CompassView)this.findViewById(R.id.compassView);

cv.setBearing(45);

}

Источник: Майер P. Android 2 : программирование приложений для планшетных компьютеров и смартфонов : [пер. с англ. ] / Рето Майер. — М. : Эксмо, 2011. — 672 с. — (Мировой компьютерный бестселлер).

По теме:

  • Комментарии