Сенсорная обработка событий в Blackberry - PullRequest
3 голосов
/ 21 мая 2011

Я пытаюсь реализовать простую обработку событий касания в эмуляторе Blackberry 9550, но это не работает. На самом деле touchEvent никогда не вызывается, потому что в консоли никогда не появляется текст. Кроме того, я получаю раздражающее «Полное меню», которое появляется при касании экрана. Вот код:

package mypackage;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.EventInjector.TouchEvent;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.VirtualKeyboard;
import net.rim.device.api.ui.container.MainScreen;

public class MyScreen extends MainScreen
{   
public MyScreen()
{    
    super(NO_SYSTEM_MENU_ITEMS);
    getScreen().getVirtualKeyboard().setVisibility(VirtualKeyboard.HIDE_FORCE);      
    add(new HandleTouch());

}

class HandleTouch extends Field {

    protected void layout(int width, int height) {
        setExtent(width, height);
    }

    public void paint(Graphics graphics) {
        graphics.drawBitmap(0, 0, this.getWidth(), this.getHeight(), Bitmap.getBitmapResource("bg.png"), 0, 0);
    }

    public boolean isFocusable() { return true;}

    protected boolean touchEvent(TouchEvent message) {
        switch( message.getEvent() ) {
        case TouchEvent.CLICK:
            System.out.println("----------------------------->CLICK");
            return true;
        case TouchEvent.DOWN:
            System.out.println("----------------------------->DOWN");
            return true;    
        case TouchEvent.MOVE:
            System.out.println("----------------------------->MOVE");
            return true;    
        }
        System.out.println("PRINT ME SOMETHING IN ANY CASE");
        return false;
    }

    public HandleTouch() {

    }
}

}

Ответы [ 2 ]

6 голосов
/ 22 мая 2011

1). Прежде всего, с этим кодом

protected void layout(int width, int height) {
    setExtent(width, height);
}

вы на самом деле устанавливаете ОЧЕНЬ большой размер поля. Это связано с тем, что структура пользовательского интерфейса BB передает максимально доступные / возможные измерения в layout(int width, int height), поэтому поле должно использовать некоторую часть в переданных значениях. В этом конкретном случае ширина будет шириной дисплея (360 пикселей), а высота - максимально возможной высотой VerticalFieldManager (к которому вы добавляете поля экрана, он неявно присутствует во внутренних элементах экрана) ( 1073741823 px). Итак, в конечном итоге это может привести к очень большому Bitmap объекту, который требуется с полем для рисования, и вы можете получить неперехваченную ошибку «Растровое изображение слишком велико» (я это делал в Storm 9530).

Итак, layout() должен использовать несколько относительно небольших значений, например ::

protected void layout(int width, int height) {
    setExtent(Math.min(width, 360), Math.min(height, 480));
}

2).

На самом деле touchEvent никогда не вызывается

Ну, на самом деле это называется. Чтобы увидеть, что вы должны просто коснуться (против щелчка). Левая кнопка мыши имитирует щелчки (последовательность TouchEvent.DOWN> TouchEvent.CLICK> TouchEvent.UNCLICK> TouchEvent.UP), правая кнопка имитирует касания (последовательность TouchEvent.DOWN> TouchEvent.UP).

3).

Кроме того, я получаю раздражающее «Полное меню», которое появляется при прикосновении к экрану.

Это потому, что ваше поле не использует TouchEvent.UNCLICK событие. Например, с этим кодом ваше поле не будет отображать всплывающее окно:

protected boolean touchEvent(TouchEvent message) {
    return true;
}

Но это плохое решение для всплывающего окна. Лучше понять, что на самом деле вызывает всплывающее окно. Если событие TouchEvent.UNCLICK не используется, то инфраструктура пользовательского интерфейса BB вызывает getContextMenu(int instance) и makeContextMenu(ContextMenu contextMenu, int instance) методы поля. Таким образом, чтобы отключить всплывающее окно (которое на самом деле ContextMenu создано getContextMenu(int instance), вы должны переопределить getContextMenu(int instance), чтобы получить что-то вроде этого:

public ContextMenu getContextMenu(int instance) {
    // just in case check if a context menu is requested
    // in order not to disable other types of menu
    boolean isContextMenu = (Menu.INSTANCE_CONTEXT == instance);
    return isContextMenu ? null : super.getContextMenu(instance);
}

4). Наконец, я бы порекомендовал не изменять родное / стандартное поведение метода touchEvent(TouchEvent message). Вы можете просто просмотреть / записать его, но не меняйте (всегда вызывайте его супер версию). Это связано с тем, что обработка сенсорных событий сложнее, чем кажется на первый взгляд. Здесь очень легко получить сложную ошибку. Я верю, что большинству программистов не следует изменять собственное поведение touchEvent(TouchEvent message), если они действительно не хотят создавать какой-либо пользовательский компонент пользовательского интерфейса для работы с сенсорными жестами. Обычно они просто хотят реагировать на клик (вести себя как ButtonField), однако для этого вы можете просто переопределить navigationClick(int status, int time) или navigationUnclick(int status, int time). Инфраструктура пользовательского интерфейса BB будет вызывать эти методы, когда пользователь нажимает ваше поле на сенсорном экране.

3 голосов
/ 08 мая 2012

Я хотел бы добавить дополнительную информацию к ответу Архимеда, так как это, кажется, целевая страница для событий касания Google ...

Мой опыт не противоречит ему, а добавляет возможные решения для будущих читателей. Я использую BB OS 5.0. Мой опыт был с симулятором Storm и устройством Torch. Мое приложение изначально было написано для OS 4.5, поэтому оно может работать в каком-то режиме совместимости.

1) Как объяснено в его пункте 4, событие Touch передается событию Navigation Click, если touchEvent(TouchEvent) возвращает false. Если navigationClick(int, int) возвращает false, система предлагает отобразить ContextMenu.

2) В моей системе я не смог найти метод getContextMenu(int). Поэтому я не смог проверить его пункт 3. Полагаю, это будет добавлено в BB6 или позже.

3) Я нашел getContextMenu() - т.е. он не принимает параметров. Я попытался переопределить этот метод, чтобы вернуть ноль.

Странно то, что этот метод вызывается только после , когда отображается начальное всплывающее контекстное меню! Отображается начальное контекстное меню (?) С кнопкой «Полное меню». Когда эта кнопка нажата, этот метод вызывается и может использоваться для заполнения появившегося MainMenu. ... странно ...

Однако это означает, что переопределение этого метода не решило мою проблему.

4) Мне не удалось найти решение, вернув true в touchEvent(TouchEvent). Я согласен, что это было бы плохо (взломать), но я научился много взламывать на платформе BB. Однако в полях списка прокрутки должно быть передано событие касания, чтобы прокрутка работала.

5) В конце концов я обнаружил нечто похожее на проблему ОП с TouchEvent.UNCLICK. Мне понадобилось 18 месяцев, чтобы найти метод navigationUnClick(int, int). Как и в моем пункте 1 выше, необработанный UNCLICK становится вызовом navigationUnClick(int, int), что может также привести к отображению контекстного меню.

Таким образом, добавив одинаковую логику к обоим navigationClick(int, int) и navigationUnClick(int, int), я смог заставить свои списки и прикосновения взаимодействовать.


Это просто дополнительная информация, которая может добавить к принятому anser.

...