黑莓中的触摸事件处理
我尝试在 Blackberry 9550 模拟器上实现简单的触摸事件处理,但它不起作用。实际上,touchEvent 永远不会被调用,因为控制台中不会出现任何文本。另外,我在触摸屏幕时会出现一个烦人的“完整菜单”。 这是代码:
package mypackage;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.EventInjector.TouchEvent;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.VirtualKeyboard;
import net.rim.device.api.ui.container.MainScreen;
public class MyScreen extends MainScreen
{
public MyScreen()
{
super(NO_SYSTEM_MENU_ITEMS);
getScreen().getVirtualKeyboard().setVisibility(VirtualKeyboard.HIDE_FORCE);
add(new HandleTouch());
}
class HandleTouch extends Field {
protected void layout(int width, int height) {
setExtent(width, height);
}
public void paint(Graphics graphics) {
graphics.drawBitmap(0, 0, this.getWidth(), this.getHeight(), Bitmap.getBitmapResource("bg.png"), 0, 0);
}
public boolean isFocusable() { return true;}
protected boolean touchEvent(TouchEvent message) {
switch( message.getEvent() ) {
case TouchEvent.CLICK:
System.out.println("----------------------------->CLICK");
return true;
case TouchEvent.DOWN:
System.out.println("----------------------------->DOWN");
return true;
case TouchEvent.MOVE:
System.out.println("----------------------------->MOVE");
return true;
}
System.out.println("PRINT ME SOMETHING IN ANY CASE");
return false;
}
public HandleTouch() {
}
}
}
I try to implement simple touch event handling on Blackberry 9550 emulator, but it doesn't work. Actually, touchEvent never gets called, 'cos no text ever appears in the console. Also, I get an annoying "Full Menu" which appears on touching the screen.
Here's the code:
package mypackage;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.EventInjector.TouchEvent;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.VirtualKeyboard;
import net.rim.device.api.ui.container.MainScreen;
public class MyScreen extends MainScreen
{
public MyScreen()
{
super(NO_SYSTEM_MENU_ITEMS);
getScreen().getVirtualKeyboard().setVisibility(VirtualKeyboard.HIDE_FORCE);
add(new HandleTouch());
}
class HandleTouch extends Field {
protected void layout(int width, int height) {
setExtent(width, height);
}
public void paint(Graphics graphics) {
graphics.drawBitmap(0, 0, this.getWidth(), this.getHeight(), Bitmap.getBitmapResource("bg.png"), 0, 0);
}
public boolean isFocusable() { return true;}
protected boolean touchEvent(TouchEvent message) {
switch( message.getEvent() ) {
case TouchEvent.CLICK:
System.out.println("----------------------------->CLICK");
return true;
case TouchEvent.DOWN:
System.out.println("----------------------------->DOWN");
return true;
case TouchEvent.MOVE:
System.out.println("----------------------------->MOVE");
return true;
}
System.out.println("PRINT ME SOMETHING IN ANY CASE");
return false;
}
public HandleTouch() {
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
1)。首先,使用这段代码,
您实际上设置了一个非常大的字段大小。这是因为 BB UI 框架将最大可用/可能尺寸传递给
layout(int width, int height)
因此该字段应该使用传递值中的某些部分。在这种特定情况下,宽度将是显示器的宽度(360 px),高度是VerticalFieldManager
的最大可能高度(您要添加屏幕字段的高度,它隐式存在于屏幕的内部结构)(1073741823 px)。因此,最终这可能会导致字段需要一个非常大的Bitmap
对象才能进行绘制,并且您可能会收到未捕获的错误“位图太大”(我在 Storm 9530 上这样做) 。因此,
layout()
应该使用一些相对较小的值,例如:2)。
好吧,实际上它确实被调用了。要查看,您只需触摸(而不是单击)即可。鼠标左键模拟点击(一系列
TouchEvent.DOWN
>TouchEvent.CLICK
>TouchEvent.UNCLICK
>TouchEvent.UP
),右键模拟触摸(TouchEvent.DOWN
>TouchEvent.UP
的序列)。3)。
这是因为您的字段不消耗
TouchEvent.UNCLICK
事件。例如,使用此代码,您的字段将不会显示弹出窗口:但是,这对于弹出窗口来说是一个糟糕的解决方案。最好了解真正导致弹出窗口的原因。如果未使用
TouchEvent.UNCLICK
事件,则 BB UI 框架会调用getContextMenu(int instance)
和makeContextMenu(ContextMenu contextMenu, int instance)
方法领域。因此,为了禁用弹出窗口(实际上是由getContextMenu(int instance)
创建的ContextMenu
,您应该重写getContextMenu(int instance)
> 像这样:4)。最后,我建议不要更改
touchEvent(TouchEvent message)
方法的本机/默认行为。您可以只观看/记录它,但不要更改(始终称为其超级版本)。这是因为触摸事件处理比乍一看更复杂。这里很容易出现棘手的错误。我确实相信大多数程序员不应该更改 touchEvent(TouchEvent message) 的本机行为,除非他们确实想创建一些自定义 UI 组件来处理触摸手势。通常他们只想对点击做出反应(作为ButtonField
),但是为此,您可以简单地重写navigationClick(int status, int time)
或navigationUnclick(int status, int time)
。当用户单击触摸屏上的字段时,BB UI 框架将调用这些方法。1). First of all, with this code
you are actually setting a VERY large size of the field. This because the BB UI framework passes max available/possible dimentions to
layout(int width, int height)
so the field should use some part within the passed values. In this specific case the width will be the width of the display (360 px) and the height is the max possible height of theVerticalFieldManager
(the one your are adding screen fields to, it is implicitly present in the screen's internals) (1073741823 px). So, finally this may result in a very largeBitmap
object that is required with the field in order to be painted and you can get an uncaught error "Bitmap is too large" (I did on Storm 9530).So, the
layout()
should use some relatively small values, e.g.:2).
Well, actually it does get called. To see that you should simply touch (versus click). Left button of the mouse simulates clicks (a sequence of
TouchEvent.DOWN
>TouchEvent.CLICK
>TouchEvent.UNCLICK
>TouchEvent.UP
), right button simulates touches (a sequence ofTouchEvent.DOWN
>TouchEvent.UP
).3).
This is because your field does not consume
TouchEvent.UNCLICK
event. For instance, with this code your field will not show the popup:But, that is a bad solution for the popup. It is better to understand what really causes the popup. If
TouchEvent.UNCLICK
event is not consumed then BB UI framework callsgetContextMenu(int instance)
andmakeContextMenu(ContextMenu contextMenu, int instance)
methods of the field. So in order to disable the popup (which is actually aContextMenu
created by thegetContextMenu(int instance)
you should override thegetContextMenu(int instance)
to be smth like this:4). Finally I'd recommend to not change native/default behavior of
touchEvent(TouchEvent message)
method. You can just watch/log it, but don't change (always call its super version). This is because touch events handling is more complicated than it may look at first. It is very easy to get a tricky bug here. I do believe most programmers should not change the native behavior oftouchEvent(TouchEvent message)
unless they really want to create some custom UI component to work with touch gestures. Normally they just want to react on a click (to behave as aButtonField
), however for that you can simply overridenavigationClick(int status, int time)
ornavigationUnclick(int status, int time)
. The BB UI framework will call those methods when user clicks your field on a touch screen.我想在 Arhimed 的答案中添加额外的信息,因为这似乎是谷歌搜索触摸事件的登陆页面......
我的经验并不是要与他相矛盾,而是为未来的读者添加可能的解决方案。我使用的是BB操作系统5.0。我的经验是使用 Storm 模拟器和 Torch 设备。我的应用程序最初是为 OS 4.5 编写的,因此它可能以某种兼容模式运行。
1) 正如第 4 点中所解释的,如果
touchEvent(TouchEvent)
返回 false,则触摸事件将传递给导航单击事件。如果navigationClick(int, int)
返回 false,则会提示系统显示ContextMenu
。2) 在我的系统上,我找不到方法
getContextMenu(int)
。所以我无法测试他的第 3 点。我推测这会在 BB6 或更高版本中添加。3)我确实找到了
getContextMenu()
- 即它不带参数。我尝试重写该方法以返回 null。奇怪的是,这个方法只有在显示初始上下文菜单弹出之后才会被调用!显示初始上下文菜单弹出窗口(?),其上有一个“完整菜单”按钮。当按下该按钮时,将调用此方法,并可用于填充出现的
MainMenu
。 ...奇怪...但是,这意味着覆盖该方法并没有解决我的问题。
4)我无法通过在
touchEvent(TouchEvent)
中返回true来获得解决方案。我同意这会是一种不好的形式(黑客攻击),但我在 BB 平台上学会了很多黑客攻击。但是,滚动列表字段需要传递触摸事件,以便滚动起作用。5)最终我发现了与
TouchEvent.UNCLICK
OP问题类似的东西。我花了 18 个月才找到navigationUnClick(int, int)
方法。与上面的第 1 点类似,未处理的UNCLICK
会变成navigationUnClick(int, int)
调用,这还会导致上下文菜单被显示。因此,通过向
navigationClick(int, int)
和navigationClick(int, int)
添加类似的逻辑;navigationUnClick(int, int)
,我能够获取我的列表&触摸互动良好。这只是补充信息,可能会添加到已接受的答案中。
I would like to add extra info to Arhimed's answer, since this seems to be a landing page for googling touch events...
My experiences are not to contradict him, but to add possible solutions for future readers. I am using BB OS 5.0. My experiences have been with the Storm simulator, and a Torch device. My app was originally written for OS 4.5, so it might be running in some sort of compatibility mode.
1) As explained in his point 4, a Touch Event gets passed along to a Navigation Click event, if
touchEvent(TouchEvent)
returns false. IfnavigationClick(int, int)
returns false, this prompts the system to display aContextMenu
.2) On my system, I could not find a method
getContextMenu(int)
. So I could not test his point 3. I presume this gets added in BB6 or later.3) I did find
getContextMenu()
- i.e. it takes no parameters. I tried to override that method to return null.The strange thing is that this method only gets called after the initial context menu popup is shown! The initial context menu popup (?) gets shown, with a button on it for "Full Menu". When that button is pressed, this method gets called, and can be used to populate the
MainMenu
that appears. ... strange...However, it means that overriding that method did not solve my problem.
4) I was unable to get a solution by returning true in
touchEvent(TouchEvent)
. I agree that this would have been bad form (hack), but I have learnt to hack a lot on the BB platform. However, scrolling list fields need to have the touch event passed up, so that the scroll works.5) Eventually I found something similar to the OP's problem with
TouchEvent.UNCLICK
. It has taken me 18 months to find the methodnavigationUnClick(int, int)
. Similar to my point 1 above, an unhandledUNCLICK
becomes anavigationUnClick(int, int)
call, which can also lead to the context menu being shown.So by adding similar logic to both
navigationClick(int, int)
&navigationUnClick(int, int)
, I was able to get my lists & touches to interact nicely.This is just supplemental info, that may add to the accepted anser.