BlackBerry触摸屏设备编程


1 BlackBerry 触摸屏设备编程1 作者: 王志刚 2 一 触摸屏幕设计需要注意的地方 开发用于带触摸屏的 BlackBerry® 设备的应用程序时,您应考虑这些设备的以下 UI 功能: • 触摸屏 • 屏幕方位的重要性 • 触摸屏键盘 • 加速度计(一些带触摸屏的 BlackBerry 设备上) 关于这些项目的具体内容和细节,可以参考blackberry的编程白皮书:BlackBerry Java Application Transitioning to Touch Screen Development. 二 触摸屏幕的具体编程和设计的要求 随着触摸屏幕手机的引入,BlackBerry也加入了相应API的支持: net.rim.device.api.ui.Touchscreen 这个类的作用就是系统用来判别当前手机是否是触屏的utility类别,所以一个比较通用的java程序的做法 就是在程序入口中加入这样的逻辑判断: if(Touchscreen.isSupported()) { /* Touch screen logic */ } else { UiApplication.getUiApplication().invokeLater(new Runnable() { public void run() { Dialog.alert("This application requires a touch screen device."); System.exit(0); } }); } 在JDE5.0的示例程序中,有一个例子touchdemo,有关于这个工具类的具体使用方法,可以参考相应的 代理例子在做一个通用的blackberry客户端程序。 触屏手机的引入,可以加入对屏幕的方向的变化,这个在原有的全键盘手机中是没有的,所以在触摸屏幕 手机开发应用过程中,需要加入相应的响应的逻辑. 有两种方式可以用来对屏幕的方位进行控制和调整,第一种方式是在screen的sublayout方法中。 public void sublayout(int width, int height) { //update scrren layout based on orientation if(Display.getOrientation()== Display.ORIENTATION_LANDSCAPE) { invalidate(); } else if(Display.getOrientation()== Display.ORIENTATION_PORTRAIT) { invalidate(); } super.sublayout(width, height); } 3 还有一种方式是在应用中显式调用屏幕的方位信息,然后做出调整: switch(Display.getOrientation()) { case Display.ORIENTATION_LANDSCAPE: Dialog.alert("Screen orientation is landscape"); break; case Display.ORIENTATION_PORTRAIT: Dialog.alert("Screen orientation is portrait"); break; case Display.ORIENTATION_SQUARE: Dialog.alert("Screen orientation is square"); break; default: Dialog.alert("Screen orientation is not known"); break; } 除了对屏幕方位也就是重力切换的处理,在触摸屏幕编程中,需要考虑UI事件的处理和全键盘手机的不 同,关于这部分的具体处理,可以参考下面部分的示例以及后续的内容介绍。 三 一个触摸屏幕应用界面的例子 本章以一个定制的黑莓UI展示程序为例,说明黑莓编程中需要注意的各个方面,通过一个可以定制的个性 化的toolbar的实现以及黑莓应用的背景的切换,来说明触摸屏幕编程和普通全键盘手机编制程序的区 别。 黑莓标准的UI组件里面是没有toolbar的,这里要设计一个toolbar,可以考虑标准UI组件的扩展,这 里我们让toolbar继承自HorizontalFieldManager. 基本的toolbar的特性包括排列的方向和toolbar的高宽等等以及组件的排列性质。这些都是可以配置 的,如果要做到一个比较灵活的设计,这里我们写死。 //public class ToolBarField extends HorizontalFieldManager public class ToolBarField extends HorizontalFieldManager { //private static final int DefaultButtonHeight = 55; //private static final int DefaultButtonWidth = 55; private static final int DefaultButtonHeight = 129; private static final int DefaultButtonWidth = 129; private Vector leftJustifiedButtons = new Vector(); private Vector rightJustifiedButtons = new Vector(); private int preferredHeight = DefaultButtonHeight; private int sideMargin = 3; private int buttonSpacing = 2; private int preferredWidth = Display.getWidth(); private Bitmap bg = null; …… } 在toolbarfield类的设计中,核心的部分在于 private Vector leftJustifiedButtons = new Vector(); private Vector rightJustifiedButtons = new Vector(); 这两个是为了放置用户加入扩种的具体field组件,这里使用的是标准的vector元素,可以添加也可以删 除组件,这里我们简单起见,只实现添加的接口,如下面的addbutton方法所示: public void addButton(ToolBarButtonField button, boolean leftJustified) { super.add(button); if (button.getPreferredHeight() > preferredHeight) preferredHeight = button.getPreferredHeight(); if (leftJustified) 4 { leftJustifiedButtons.addElement(button); } else { rightJustifiedButtons.addElement(button); } } 为了实现更加可供定制化的效果,可以扩充Horizontalmanager的subpaint方法,添加部分背景处理 的能力: protected void subpaint(Graphics graphics) { if (bg != null) { for (int x = 0; x < Display.getWidth();) { graphics.drawBitmap(x, 0, getPreferredWidth(), bg.getHeight(), bg, 0, 0); x += bg.getWidth(); } } else { graphics.setColor(Color.BLACK); graphics.drawRect(0, 0, getPreferredWidth(), getPreferredHeight()); } super.subpaint(graphics); } 如果所有的功能扩充到这里,我们所设计的toolbar也只是一个可供全键盘手机使用的版本,这里我们加 入一个新的touchevent方法,用来加入对触摸屏幕的响应有了这个方法,这个就是一个专门针对 touchscreen的控件版本版本: public boolean touchEvent(TouchEvent event) { int eventID = event.getEvent(); if (eventID == TouchEvent.DOWN || eventID == TouchEvent.UP) { boolean hit = false; int x = event.getX(1); int y = event.getY(1); for (int f = 0; f < getFieldCount(); f++) { ToolBarButtonField field = (ToolBarButtonField)getField(f); XYRect ext = field.getExtent(); if (ext.contains(x, y)) { hit = true; if (eventID == TouchEvent.UP) { field.setActive(false); this.setFocus(); } else { field.setFocus(); field.setActive(true); } invalidate(); break; 5 } } if (!hit && eventID == TouchEvent.UP) { this.setFocus(); invalidate(); } } return true; } 基本上UI的展现,如果把如上的部分做完了,有了基本的UI的事件的处理之后也就可以了,系统会自动对 UI的布局做一些调整,但是作为一个标准的应用组件,需要考虑的是如何让UI的展现在任何情况下都能达 到比较理想的效果,那么就需要对触屏手机的屏幕视图方位切换事件进行相应的处理和考虑了。 protected void sublayout(int maxWidth, int maxHeight) { this.setExtent(maxWidth, getPreferredHeight()); Enumeration iter = leftJustifiedButtons.elements(); if (maxHeight > Display.getHeight()) maxHeight = Display.getHeight(); int y = 0; int curX = sideMargin; // // Layout the left justified buttons // while (iter.hasMoreElements()) { ToolBarButtonField button = (ToolBarButtonField)iter.nextElement(); this.layoutChild(button, button.getPreferredWidth(), button.getPreferredWidth()); this.setPositionChild(button, curX, y); curX = curX + button.getWidth(); } int minX = curX + buttonSpacing; int totalButtonsWidth = 0; // // Layout the right justified buttons // iter = rightJustifiedButtons.elements(); while (iter.hasMoreElements()) { ToolBarButtonField button = (ToolBarButtonField)iter.nextElement(); this.layoutChild(button, button.getPreferredWidth(), button.getPreferredWidth()); totalButtonsWidth += button.getWidth() + buttonSpacing; } totalButtonsWidth -= buttonSpacing; if ((totalButtonsWidth+minX) > maxWidth) { preferredWidth = totalButtonsWidth+minX; } curX = maxWidth; iter = rightJustifiedButtons.elements(); while (iter.hasMoreElements()) { ToolBarButtonField button = (ToolBarButtonField)iter.nextElement(); this.layoutChild(button, button.getPreferredWidth(), button.getPreferredWidth()); 6 curX = curX - button.getWidth(); this.setPositionChild(button, curX, y); curX -= buttonSpacing; } } 我们这里以一个定制的toolbar组件为例,说明如何在BlackBerry的触摸屏幕上响应和处理屏幕的转换 和翻转,做到application对屏幕的自适应能力。Blackberry标准的屏幕切换事件处理中,是推荐用户 在sublayout中对页面组件的布局进行相应的调整,上面的方法中,也实现了部分这样的功能,但是并没 有用到触屏编程中需要考虑的方位问题的检测,所以并不完整。 所以下面我们来考虑这个例子中的一个比较好的切入点,对于屏幕背景的切换,标准的blackberry的 api中,提供了screen以及mainmanager的backbround的背景设置的api,但是由于种种原因是有些 问题,这里我们考虑一种方法,可以绕过这个问题: DecorTestScreen screen = new DecorTestScreen(); VerticalFieldManager horizontalFieldManager = new VerticalFieldManager(VerticalFieldManager.USE_ALL_WIDTH | VerticalFieldManager.USE_ALL_HEIGHT){ //Override the paint method to draw the background image. public void paint(Graphics graphics) { graphics.clear(); switch(Display.getOrientation()) { case Display.ORIENTATION_LANDSCAPE: graphics.drawBitmap(0, 0, Display.getWidth(), Display.getHeight(), backgroundBitmap, 0, 0); break; case Display.ORIENTATION_PORTRAIT: graphics.drawBitmap(0, 0, Display.getWidth(), Display.getHeight(), backgroundBitmap2, 0, 0); break; default: break; } super.paint(graphics); } }; screen.setTitle(toolBar); screen.add(horizontalFieldManager); 这里面使用的办法实际上就是天面提到的在应用中检测程序的方位,然后重新绘制屏幕,只不过我们这里 重新绘制的是屏幕背景不是具体的ui组件,如果是ui组件,更好的办法是它们放置到sublayout方法中 去通过对layoutmanager的设置。 在完成基本的屏幕和toolbar组件的设计之后,剩下的就是测试和验证这个设计了, 我们设计一个toolbar的添加button的类别,然后把这些button类别添加到我们设计的toolbar中,代 码如下: public class ToolBarButtonField extends ImageButtonField //class ToolBarButtonField extends ImageButtonField { //private static final int WIDTH = 55; //private static final int HEIGHT = 55; private static final int WIDTH = 128; private static final int HEIGHT = 128; int prefWidth = WIDTH; int prefHeight = HEIGHT; 7 public ToolBarButtonField(Bitmap focusImage, Bitmap unFocusImage) { super(focusImage, unFocusImage, Field.FOCUSABLE); if (focusImage.getWidth() < WIDTH) prefWidth = focusImage.getWidth(); if (focusImage.getHeight() < HEIGHT) prefHeight = focusImage.getHeight(); } } 在我们应用的主类中,加入如下测试代码: DecorTestScreen screen = new DecorTestScreen(); ToolBarField toolBar = new ToolBarField(); bgbutton = Bitmap.getBitmapResource("app2.png"); ToolBarButtonField boolbarbutton = new ToolBarButtonField(bgbutton, bgbutton); bgbutton1 = Bitmap.getBitmapResource("app1.png"); ToolBarButtonField boolbarbutton1 = new ToolBarButtonField(bgbutton1, bgbutton1); bgbutton2 = Bitmap.getBitmapResource("app3.png"); ToolBarButtonField boolbarbutton2 = new ToolBarButtonField(bgbutton2, bgbutton2); bgbutton3 = Bitmap.getBitmapResource("app4.png"); ToolBarButtonField boolbarbutton3 = new ToolBarButtonField(bgbutton3, bgbutton3); toolBar.addButton(boolbarbutton, false); toolBar.addButton(boolbarbutton1, false); toolBar.addButton(boolbarbutton2, false); toolBar.addButton(boolbarbutton3, false); screen.setTitle(toolBar); screen.add(horizontalFieldManager); //screen.setStatus(toolBar); pushScreen(screen); 通过screen的settitle()方法,就可以把我们新加入的toolbar加入到屏幕上面去,或者通过 setStatus,就可以把我们的toolbar加入到屏幕下面来。 这个是纵向屏幕的示例: 8 在模拟器可以模拟重力切换事件,执行如下操作: 9 最后得到的横向视图如下所示: 四 屏幕横竖切换的屏蔽 有时候,我们可能会需要强行指定手机的横向或者纵向视图,在BlackBerry中,提供了如下一些小的窍 门,可以实现相应的效果。 代码示例:强制在 BlackBerry API 应用程序中使用纵向视图 // Use code like this before invoking UiApplication.pushScreen() int direction = Display.DIRECTION_NORTH; Ui.getUiEngineInstance().setAcceptableDirections(direction); 代码示例:强制在 MIDlet 应用程序中使用横向视图 // Use code like this before invoking Display.setCurrent() in the MIDlet constructor DirectionControl dc = (DirectionControl) ((Controllable) Display.getDisplay(this)). getControl("net.rim.device.api.lcdui.control.DirectionControl"); int directions = DirectionControl.DIRECTION_EAST | DirectionControl.DIRECTION_WEST; dc.setAcceptableScreenDirections(directions); 五 触摸事件类型 TouchEvent 类表示 BlackBerry® 设备用户执行的触摸输入操作。 TouchGesture 类表示的事件是 BlackBerry 设备用户执行的触摸输入操作的组合。在下表中,所有事件均 位于 net.rim.device.api.ui 数据包中 10 除了基本的触摸事件,还有一些其他的触摸事件,blackberry 也提供相应的支持 11 六 可以改进和提高的地方 到目前为止,一个基本的 toolbar 的设计和相应的触摸屏幕的编程就结束了,但是目前这样设计的一个 toolbar 以及对触摸屏幕的处理还是比较初级的,可以改进和提高的地方和空间都很大,比如: 1. 加入 toolbar 中的对屏幕滑动的事件的处理,以容纳更多的 toolbar 组件 2. 对主屏幕布局的处理和切换的响应,在屏幕上加入更多更复杂的 UI 组件来进行设计 3. Toolbar 上的具体组件的点击以及选择相应的处理,这个需要在 touchevent 的处理中加入屏幕的 坐标点检测。 4. 。。。。。。。 关于触摸编程的具体更多的细节和API参考,可以参考blackberry的编程白皮书:BlackBerry Java Application Transitioning to Touch Screen Development以及相应的blackberry的api doc。
还剩10页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 20 金币 [ 分享pdf获得金币 ] 0 人已下载

下载pdf

pdf贡献者

BlackBerry

贡献于2010-09-15

下载需要 20 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf