views:

391

answers:

2

I need to implement OnLongClickListener for BlackBerry platform.
It may be used for user input (ex phone keyboard implementation) or other functionality (navigation, rewind control, zoom control, etc). There are requirements:

  • target control to listen - custom ButtonField
  • it should be version compiliant with 4.5 and 4.6, so no touchEvents etc.
  • configurable long click time

Do you have some suggestions about concept and implementation?
Also, what issues I can get in using multiple listeners for same field?

Thank you!

+1  A: 

Well, just straightforward advice. Override navigationClick and navigationUnclick - the storm will automatically map presses on the screen to these events.

You'll have to use a separate Thread or a Timer to actually time the click - there's no way to do that otherwise (you do get a time parameter in both events, but you want the event to fire before the unclick).

Also you'll have to be careful about what happens if the user say unclicks and then clicks again within the span of a long click interval. Probably you want to start the timer again.

Multiple listeners shouldn't provide any difficulty - assuming that whatever class implements the listener is well-behaved (doesn't do heavy processing within the callback method). Generally BlackBerry UI components can have a maximum of 1 listener at a time (that's why there's a setChangeListener instead of addChangeListener). Unless there's a compelling reason to go the android route with multiple listeners, I'd stick with just one - it'll make implementation a little easier, and it's consistent with the BB paradigm.

Anthony Rizk
Thanks Anthony, great advices!
Max Gontar
A: 

I have followed Anthony's advices, implementation using TimerTask and ButtonField.
Be carfull with CONSUME_CLICK style, somehow it excludes navigationClick event.
Also, I have expirienced troubles with Bold 9000/8900 simulators, navigationClick is fired after trackwheel is unclicked. But sample works fine with Storm.

Interface:

public interface LongClickListener {
    public void longClickEvent(Field field, int eventNumber);
}

Control itself:

public class LongClickButtonField extends ButtonField { 

    boolean mContinuousMode = false;
    Timer mLongClickTimer = null;

    long mLongClickDelay = 1000;
    long mContinuousPeriod = 500; 
    LongClickListener mLongClickListener = null;

    public LongClickButtonField(String label) {
     super(label);
    }

    public LongClickButtonField(String label, boolean continuousMode) {
     this(label);
     mContinuousMode = continuousMode;
    }

    public void setLongClickListener(LongClickListener longClickListener) {
     mLongClickListener = longClickListener;
    }

    protected boolean navigationClick(int status, int time) {
     mLongClickTimer = new Timer();
     final Field eventArg = this;
     if(!mContinuousMode)
     {
     mLongClickTimer.schedule(new TimerTask() {public void run() {
      mLongClickListener.longClickEvent(eventArg, 0);
     }}, mLongClickDelay);
     }
     else
     {
      mLongClickTimer.schedule(new TimerTask(){
       int eventNum= 0;
       public void run() {    
       mLongClickListener.longClickEvent(eventArg, eventNum);
       eventNum++;
      }}, mLongClickDelay, mContinuousPeriod);
     }
     return true;
    }

    protected boolean navigationUnclick(int status, int time) {
     mLongClickTimer.cancel();
     return true;
    }
}

Use:

public class Scr extends MainScreen implements LongClickListener {
    LabelField mStatusLabel = new LabelField("status") {
     protected void paint(Graphics graphics) {
      graphics.setColor(Color.BLACK);
      super.paint(graphics);
     };
    };

    public Scr() {
     LongClickButtonField button = new LongClickButtonField(
       "click & hold 5 s");
     LongClickButtonField buttonContinuous = new LongClickButtonField(
       "click & hold > 5 s", true);
     button.setLongClickListener(this);
     buttonContinuous.setLongClickListener(this);
     add(mStatusLabel);
     add(button);
     add(buttonContinuous);
    }

    public void longClickEvent(final Field field, final int eventNumber) {
     UiApplication.getUiApplication().invokeLater(new Runnable() {
      public void run() {
       mStatusLabel.setText(  
         ((ButtonField) field).getLabel()
         + " event #"  
         + String.valueOf(eventNumber));
      }
     });

    }
}
Max Gontar