Blackberry 6: отображение меню при долгом нажатии, выполнение 1 действия при коротком нажатии

Добрый день, коллеги программисты ББ.

если вы посмотрите на родное приложение Контакты (Адресная книга) на телефоне Blackberry 6 с сенсорным экраном - оно ведет себя очень естественно:

  1. По короткому тапу выполняется действие по умолчанию — просмотр выбранной записи адресной книги
  2. При длительном касании и удержании отображается меню с несколькими действиями:

Адресная книга

Я сам пытаюсь создать приложение с ListField и аналогичным (и интуитивно понятным) поведением: запускать действие по умолчанию при коротком касании и отображать меню в центре экрана с несколькими дополнительными действиями при более длительном касании.

Я много искал и, к сожалению, смог создать только тестовое приложение с совершенно противоположным поведением:

Я слушаю TouchGesture.HOVER и запускаю editMenu.run(). А по короткому тапу меню приходит само собой (пока не нашел, чем оно появляется, каким-то методом в MainScreen/Screen?). Я пытался запустить onMenu(0), но меню появляется в верхнем/правом углу, а не в центре экрана.

Приложение MyList

Ниже приведен мой очень простой тестовый код MyList.java, помогите мне его исправить:

package mypackage;

import java.util.*;
import net.rim.device.api.collection.*;
import net.rim.device.api.collection.util.*; 
import net.rim.device.api.system.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.ui.decor.*;
import net.rim.device.api.util.*;

public class MyList extends UiApplication {
    public static void main(String args[]) {
        MyList app = new MyList();
        app.enterEventDispatcher();
    }

    public MyList() {
        pushScreen(new MyScreen());
    }
} 

class MyScreen extends MainScreen {

    ObjectListField myList = new ObjectListField() {
        protected boolean touchEvent(TouchEvent event) {
            if (event.getEvent() == TouchEvent.GESTURE) {
                TouchGesture gesture = event.getGesture();
                if (gesture.getEvent() == TouchGesture.HOVER) {
                    System.err.println("XXX hover=" + gesture.getHoverCount() + ", index=" + myList.getSelectedIndex());
                    editMenu.run();
                    // onMenu(0);
                    return true;
                }
            }
            return super.touchEvent(event);
        }
    };

    private final MenuItem addMenu = new MenuItem("Add item", 0, 0) {  
        public void run() { 
            Status.show("Adding new item");
        }
    };

    private final MenuItem editMenu = new MenuItem("Edit item", 1, 0) {  
        public void run() { 
            Status.show("Editing existing item: " + myList.getSelectedIndex());
        }
    };

    private final MenuItem removeMenu = new MenuItem("Remove item", 2, 0) {  
        public void run() { 
            Status.show("Removing existing item: " + myList.getSelectedIndex());
        }
    };


    public MyScreen() {
        setTitle("How to display menu on long click?");
        myList.set(new String[] { "Item 1", "Item 2", "Item 3", "Item 4", }); 
        add(myList);

        addMenuItem(addMenu);
        addMenuItem(editMenu);
        addMenuItem(removeMenu);
    }
}

Спасибо! Алекс


person Alexander Farber    schedule 08.05.2011    source источник


Ответы (1)


Описанная здесь проблема связана с новыми всплывающие меню введен в OS 6. Использование TouchEvent является хаком и не будет работать для всех устройств (не все устройства OS 6 имеют сенсорный экран).

class MyScreen extends MainScreen {

    ObjectListField myList = new ObjectListField() {
        protected boolean navigationClick(int status, int time) {
            editMenu.run();
            return true;
        }
    };

    private final MenuItem addMenu = new MenuItem("Add item", 0, 0) {  
        public void run() { 
            Status.show("Adding new item");
        }
    };

    private final MenuItem editMenu = new MenuItem("Edit item", 1, 0) {  
        public void run() { 
            Status.show("Editing existing item: " + myList.getSelectedIndex());
        }
    };

    private final MenuItem removeMenu = new MenuItem("Remove item", 2, 0) {  
        public void run() { 
            Status.show("Removing existing item: " + myList.getSelectedIndex());
        }
    };

    public MyScreen() {
        setTitle("How to display menu on long click?");
        myList.set(new String[] { "Item 1", "Item 2", "Item 3", "Item 4", }); 
        add(myList);

        addMenuItem(addMenu);
        addMenuItem(editMenu);
        addMenuItem(removeMenu);
    }
}

Почему это работает так, как ожидалось? Добавление элементов меню на экран неявно устанавливает ContextMenuProvider для экрана (оно определяет стратегию отображения всплывающего меню экрана). Таким образом, наведение работает, как и ожидалось, на уровне экрана — именно экран обнаруживает «событие наведения» и открывает всплывающее меню. С другой стороны, «краны» обрабатываются списком в navigationClick().

person Vit Khudenko    schedule 09.05.2011
comment
Мне нравится, как ты спрашиваешь. Так что приятно ответить на такой хорошо сформулированный вопрос. - person Vit Khudenko; 09.05.2011