I want a div element on my page which increases a number on the page while it is pressed.
This is fairly easy, but I want this to work on IPad and Android devices as well.
I am using the touchstart event using jQuery bind on the div.
Using a setInterval I update the number (I could use calling a setTimeout every time the number is increased, but that is irrelevant).
I want the interval cleared when the finger (touch) moves outside the div. Unfortunately touchend is not called until the finger is released from the screen.
Mobile safari or webkit do not seem to support touchleave.
So here my question: Any ideas on how to mimic touchleave?
Based on above answer, here's what I do.
var $this = $('elementselector');
var fnmove = function (e) {
e.preventDefault();
e = e.originalEvent;
var touch = e.touches[0] || e.changedTouches[0];
if (!_isInBounds(touch, $this.offset(), $this.outerWidth(), $this.outerHeight())) {
$this.trigger(touch_leave_event);
$this.unbind(touch_move_event, fnmove);
};
};
$this.bind(touch_move_event, fnmove);
-- inbounds function
function _isInBounds(touch, elemposition, width, height) {
var left = elemposition.left,
right = left + width,
top = elemposition.top,
bottom = top + height,
touchX = touch.pageX,
touchY = touch.pageY;
return (touchX > left && touchX < right && touchY > top && touchY < bottom);
};
EDIT (thanks to Guillaume to completing this):
var $this = $('elementselector');
var fnmove = function (e) {
e.preventDefault();
e = e.originalEvent;
var touch = e.touches[0] || e.changedTouches[0];
if (!_isInBounds(touch, $this.offset(), $this.outerWidth(), $this.outerHeight())) {
$this.trigger(touch_leave_event);
$this.unbind(touch_move_event, fnmove);
};
};
$this.bind(touch_move_event, fnmove);
function _isInBounds(touch, elemposition, width, height) {
var left = elemposition.left,
right = left + width,
top = elemposition.top,
bottom = top + height,
touchX = touch.pageX,
touchY = touch.pageY;
return (touchX > left && touchX < right && touchY > top && touchY < bottom);
};
Sorry for the short answer, I'm leaving work. I'll come back to fill in the blanks. But you should get the idea.
The best method I've found is to check the position of the touchpoint inside your touchmove handler. When a touchpoint is created (on touchstart), it is added to an array called "touches". These touchpoints can be accessed by index (order in which the touchpoints were added). Then you can access the x and y coordinates from this point to determine whether or not it's still within the bounds of the element you're observing. Let's say I have a div called "myDiv" and I want to detect when the user's finger is dragged out of it from within.
var myDiv = document.getElementById('myDiv');
myDiv.addEventListener('touchmove', function(event){
var currentElement = document.elementFromPoint(event.touches[0].clientX, event.touches[0].clientY);
if (currentElement.id !== 'myDiv'){
console.log('finger has moved outside of element');
}
}, false);
So when we move our finger, we capture over which element it currently is with the document.elementFromPoint() function, passing in the x and y coordinates gathered from the touch stored in the touches array, at index 0 (addition touches would be added to the array at index 1, 2, 3, etc.). Lastly, we check if this captured element where our finger currently is is the same as "myDiv". If it isn't, we know the finger has been moved off of this element.
Related
I'm trying to make my code where my avatar (thing you move with your finger) move by a tween because when you put your finger on it works but when you take it off and put it back on the avatar will instantly teleport to my finger and I want him to move to it. Please inform me what I've done wrong and what I can improve to make this work.(this is in a class which is why I use public )
public var lastPosX:Number; public var lastPosY:Number;
public function onTouchBegin (e:TouchEvent):void {
var newPosX:Number = avatar.x; //the point of x your finger is
var newPosY:Number = avatar.y; //the point of y your finger is
//checks for first time putting finger down
if ( isNaN(lastPosX)) {
avatar.x = e.stageX;
avatar.y = e.stageY;
//x and y values = to your finger
}
else {
var myTweenX:Tween = new Tween(avatar, "x", Strong.easeOut, lastPosX, newPosX, 5, true);
var myTweenY:Tween = new Tween(avatar, "y", Strong.easeOut, lastPosY, newPosY, 5, true);
//makes the avatar move to your finger when u lift your finger off and on
}
}
public function onTouchMove (e:TouchEvent):void {
avatar.x = e.stageX;
avatar.y = e.stageY;
//x and y values = to your finger
}
public function onTouchFinish (e:TouchEvent):void {
avatar.x = e.stageX;
avatar.y = e.stageY;
lastPosX = avatar.x;
lastPosY = avatar.y;
//x and y values = to your finger
//Defines x and y value of finger
}
If you develope game, Tween isn't good choice for updating position for avatar. Create main gaming loop, and update position for the avatar in onTouchBeginand correct position in onTouchMove. This tutorial should help you. In another way, you are forced to spawn new Tweens in onTouchMove.
switch for action up and down we have no default bocoz write now dont want to do only these 2 things
first 2 line gives touch coordinate
playable area is set such that only in that area touch works
roughly lower fourth area is occupid by character so takinh /4
I am trying to move and object by touching it and dragging. I am testing it on my Samsung Galaxy SIII. I have used the following code. For some reason it moves faster than my finger. It should always be beneath my finger. What is wrong? (note: I haven't done the "move object only if you touch onto it" part, so right now it moves where ever I touch).
#pragma strict
var speed : float = 1;
function Start () {
}
function Update () {
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved) {
// Get movement of the finger since last frame
var touchDeltaPosition:Vector2 = Input.GetTouch(0).deltaPosition;
// Move object across XY plane
transform.position = Vector2.Lerp(transform.position,
touchDeltaPosition,
Time.deltaTime*speed);
}
}
this is what i use, it may be a better option for you, it is based on the camera, the reason that your Vector2.Lerp is not working correctly i think is because of your time variable in it you could refer to this Lerp and tweak your 't' variable until it is good for you, or you can try this, this is what i use, also i subtract from x and add to y so my finger isnt over the graphic, best of luck :)
#pragma strict
var speed : float = 1;
var distance : float = 5;
function Start () {
}
function Update () {
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved) {
// Get movement of the finger since last frame
var touchDeltaPosition:Vector2 = Input.GetTouch(0).deltaPosition;
var touchmove : Vector3 = Vector3(touchDeltaPosition.x, touchDeltaPosition.y, distance);
// Move object across XY plane
transform.position = Camera.main.ScreenToWorldPoint(touchmove);
}
}
I am generating a 6x6 grid of buttons using widget.newButton. I would like the user to be able to add numbers to a selection by touching the screen and then dragging their finger over the desired buttons. For example if I wanted to select "811030" (i.e the top row of the grid) then I would just drag my finger over it.
Here is the code I have so far:
local widget = require( "widget" )
local function handleButtonEvent( event )
local phase = event.phase
if "moved" == phase then
print("Button Pressed")
end
end
function tileRow(numTiles, padding)
local tileWidth = (display.contentWidth / numTiles) - padding
local x = padding/2
local y = display.contentHeight - numTiles * (tileWidth + padding)
for i = 1, numTiles, 1 do
for j = 1, numTiles, 1 do
local myButton = widget.newButton
{
left = x,
top = y,
width = tileWidth,
height = tileWidth,
id = "button_"..i..j,
label = math.random(0,9),
onEvent = handleButtonEvent,
}
x = x + tileWidth + padding
end
x = padding/2
y = y + tileWidth + padding
end
end
tileRow(6,1)
Just access the label inside the event handler, and build your full number from there.
I'll let you handle the corner cases, like putting fullNumber back to "" at one point :)
local fullNumber = ""
local function handleButtonEvent( event )
local phase = event.phase
local btn = event.target
local btnLabel = btn.label
if "moved" == phase then
print("Button Pressed with label:"..btnLabel)
fullNumber=fullNumber..btnLabel
print("Full number: "..fullNumber)
end
end
Cheers !
Get the button under the finger
In handleButtonEvent, you can retrieve the coordinates (x, y) where the user is touching and moving his finger. Indeed the event.target is not enough to your purpose because the event.target will always be equal to the first touched button.
You have to implement this function GetMyButton(x, y) that will return a widget.newButton. It should not be hard.
Get the label of the found button
According to widget_button.lua, to get the label of a button you should do :
local btnLabel = btn:getLabel()
Concatenate the found labels (be aware of duplication)
I've created a customized keyboard of my own.
When I click & drag over the keyboard the key should be highlighted according to my finger move. When I lift up my finger the corresponding letter has to be printed on the EditText.
How could I do this?
Assuming you are just drawing your 'customized' keyboard onto a Canvas. Obviously using the built-in keyboard is better. However if you really want to do this yourself, here is a solution.
Draw each character of your keyboard, store it's x,y location in an array corresponding to each key as you draw it.
//initialise
int[] letterX = new int[29];
int[] letterY = new int[29];
char[] keyboardChar = {'Q','W','E','R','T','Y','U','I','O','P','A','S','D','F','G','H','J','K','L','Z','X','C','V','B','N','M',' ', '<','#'};
somewhere in your 'draw' method:
// first keyboard row (do this for each row moving adding to y for next row
x=10; y=50; keySpacing = 30; // starting x, y position
for ( int charIndex = 0; charIndex < 10; charIndex++) {
letterX[charIndex] = x;
letterY[charIndex] = y;
textWidth = mPaint.measureText(keyboardChar, charIndex, 1);
if ( !letterHit ) {
canvas.drawText(keyboardChar, charIndex, 1, x - (textWidth/2), y, mPaint);
} else {
// this key is being pressed so draw highlighted somehow
canvas.drawText(keyboardChar, charIndex, 1, x - (textWidth/2), y,mPaint);
}
x += keySpacing;
}
In the onTouchEvent, compare the x, y touch position to your array of letterX, letterY this will tell you if a key is being pressed. The array index tells you which character it is. You'd need some code in the draw method to print out the key highlighted if its being pressed (example below assumes 16px tolerance).
for (int j=0; j < 29; j++ ) {
if (( Math.abs(touchX - letterX[j]) < 16 ) && ( Math.abs(touchY - letterY[j]) < 16 ) && !keyboardLock ) {
letterHit = j;
}
}
You'll still need more logic (for deleting etc) and you'll need to maintain a string. That's why really this is best to use the system keyboard if possible.
I think you need something like this post .
I want to know how I can detect child views if I move a view from one ViewGroup to another ViewGroup, particularly when doing a touch event. Is there a method I can call that will let me know which views i'm "hovering" over?
What I'm doing right now is when I detect an ACTION_MOVE event on my view i'm raising it to the top level parent so that it can move and be drawn within the entire window ( and not just inside it's original parent bounds ), then I want to move the view across to a different ViewGroup and on ACTION_UP attach the view to that ViewGroup.
Inspired by Ami's response, but discovering that MotionEvent#getX()/getY() along with View#getTop()/etc return coordinates wrt the parent View, I ended up doing the following below to operate in screen coordinates, allowing me to work across ViewGroups:
private boolean inRegion(float x, float y, View v) {
v.getLocationOnScreen(mCoordBuffer);
return mCoordBuffer[0] + v.getWidth() > x && // right edge
mCoordBuffer[1] + v.getHeight() > y && // bottom edge
mCoordBuffer[0] < x && // left edge
mCoordBuffer[1] < y; // top edge
}
whose usage inside an OnTouchListener is e.g.:
boolean inside = inRegion(event.getRawX(), event.getRawY(), targetView);
I think I found a simpler way to do this.
Create an ArrayList of possible targets
Call this method from your touch event, supplying your targets list and the coords
private View findView(float x, float y, ArrayList<View> targets)
{
final int count = targets.size();
for (int i = 0; i < count; i++) {
final View target = targets.get(i);
if (target.getRight() > x && target.getTop() < y
&& target.getBottom() > y && target.getLeft() < x) {
return target;
}
}
return null;
}
I found Sebastian Roth's answer very helpful with resources, but since it wasn't really an answer to my question, I thought I'd share what I came up with.
Here is the code I use to detect views ( only views that will accept a drop that is ) given a coordinate on the screen.
private DropView findDropTarget( int x, int y, int[] dropCoordinates ){
final Rect r = mRectTemp;
final ArrayList<DropView> dropTargets = ((main) context).getBoardDropTargets();
final int count = dropTargets.size();
for (int i=count-1; i>=0; i--) {
final DropView target = dropTargets.get(i);
target.getHitRect(r);
target.getLocationOnScreen(dropCoordinates);
r.offset(dropCoordinates[0] - target.getLeft(), dropCoordinates[1] - target.getTop());
if (r.contains(x, y)) {
dropCoordinates[0] = x - dropCoordinates[0];
dropCoordinates[1] = y - dropCoordinates[1];
return target;
}
}
}
Ok, first off mRectTemp is just an allocated Rectangle so you don't have to keep creating new ones ( I.E. final Rect r = new Rect() )
The next line dropTargets is a list of views that will accept a drop in my app.
Next I loop through each view.
I then use getHitRect(r) to return the screen coordiantes of the view.
I then offset the coordiantes to account for the notification bar or any other view that could displace the coordiantes.
finally I see if x and y are inside the coordinates of the given rectangle r ( x and y are the event.rawX() and event.rawY() ).
It actually turned out to be simpler then expected and works very well.
Read this:
http://developer.android.com/reference/android/view/ViewGroup.html#onInterceptTouchEvent(android.view.MotionEvent)
http://developer.android.com/reference/android/view/View.html#onTouchEvent(android.view.MotionEvent)
I had implemented a Drag and Drop using that method.
I also highly recommend a read of the HomeScreen sourcecode, which contains this thing (kind of):
https://android.googlesource.com/platform/packages/apps/Launcher2