【问题标题】:Blackberry Click Events黑莓点击事件
【发布时间】:2013-05-15 16:49:56
【问题描述】:

我在 VerticalFieldManager 中有一个 ImageButton,在 Horizo​​ntalFieldManager 中有一个 VFM。当我单击周围字段中的任何位置时,会触发 ImageButton 单击事件。我希望该单击事件仅在单击 ImageButton 时触发,而不是字段(VFM 或 HFM)。

以下是代码:

ImageButton Login = new ImageButton(configModel.getLoginButton(), FOCUSABLE|Field.FIELD_RIGHT, "login.png", "plogin.png",0x9cbe95);
HorizontalFieldManager hfm = new HorizontalFieldManager(USE_ALL_WIDTH);
VerticalFieldManager loginButtonVfm = new VerticalFieldManager(USE_ALL_WIDTH);

loginButtonVfm.add(Login);
hfm.add(loginButtonVfm);
add(hfm);


FieldChangeListener loginListener = new FieldChangeListener() { 
public void fieldChanged(Field field, int context) {
     Dialog.alert("Fired");
    }
}
Login.setChangeListener(loginListener); 

ImageButton 类代码在这里:

public class ImageButton extends Field{

        //Image Button Class 
        private String _label;
        private int _labelHeight;
        private int _labelWidth;
        private Font _font;

        private Bitmap _currentPicture;
        private Bitmap _onPicture;
        private Bitmap _offPicture;
        int color;

        public ImageButton(String text, long style ,String img, String img_hvr, int color){
            super(style);

            _offPicture = Bitmap.getBitmapResource(img);
            _onPicture = Bitmap.getBitmapResource(img_hvr);

            _font = Font.getDefault().derive(Font.BOLD, 7, Ui.UNITS_pt);
            _label = text;


            _labelHeight = _onPicture.getHeight();  
            _labelWidth = _onPicture.getWidth();

            this.color = color;

            _currentPicture = _offPicture;
        }
        public void setImage(String img){

            _offPicture = Bitmap.getBitmapResource(img); 
            _currentPicture = _offPicture;
        }

        /**
         * @return The text on the button
         */
        public void setText(String text){
            _label = text;
        }
            String getText(){
            return _label;
        }

        /**
         * Field implementation.
         * @see net.rim.device.api.ui.Field#getPreferredHeight()
         */
        public int getPreferredHeight(){
            return _labelHeight;
        }
        /**
         * Field implementation.
         * @see net.rim.device.api.ui.Field#getPreferredWidth()
         */
        public int getPreferredWidth(){
            return _labelWidth;
        }

        /**
         * Field implementation.  Changes the picture when focus is gained.
         * @see net.rim.device.api.ui.Field#onFocus(int)
         */
        protected void onFocus(int direction) {

             _currentPicture = _onPicture;
          //  invalidate();
            super.onFocus(direction);
        }

        /**
         * Field implementation.  Changes picture back when focus is lost.
         * @see net.rim.device.api.ui.Field#onUnfocus()
         */
        protected void onUnfocus() {
            _currentPicture = _offPicture;
            invalidate();
            super.onUnfocus();
        }

        /**
         * Field implementation.  
         * @see net.rim.device.api.ui.Field#drawFocus(Graphics, boolean)
         */
//      protected void drawFocus(Graphics graphics, boolean on) {
//          // Do nothing
//      }
        protected void drawFocus(Graphics graphics, boolean on) {
            if (on) {
                     //draw your own custom focus.
                    }
                }
        /**
         * Field implementation.
         * @see net.rim.device.api.ui.Field#layout(int, int)
         */
        protected void layout(int width, int height) {
            setExtent(Math.min( width, getPreferredWidth()),
            Math.min( height, getPreferredHeight()));
        }
        /**
         * Field implementation.
         * @see net.rim.device.api.ui.Field#paint(Graphics)
         */
        protected void paint(Graphics graphics){      
            // First draw the background colour and picture
            graphics.setColor(this.color);
            graphics.fillRect(0, 0, getWidth(), getHeight());
            graphics.drawBitmap(0, 0, getWidth(), getHeight(), _currentPicture, 0, 0);

            // Then draw the text
            graphics.setColor(Color.WHITE);
            graphics.setFont(_font);
            graphics.setFont(graphics.getFont().derive(Font.BOLD)); 
            graphics.drawText(_label, 5,9,
                (int)( getStyle() & DrawStyle.ELLIPSIS | DrawStyle.VALIGN_MASK | DrawStyle.HALIGN_MASK),
                getWidth() - 6 );

        }

        /**
         * Overridden so that the Event Dispatch thread can catch this event
         * instead of having it be caught here..
         * @see net.rim.device.api.ui.Field#navigationClick(int, int)
         */
        protected boolean navigationClick(int status, int time){
            fieldChangeNotify(1);
            return true;
        } 
}

【问题讨论】:

    标签: user-interface blackberry


    【解决方案1】:

    当您尝试自己编写自定义字段时,这种事情实际上很容易找到错误。 (这不是你的错……黑莓 Java 让这件事变得比它应该做的更困难!)

    我认为解决这个问题的最简单方法是重用其他人已经测试过的东西。我建议查看BlackBerry Advanced UI 库,尤其是这两个类:

    BaseButtonField

    BitmapButtonField

    我认为他们完全符合您的需要。我相信您需要更改或添加到 ImageButton 类的重要代码是这样的:

    protected boolean keyChar( char character, int status, int time ) 
    {
        if( character == Characters.ENTER ) {
            clickButton();
            return true;
        }
        return super.keyChar( character, status, time );
    }
    
    protected boolean navigationClick( int status, int time ) 
    {
        if (status != 0) clickButton(); 
        return true;    
    }
    
    protected boolean trackwheelClick( int status, int time )
    {        
        if (status != 0) clickButton();    
        return true;
    }
    
    protected boolean invokeAction( int action ) 
    {
        switch( action ) {
            case ACTION_INVOKE: {
                clickButton(); 
                return true;
            }
        }
        return super.invokeAction( action );
    }    
    
    protected boolean touchEvent( TouchEvent message )
    {
        int x = message.getX( 1 );
        int y = message.getY( 1 );
        if( x < 0 || y < 0 || x > getExtent().width || y > getExtent().height ) {
            // Outside the field
            return false;
        }
        switch( message.getEvent() ) {
    
            case TouchEvent.UNCLICK:
                clickButton();
                return true;
        }
        return super.touchEvent( message );
    }
    
    /**
     * A public way to click this button
     */
    public void clickButton() 
    {
        fieldChangeNotify( 0 );
    }
    

    然后您就可以像现在一样使用FieldChangeListener,但是除非点击发生在您的按钮上,否则图像按钮不会调用它。

    如果你愿意,你当然可以改变上面的代码来使用

        fieldChangeNotify( 1 );
    

    如果1 对您来说是一个有意义的context 值。重要的是添加其他方法,并更改navigationClick()

    【讨论】:

    • 太棒了,如果你能描述一下你的解决方案,问题是什么?
    • 如果您在 touch 屏幕上看到此问题,我认为问题在于缺少 touchEvent() 的实现。如果您查看该代码,您会发现它会检查以确保触摸在按钮内部,而不是外部。你也应该包括其他的东西。例如,keyChar() 确保用户可以将注意力集中在您的按钮上,然后按 ENTER 键单击它。 trackwheelClick() 使拨轮设备等的处理统一。
    • @Nate 上面代码的一个问题是您处理了navigationClick 而不是navigationUnClick,而在触摸事件中,您处理的是UNCCLIK。这将导致 clickButton 被调用两次,一次在单击期间,然后在取消单击触摸设备期间再次调用。我一般建议人们只处理 navigationUnclick() 以符合标准 UI 行为。
    • @adwiv,I agree 100% that using UNCLICK makes a better UI。在这种情况下,这不是我的代码,但我很确定它仍然是正确的,尽管可能有点不清楚。 navigationClick() 中的检查 status != 0 我相信可以防止这个问题。对于触摸设备,它会过滤掉事件,并将其留给touchEvent() 处理。对于键盘设备,navigationClick() 以非零 status 调用。我在 5.0 设备和 6.0 模拟器上进行了快速测试,没有两次调用 clickButton()。它也会在取消点击时触发。
    • @adwiv,我承认它确实闻起来有点骇人听闻。部分原因是此检查基本上是询问是否设置了 none 状态位,并且它们没有定义STATUS_NONE 使用的常量值。您通常不想对此类值的数值表示做出假设的一个原因是,它可能会在将来的版本中更改,并破坏您的代码。不过,在这种情况下,我们知道不会有新的 BlackBerry Java 版本,所以如果代码现在可以正常工作,它总是可以的。因此,在这种特殊情况下,只是需要考虑一些事情。不过好点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多