1

我正在尝试创建一个自定义 ButtonField,其焦点(蓝色突出显示颜色)会在几秒钟不活动后消失 - 就像在带触摸屏的 BB 手机上的原始音乐播放器中一样。

通过以下示例,我几乎成功了:

截屏

以下是east.png 和 west.png(由 openclipart.org 提供):

东

西方

这是我的测试代码 MyFocus.java:

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.system.*;
import net.rim.device.api.ui.image.*;

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

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

class MyScreen extends MainScreen {
    public MyScreen() {       
        setTitle("2nd trackpad click not working");
        getMainManager().setBackground(BackgroundFactory.createLinearGradientBackground(Color.WHITE, Color.GRAY, Color.DARKGRAY, Color.GRAY));

        add(new MyButton(MyButton.EAST));
        add(new MyButton(MyButton.WEST));
        add(NF);
    }

    class MyButton extends ButtonField {
        public final static int EAST  = 0;
        public final static int WEST  = 1;

        public final static int WIDTH  = 100;
        public final static int HEIGHT = 100;

        private final XYEdges EDGES = new XYEdges(0, 0, 0, 0);
        private final Application _app = UiApplication.getUiApplication();
        private final static long FOCUS_DURATION = 3000L;    

        private int _focusTimer = -1;
        private final int _direction;

        public MyButton(int direction) {
            setMargin(EDGES);
            setPadding(EDGES);
            setImageSize(WIDTH, HEIGHT);

            setBorder(VISUAL_STATE_NORMAL, 
BorderFactory.createSimpleBorder(EDGES));
            setBorder(VISUAL_STATE_FOCUS, BorderFactory.createSimpleBorder(EDGES));
            setBorder(VISUAL_STATE_ACTIVE, BorderFactory.createSimpleBorder(EDGES));

            setBackground(VISUAL_STATE_NORMAL, BackgroundFactory.createSolidTransparentBackground(Color.GREEN, 0));
            setBackground(VISUAL_STATE_FOCUS, BackgroundFactory.createSolidTransparentBackground(Color.BLUE, 100));
            setBackground(VISUAL_STATE_ACTIVE, BackgroundFactory.createSolidTransparentBackground(Color.RED, 200));

            _direction = direction;
            switch(_direction) {
                case EAST: 
                    setImage(ImageFactory.createImage("east.png"));
                    break;
                case WEST: 
                    setImage(ImageFactory.createImage("west.png"));
                    break;
            }
        }

        // display red background on long touch and hold            
        protected boolean touchEvent(TouchEvent event) {
            if (event.getEvent() == TouchEvent.CLICK) {
                applyThemeOnStateChange();
                return true;
            }
            return super.touchEvent(event);
        }

        protected void onUnfocus() {
            if (_focusTimer != -1) {
                _app.cancelInvokeLater(_focusTimer);
                _focusTimer = -1;
            }            

            super.onUnfocus();
        }

        protected void onFocus(int direction) {
            if (_focusTimer != -1) {
                _app.cancelInvokeLater(_focusTimer);
                _focusTimer = -1;
            }            

            _focusTimer = _app.invokeLater(new Runnable() {
                public void run() {
                    MyButton.super.onUnfocus();
                    _focusTimer = -1;
                }
            }, FOCUS_DURATION, false);

            super.onFocus(direction);
        }

        public int getPreferredHeight(){
                return HEIGHT;
        }

        public int getPreferredWidth(){
                return WIDTH;
        }

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

当我第一次选择一个按钮并等待几秒钟以使其焦点消失时,我的问题是可见的。然后我单击触控板,按下按钮时(已验证),您在屏幕上看不到任何东西 - 它不会变成蓝色或红色。

我已经尝试了 navigationClick() 和 trackwheelUnclick() 的所有组合,但无法解决这个问题。

请问有什么帮助吗?亚历克斯

更新 1:

我尝试了以下方法,但效果不佳(焦点永远消失,可能是因为按钮认为它已经处于所需的视觉状态):

    protected void onFocus(int direction) {
        if (_focusTimer != -1) {
            _app.cancelInvokeLater(_focusTimer);
            _focusTimer = -1;
        }            

        _focusTimer = _app.invokeLater(new Runnable() {
            public void run() {
                MyButton.this.setBorder(BorderFactory.createSimpleBorder(EDGES));
                MyButton.this.setBackground(BackgroundFactory.createSolidTransparentBackground(Color.GREEN, 0));
                invalidate();
                _focusTimer = -1;
            }
        }, FOCUS_DURATION, false);

        super.onFocus(direction);
    }

更新 2:

尝试使用 NullField,仍然无法正常工作:

在此处输入图像描述

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.system.*;
import net.rim.device.api.ui.image.*;

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

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

class MyScreen extends MainScreen {
    static NullField NF = new NullField();
    HorizontalFieldManager hfm = new HorizontalFieldManager() {
        int lastFocused = -1;

        protected int firstFocus(int direction) {
            lastFocused = super.firstFocus(direction);
            System.out.println("XXX firstFocus: " + lastFocused);
            return lastFocused;
        }

        protected int nextFocus(final int direction, final int axis) {

            if (getFieldWithFocus() == NF) {
                return lastFocused;
            } 

            lastFocused = super.nextFocus(direction, axis);
            System.out.println("XXX nextFocus: " + lastFocused);
            return lastFocused;
        }
    };

    public MyScreen() {       
        setTitle("2nd trackpad click not working");
        getMainManager().setBackground(BackgroundFactory.createLinearGradientBackground(Color.WHITE, Color.GRAY, Color.DARKGRAY, Color.GRAY));

        hfm.add(new MyButton(MyButton.WEST));
        hfm.add(new MyButton(MyButton.EAST));
        hfm.add(new MyButton(MyButton.EAST));
        hfm.add(NF);

        add(hfm);
    }

    class MyButton extends ButtonField {
        public final static int EAST  = 0;
        public final static int WEST  = 1;

        public final static int WIDTH  = 100;
        public final static int HEIGHT = 100;

        private final XYEdges EDGES = new XYEdges(0, 0, 0, 0);
        private final Application _app = UiApplication.getUiApplication();
        private final static long FOCUS_DURATION = 3000L;    

        private int _focusTimer = -1;
        private final int _direction;

        public MyButton(int direction) {
            setMargin(EDGES);
            setPadding(EDGES);
            setImageSize(WIDTH, HEIGHT);

            setBorder(VISUAL_STATE_NORMAL, BorderFactory.createSimpleBorder(EDGES));
            setBorder(VISUAL_STATE_FOCUS, BorderFactory.createSimpleBorder(EDGES));
            setBorder(VISUAL_STATE_ACTIVE, BorderFactory.createSimpleBorder(EDGES));

            setBackground(VISUAL_STATE_NORMAL, BackgroundFactory.createSolidTransparentBackground(Color.GREEN, 0));
            setBackground(VISUAL_STATE_FOCUS, BackgroundFactory.createSolidTransparentBackground(Color.BLUE, 100));
            setBackground(VISUAL_STATE_ACTIVE, BackgroundFactory.createSolidTransparentBackground(Color.RED, 200));

            _direction = direction;
            switch(_direction) {
                case EAST: 
                    setImage(ImageFactory.createImage("east.png"));
                    break;
                case WEST: 
                    setImage(ImageFactory.createImage("west.png"));
                    break;
            }
        }

        protected boolean touchEvent(TouchEvent event) {
            if (event.getEvent() == TouchEvent.CLICK) {
                applyThemeOnStateChange();
                return true;
            }
            return super.touchEvent(event);
        }

        protected void onUnfocus() {
            if (_focusTimer != -1) {
                _app.cancelInvokeLater(_focusTimer);
                _focusTimer = -1;
            }            

            super.onUnfocus();
        }

        protected void onFocus(int direction) {
            if (_focusTimer != -1) {
                _app.cancelInvokeLater(_focusTimer);
                _focusTimer = -1;
            }            

            _focusTimer = _app.invokeLater(new Runnable() {
                public void run() {
                    MyScreen.NF.setFocus();
                    _focusTimer = -1;
                }
            }, FOCUS_DURATION, false);

            super.onFocus(direction);
        }

        public int getPreferredHeight(){
                return HEIGHT;
        }

        public int getPreferredWidth(){
                return WIDTH;
        }

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

1 回答 1

1

我可能会在调用之前覆盖该drawFocus()方法以检查标志,然后在 in中将标志设置为 true 并安排 Runnable 将标志更改为 false 并使其无效(也在 in 中将其设置为 false )。也不必担心取消计时器或以这种方式进行的任何事情,因为它只会更改标志并使其无效,使其保持在适当的状态。_showFocussuper.drawFocus()onFocus()_showFocusonUnfocus()

于 2011-08-05T17:30:20.270 回答