I have this:
#Override
public void onTouch(final ControlTouchEvent event) {
int action = event.getAction();
if (action == Control.Intents.TOUCH_ACTION_PRESS) {
Log.d("Touch Test", "Touch: Press at " + event.getX() + " - " + event.getY());
}
else if (action == Control.Intents.TOUCH_ACTION_RELEASE) {
Log.d("Touch Test", "Touch: Release at " + event.getX() + " - " + event.getY());
}
}
Basically, its working but for single presses. Let me explain.
If you press the screen and release on same position, lest call it a "click" both logs get fired, the Press first, then the release.
But I want to manage scrolling, so, if I press, then move my finger, and release in other place of the screen, I only get the press event fired.
I want to know start position when pressed and end position when released, so I can scroll the layout!
How can I achieve that?
Thanks!
But I want to manage scrolling, so, if I press, then move my finger, and release in other place of the screen, I only get the press event fired.
I think that's because you are doing a swipe event, so on release it will trigger the Control.Intents.SWIPE_DIRECTION_[UP|DOWN|RIGHT|LEFT] action and not the Control.Intent.TOUCH_ACTION_RELEASE.
If you don't need the swipe events you can remove the Swipe intent from the manifest. Otherwise you should consider to use the SWIPE intents to manage the scrolling. The main difference is that with Swipe events you don't get the magnitude of the swipe you only get the direction, but that should be enough for the most cases.
The SmartWatch 2 is not functioning consistently in regard to the touch detection. Thus, not every TOUCH_ACTION_PRESS event is followed by a TOUCH_ACTION_RELEASE event (as it is the case for the SmartWatch 1), but it can be followed by a SWIPE event, for example. Also, the SWIPE events are too easily triggered, so any attempt to implement the scrolling as you want it, would not be successful.
Best thing to do is to use the Gallery and ListView for smooth scrolling.
As the others said, the "scroll" as is, is not supported.
The SDK is good, but lacks some functions. I hope Sony update it in the future, however, it may be too late now.
This is what I ended doing on my app:
I used a TOUCH_ACTION_PRESS to save the press action in a global object, then, I used the SWIPE event to get a direction.
In the Swipe routine, I ask if the PRESS event has been made, and if so, I do the "scrolling" with the SWIPE direction.
To get a better feel, I ask where the PRESS started on the Y axis, so, if lets say the pressed started at bottom of the screen, and the swipe was swipe up, I move the view more than if the press started at half screen.
It is not very smooth, but, I think there is no better way to do it. The other option is to use on screen buttons, but I do not like them.
I haven't fully understood this yet but I am getting three sets of events when I have not got any clickable objects:
For simple taps: onTouch(PRESS) followed by onTouch(RELEASE)
For swipes: onTouch(PRESS) followed by onSwipe()
Unfortunately for very short swipes, or slipped taps:
onTouch(PRESS) only
It appears to differ if you have clickable objects. This is the pattern I get when I do:
For simple taps: onTouch(PRESS) followed by onTouch(RELEASE) then onObjectClick
For all swipes: onTouch(PRESS) followed by onSwipe()
Since onSwipe only gives the direction and not the event (with location), I cannot find a satisfactory way of handling this except to process all events when I get on onTouch(PRESS) and then undo the tap operation if there is a follow up onSwipe. Depending on what you are doing this undo could be easy or really tricky - but if fast enough the user will never notice...
Turning off swipe in the manifest doesn't help - you just lose the onSwipe events and sadly don't gain the onTouch(RELEASE).
Related
I'm writing an application using wxHaskell and I want to be able to detect the state of a button (whether or not it is pressed at any given time). I'm having a bit of trouble figuring out how to do this, however. First I thought that there might be a "button is pressed" attribute that I could use, but there didn't seem to be. Then I had the idea of maintaining an IORef which I update on button-up and button-down events. However, that would require that the Button object actually have button-up and button-down events, which is does not appear to. It is an instance of Commanding, but I assume that the command event is fired on button-up only, which isn't enough for that idea. Does anyone have any other suggestions?
Workaround
You can implement this yourself by detecting the low-level actions that trigger those events (eg. mouse button down, space bar down).
In WX you can use the following function and constructor:
mouse :: Reactive w => Event w (EventMouse -> IO ())
data EventMouse = ... | MouseLeftDown !Point !Modifiers
And, as you suggest, you could keep the state yourself in an IORef. My suspicion is that left button here means main button (right for left-handed users).
UI design principles
The second question, which you haven't asked by I'll answer, is whether this is good UI design.
The behaviour of a button (assuming interaction using a mouse) is that click events are reported when the user releases the mouse button in the button area after pressing the mouse button down in the same area. If the user moves away and releases, or presses 'Escape', there is no click.
Taking any action on a button being pressed (not clicked) would feel unnatural for users.
In practice, the only acceptable way to use this would be, imho, to take an action whose effects can only be witnessed after releasing and which is immediately undone if the click is cancelled (ie. mouse button released outside button area).
EDIT: Please, also, take into account that users with accessibility requirements may have OS settings enabled that affect how and when button clicks are reported (but not down/up mouse events).
There is no way to know if a wxButton is pressed or not because it is an abstraction of a push button which intentionally hides this implementation detail. If you need to know the button state, use a wxToggleButton instead.
I need to implement a behavior:
when element clicked - one thing happens
but when it's clicked and held for more than one second, something else happens (e.g element becomes draggable) and then the first event never fires
I think I know how to catch click&hold type of events, but how to distinguish between first and second?
Can you show me how to do that using this jsbin. I already made the "click, hold & drag" part, except that it is still firing the 'click' event after dragging the element and it shouldn't.
again: element clicked - one event, click and hold - element is draggable (even after mouse up) and when clicked again it's back to normal (undraggable) state.
I am not looking for a trivial solution, it has to be built using Rx.Observable or at least Bacon's streamEvent object
Thank you
I think you were pretty close with your solution, but probably it is not possible to elegantly achieve what you want while using the browser's built-in click event.
HERE is my attempt to tackle your problem.
The main idea is to define your own click streams like so:
var clicks = downs.flatMapLatest(function(){
return ups.takeUntil(Rx.Observable.timer(250));
});
var longDownsStart = downs.flatMapLatest(function(){
return Rx.Observable.timer(1000).takeUntil(ups);
});
In case of clicks we wait max 250 ms after a mouse down for a mouse-up; in case of the latter we generate the event only if there was no mouse-up within 1000 ms.
There might be some corner cases in which the code does not work as intended.
Here is my proposed solution (with Bacon.js).
I'm trying to understand how to pause and resume interaction in paper.js.
I have the metaball example on a page with an input element on top, and because paper.js steals focus for driving the metaball generation onMouseMove... bad things happen. Like not able to select what you typed.
I understood I could use item.locked = true;, but I don't know what to apply it to because nothing works.
What is the parent Item for paper.js and can I lock it so that everything stops responding to the mouse?
I also couldn't reattach the mousemove event from the Tool, which is why I came to look into item.locked. What's the correct way to remove and reattach mouse events?
As you can see in my previous question, I am currently struggling with single and double click events – I wanted to perform an action after a click and a completely different action after a double click. The problem is that the low-level events only tell me things like this was a mouse down or this was a mouse up and the total click count is == 2. It’s hard to discriminate between a single and a double click this way, since when the mouse comes up after a single click, I have to wait a while to make sure there’s not a second click coming.
Now I am wondering how different GUI toolkits handle this, as there’s no magical way around. You can’t have separate high-level single-click and double-click events without having the single-click event delayed or something, can you?
(It looks like the usual way to solve this is to have the single and double click actions related, like selection on the first click and app launch on the second. That way it does not matter that the single-click action is triggered along with the double-click one. Am I right?)
You always need some sort of timer to distinguish between single and double click. Think about it: you cannot predict whether a second click will happen once the first occurred, you just have to wait and see.
On iOS, you can have gesture recognizers. And if you only register a single tap recognizer it fires right away, but as soon you also register a double tap recognizer you notice that a single tap doesn't fire right away but only after a noticeable delay. Made me change to a a single tap with two fingers in one app because the delay is really annoying.
You could work around the delay if your single click action is undoable or cancelable: do the action when click count == 1, and if click count == 2, revert the action of the single click. Might result in undesired/unexpected UI behavior, though (from a user perspective).
In MFC a double-mouse click event triggers the following sequence of messages
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDBCLK
WM_LBUTTONUP
So responding to the WM_LBUTTONDBCLK message allows you to detect a double-click. But if I just want to detect a single-click how to I distinguish it?
But just looking at the WM_LBUTTONUP message isn't enough as it could be a single-click or it could be the first click of a double-click.
How can I successfully identify just a single-click?
(Please allow me to call these events Mouse Up and Mouse Down. My MFC is a little rusty. And there's this stuff called .NET who's been messing up my terminology lately ;-)
Short story: You don't simply want to know about Mouse Click. You need more.
Long story:
Although this is counter-intuitive, it appears that simply wanting a mouse-click is fairly uncommon. Most often, you'll want to perform some processing on Mouse Down and do some further processing on Mouse Up. The trick is that simply tracking Mouse Up messages is not enough: Mouse Down may not have happened in your window. Do you consider it a valid click then? Especially considering that the Mouse Down processing (such as selecting an item) did not occur.
Going further up the reasoning, you should not rely on receiving a Mouse Up after you processed Mouse Down: User may have moved the mouse and released the button somewhere else (think drag'n'drop), in which case, you don't receive the MouseUp event... unless you capture the mouse on MouseDown to make sure you get mouse event up to Mouse Up even if the mouse left your window.
All in all, you end up tracking Mouse Down, capture the mouse and when you receive Mouse Up, just check if you own the capture. If not, the mouse was either double-clicked (no 2nd mouse down) or Mouse Down happened somewhere else hence you most likely don't care about this Mouse Up.
In conclusion: There's no MouseClick message simply because you wouldn't go very far with it: You need to handle more messages and implement more mechanics anyway.
Oh! And if your dealing with an existing control which already handles all this items and selection stuff, such as a listview, chances are it provides with a similar custom notification such as Item Activate or Item Selection Changed.
I just tried this in Delphi, the behavior is the same: even when a double click is happening, a single click event is issued right after the first one of the two.
I solved it using a timer, which works like this:
deactivate timer on WM_LBUTTONDBLCLK (and set bDbl to true)
activate timer on WM_LBUTTONUP if bDbl==false
deactivate on WM_LBUTTONUP if bDbl==true (and reset bDbl)
I set the interval of the timer to the time returned by GetDoubleClickTime.
MSDN says:
The GetDoubleClickTime function
retrieves the current double-click
time for the mouse. A double-click is
a series of two clicks of the mouse
button, the second occurring within a
specified time after the first. The
double-click time is the maximum
number of milliseconds that may occur
between the first and second click of
a double-click.
If the timer happens to fire then you have the real click. In my case the double click interval is 500ms, so any "real click" will be delayed this long.
You could check WM_LBUTTONDOWN has not been called more than once before WM_LBUTTONUP. In practice Windows does this for you, in that if you get a WM_LBUTTONDBCLK you tend not to get a WM_LBUTTONUP.
You can use PreTranslateMessage() to count the messages as they appear. If you've received only the mouse messages corresponding to a single-click, and the system-configured time for double-clicking has expired, you can safely assume it's a single-click.
As far as I know there is no way to know that this is the case as it is happening, which makes sense -- until the time is expired, there's no way to know that a second click is or isn't coming.
that's a little tricky.
I would detect the WM_LBUTTONDOWN & WM_LBUTTONUP combo, store that event somewhere and set a timeout for a second or so. If there isn't a WM_LBUTTONDBCLK during that timeout then you have a single click.
This might imply you need to have another thread running but I think you could accomplish it with one thread.
I think the solution is to start a timer after the first click & then check the elapsed time after at the next immediate click, this will tell you if it is a single click or double click.
You typically look at #MLButtonUp and you would not have single click and double click behavior on the same mouse button.