Главная » Разработка для Android » Использование сенсорного экрана

0

Мобильные сенсорные  экраны  существуют  со времен Apple Newton и Palm Pilot,  хотя удобство их использования вызывало  смешанные  чув- ства. Недавно  эта технология  обрела вторую жизнь  вместе с появлением таких устройств,  как Nintendo DS и Apple iPhone,  принесших  множество инноваций.

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

Пальцевый ввод менее точный и часто основывается на движении, а не на простом прикосновении. Стандартные приложения в Android  широко используют сенсорные интерфейсы, рассчитанные на пальцы, помимо всего прочего, они предусматривают использование жестов «перетаскивания» для прокрутки списков или выполнения других действий.

Чтобы создать Представление или Активность, которые могут взаимодей- ствовать с сенсорным экраном, переопределите обработчик onTouchEvent:

@Override

public boolean onTouchEvent(MotionEvent event) {

return super.onTouchEvent(event);

}

Верните true, если вы обработали нажатие на экран. В ином случае вер- ните false, чтобы передавать события по цепочке от Представления до Актив- ности, пока оно не будет успешно обработано.

Обработка  одиночных и множественных  касаний. onTouchEvent срабатывает  в трех случаях: когда пользователь прикасается к экрану, из- меняет  позицию  касания  и отпускает  палец. В Android  2.0 (API  level 5) появилась поддержка платформы для обработки произвольного количества одновременных событий,  связанных с сенсорным  экраном.  Для  каждого касания  выделяется отдельный  точечный  идентификатор, ссылающийся на параметр MotionEvent.

ПРИМЕЧАНИЕ

Не все сенсорные экраны уведомляют о нескольких одновременных на- жатиях. Если аппаратное обеспечение не поддерживает множественные касания, Android возвращает одиночное событие.

Вызовите метод getAction из параметра MotionEvent, чтобы определить тип события, которое запустило  обработчик. Независимо от того, поддер- живает устройство  множественные касания  или нет, вы все равно можете использовать константы ACTION_UP/DOWN/MOVE/CANCEL/OUTSIDE для получения типа события, как показано в листинге 15.24.

Листинг 15.24. Обработка  одиночных (или первых) касаний

@Override

public boolean onTouchEvent(MotionEvent event) {

int action = event.getAction();

switch (action) {

case (MotionEvent.ACTION_DOWN)  : // Нажатие на сенсорном экране break;

case (MotionEvent.ACTION_UP)  : // Завершение нажатия break;

case (MotionEvent.ACTION_MOVE)  : // Контакт был перемещен по экрану break;

case (MotionEvent.ACTION_CANCEL) : // Касание было отменено break;

case (MotionEvent.ACTION_OUTSIDE): // Произошло движение за пределами

// границ экранного элемента,

// который отслеживается break;

}

return super.onTouchEvent(event);

}

Чтобы  следить  за касаниями в разных  точках, необходимо  использо- вать константы  MotionEvent.ACTION_MASK и MotionEvent.ACTION_ POINTER_ID_MASK для определения типа события (будь то ACTION_ POINTER_DOWN или ACTION_POINTER_UP) и идентификатора контакта, который его вызвал, соответственно.  На примере листинга 15.25 вызовите  метод getPointerCount, чтобы определить  наличие  множествен- ных касаний.

Листинг 15.25. Обработка  множественных касаний

@Override

public boolean onTouchEvent(MotionEvent event) {

int action = event.getAction();

if (event.getPointerCount() > 1) {

int actionPointerId = action & MotionEvent.ACTION_POINTER_ID_MASK;

int actionEvent = action & MotionEvent.ACTION_MASK;

// Какие-либо действия с идентификатором контакта и событием.

}

return super.onTouchEvent(event);

}

Объект MotionEvent содержит координаты текущего контакта  с экра- ном. Вы можете получить их с помощью методов getX и getY. Возвращен- ные значения  — относительные для соответствующего Представления или Активности.

В случае с множественными касаниями объект MotionEvent включает текущую позицию  каждого контакта.  Чтобы  найти координаты заданно- го контакта, передавайте  его индекс в методы getX и getY. Обратите  вни- мание, что этот индекс не имеет никакого  отношения  к идентификатору

контакта. Чтобы получить  индекс заданного контакта, используйте метод findPointerIndex, передавая ему ID соответствующего касания, как показано в листинге 15.26.

Листинг 15.26. Получение  координат  соприкосновения с экраном

int xPos = -1; int yPos = -1;

if (event.getPointerCount() > 1) {

int actionPointerId = action & MotionEvent.ACTION_POINTER_ID_MASK;

int actionEvent = action & MotionEvent.ACTION_MASK;

int pointerIndex = findPointerIndex(actionPointerId);

xPos = (int)event.getX(pointerIndex);

yPos = (int)event.getY(pointerIndex);

}

else {

// Одиночное касание.

xPos = (int)event.getX();

yPos = (int)event.getY();

}

Параметр  MotionEvent содержит  степень  давления,  которое  было применено  к экрану. Получить  его можно с помощью метода getPressure, который возвращает  значение в пределах между 0 (без давления) и 1 (нор- мальное давление).

ПРИМЕЧАНИЕ

В зависимости от калибровки аппаратного обеспечения это значение может быть больше 1.

Наконец,  вы также можете определить  нормализованный размер теку- щей области соприкосновения, используя метод getSize. Он возвращает значения в диапазоне между 0 и 1, где 0 обозначает очень точное измерение, а 1 указывает  на возможное  «толстое» прикосновение, при котором поль- зователь, вероятно, вовсе не пытался ничего нажать.

Отслеживание движений. Каждый раз при изменении позиции текущего прикосновения, его давления  или размера срабатывает  новый обработчик onTouchEvent с действием ACTION_MOVE.

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

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

события из буфера, используя набор методов getHistorical* и передавая ин- дексы позиций, как показано в листинге 15.27. Обратите внимание, что, как и в случае с методами getX и getY, описанными ранее, вы можете передать индекс контакта для получения данных о касаниях  из нескольких  точек.

Листинг 15.27. Получение  истории изменения значений  для событий касания

int historySize = event.getHistorySize();

long time = event.getHistoricalEventTime(i);

if (event.getPointerCount() > 1) {

int actionPointerId = action & MotionEvent.ACTION_POINTER_ID_MASK;

int pointerIndex = findPointerIndex(actionPointerId);

for (int i = 0; i < historySize; i++) {

float pressure = event.getHistoricalPressure(pointerIndex, i);

float x = event.getHistoricalX(pointerIndex, i);

float y = event.getHistoricalY(pointerIndex, i);

float size = event.getHistoricalSize(pointerIndex, i);

// TODO: Какие-либо действия с каждым контактом

}

}

else {

for (int i = 0; i < historySize; i++) {

float pressure = event.getHistoricalPressure(i);

float x = event.getHistoricalX(i);

float y = event.getHistoricalY(i);

float size = event.getHistoricalSize(i);

// TODO: Какие-либо действия с каждым контактом

}

}

На деле для реагирования на движения необходимо обрабатывать каж- дое событие из истории,  следующее  за текущими  значениями из объекта MotionEvent, как продемонстрировано в листинге 15.28.

Листинг 15.28. Обработка  касательных движений  по экрану

@Override

public boolean onTouchEvent(MotionEvent event) {

int action = event.getAction();

switch (action) {

case (MotionEvent.ACTION_MOVE)

{

int historySize = event.getHistorySize();

for (int i = 0; i < historySize; i++) { float x = event.getHistoricalX(i); float y = event.getHistoricalY(i); processMovement(x, y);

}

float x = event.getX();

float y = event.getY();

Продолжение ?

Листинг 15.28 (продолжение)

processMovement(x, y);

return true;

}

}

return super.onTouchEvent(event);

}

private void processMovement(float _x, float _y) {

// Todo: Обработка движения.

}

Использование интерфейса OnTouchListener. Вы можете отслеживать касания  без наследования ранее созданных Представлений, просто добавив OnTouchListener к любому объекту View, используя метод setOnTouchListener. В листинге  15.29 показано, как назначить  новую реализацию интерфейса OnTouchListener для существующего  Представления внутри Активности.

Листинг 15.29. Назначение OnTouchListener для существующего

Представления

myView.setOnTouchListener(new OnTouchListener() {

public boolean onTouch(View _view, MotionEvent _event) {

// TODO Реакция на движение return false;

}

});

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

По теме:

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