Im trying to play around with some multitouch in Android.
I have two RelativeLayout on screen where I would like to get touch events.
fooLayout = (RelativeLayout)findViewById(R.id.foo);
fooLayout.setOnTouchListener(onTouchListener);
barLayout = (RelativeLayout)findViewById(R.id.bar);
barLayout.setOnTouchListener(onTouchListener);
...
View.OnTouchListener onTouchListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
...
I tried having a OnTouchListener for each layout but that didn't seem to work at all.
I figured since the onTouch method gets an View I would be able to make out with view the current touch event came from and save away the pointer id.
int pointerId = event.getPointerId(event.getActionIndex());
int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
switch (v.getId()) {
case R.id.foo:
fooPointerId = pointerId;
break;
case R.id.bar:
barPointerId = pointerId;
break;
}
This does not work as I thought it would.
When my first finger touches in one of the layouts I will get the correct id from that layout. But when I put down a second finger in the other layout it will get the id of the layout where I put down my first finger.
Am I going about this the wrong way?
Is this possible to do or do I have to put the OnTouchListener on the top view and figure out which layout Im touching by the x/y values of the event?
I think you should extend relative layout and implement onTouchEvent(MotionEvent ev) over there to figure out which pointers are touching which child views(Put foo and bar inside your main relative layout/view group that implements onTouchEvent).
IMO onTouch(View v, MotionEvent ev) only lets you register one pointer at a time so it may not be possible using this approach. This link might help out
Related
I have a RelativeLayout with a single ImageView inside of it. The ImageView has an OnTouchListener attached to it which is working perfectly fine if I just press the ImageView. The problem I'm having though is that if I press and hold in the empty space outside of the ImageView and then try to press the ImageView the touch listener doesn't fire. It seems like the layout is absorbing the touch events somehow. Any ideas on how I could fix this?
The action defined by you here is a Multi-touch gesture. Go through this doc to know how to handle this type of actions.
Also take a look at the ACTION_POINTER_DOWN action define in MotionEvent. This is the event that will get called when additional fingers come down.
you mout use this code:
imageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
//your code
break;
case MotionEvent.ACTION_UP:
//your code
break;
case MotionEvent.ACTION_MOVE:
//your code
break;
default:
//your code
break;
}
return true;
}
});
in my onTouch(View view, Motionevent event) method, the view.getY() always returns the same (0.0). I want to check what view is being touched and compare it with int Y = event.getRawY(). Would something like this be possible?
The reason is that I have a couple of animated fields in my layout, and I would like to animate each view differently depending on which one is being touched. I will appreciate any advice or ideas. Thank you in advance
check api reference first. see View.getY and Motionevent.getRawY.
I did this to solve my problem:
LinearLayout animLayout = new LinearLayout(this);
animLayout.addView(//add some view);
animLayout.setId(1)
animLayout.setOnTouchListener(this);
#Override
public boolean onTouch(View view, MotionEvent event){
case MotionEvent.ACTION_UP
switch (view.getId()}
case 1:
//My code
break;
}
break;
}
}
Basically, give my view an ID and in my onTouch get the ID in a switch case and do what I want with it.
I'm using onTouchListener to change the background color when the user's finger is down and change back to default when the user's finger is up. The problem is that when the user's finger is down the background color changes but if the user doesn't takes the finger up and starts scrolling the background color doesn't change to default. Please help.
Below is my code:
V.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
V.setBackgroundColor(Color.BLUE);
break;
case MotionEvent.ACTION_UP:
V.setBackgroundColor(Color.BLACK);
break;
}
return true;
}
});
I've also tried to return false but the result is the same
There are a few different approaches you can use. You can look at MotionEvent.ACTION_MOVE and act when you receive that in your onTouch. You can look at MotionEvent.ACTION_OUTSIDE
and see if they have left the region your are checking.
You can also put a listener on your scroll View and change the background when it moves. Synchronise ScrollView scroll positions - android
Alternately, you could use a gestureListener and detect that.
I have several buttons and I would like to press on one of them and drag through another presing them. Could you tell me which MotionEvent or another functionality should I use. I'm using onTouchListener.
There is an image where you can see what I want to do (first ACTION_DOWN on 1st button and drag through 2nd-7th buttons still pressing the screen) and finally press every white buttons:
Below is my onTouch button code:
button1 = (Button) findViewById(R.id.button1);
button1.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
soundIDs[0] = sound.play(R.raw.sample1);
button1.setBackgroundResource(R.drawable.white_clicked);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
sound.stop(soundIDs[0]);
button1.setBackgroundResource(R.drawable.white);
break;
}
return false;
}
});
You are setting the OnTouchListener on just the one button. That's not going to help you know when the pointer moves (e.g. user drags his finger) into another button.
You could set an OnTouchListener on the view that contains the buttons. Then check for ACTION_DOWN, ACTION_MOVE, and ACTION_UP events. You would then have to do some simple hit detection to figure out which button to activate.
Something along the lines of:
getWindow().getDecorView()
.findViewById(android.R.id.content)
.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent event) {
int action = event.getAction();
if (action != MotionEvent.ACTION_DOWN
&& action != MotionEvent.ACTION_MOVE
&& action != MotionEvent.ACTION_UP) return false;
Rect hitRect = new Rect();
Button button;
for(int i = 0; i < myButtons.size(); i++) {
button = myButtons.get(i);
button.getHitRect(hitRect);
if (hitRect.contains((int)event.getX(), (int)event.getY())) {
button.setText("hit!");
}
}
return true;
}
});
Where myButtons is an ArrayList of your buttons (piano keys in your example).
Also, you'd probably want to modify this to properly deactivate the currently active button if the user's touch leaves the button, but doesn't hit another button.
I tested the above code on an android device with a layout that has 3 buttons in a row. Dragging your finger across all the buttons causes each button's text to change to "hit!"
Like I said above, you were setting the touch listener on the just one button, that will not work. In this example I have set the touch listener on the entire view for the activity.
I got a custom ListView which I fill with an Adaptar. During my application the items within the list will change according to their status so I'm updating my ImageViews like so:
mStatusIcon = (ImageView) findViewById(R.id.imgStatusIcon);
mStatusIcon.setImageResource(R.drawable.icon_cancel);
So far so good. The problem is that I want some kind of focus/hover state on a certain part of my layout. I've set up an OnTouchListener() on my View mHitfield in my layout xml.
I can catch all the relevant actions: ACTION_MOVE, ACTION_DOWN, ACTION_UP and ACTION_CANCEL.
The problem is that when I change my ImageView mStatusIcon the next action I catch is always ACTION_CANCEL.
View mHitfield = (View) findViewById(R.id.outerShape);
mHitfield.setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
int currentAction = event.getAction();
switch(currentAction)
{
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
// if I comment out these lines I keep receiving all actions
// if I don't, I only receive ACTION_DOWN followed by ACTION_CANCEL
mStatusIcon.setImageResource(R.drawable.icon_download_normal);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
// if I comment out these lines I keep receiving all actions
// if I don't, I only receive ACTION_DOWN followed by ACTION_CANCEL
mStatusIcon.setImageResource(R.drawable.icon_download_hover);
break;
}
return false;
}
});
Can somebody explain to me why this is happening and if there is a way to work arround this?
I'm still not really sure why it happened but it was seems the TouchEvent was canceled because the layout was updated within the custom View created. Once I didn't use a custom View but created a XML Layout instead the problem ceased to exist.