I am programming an android application and my "testing" device is a Motorola Milestone (Droid). I have done a grid that scroll like the iPhone home menu ( with "points").
I got two problems:
The first one : the drag only works on the Android Device Emulator and don't on the Droid! (Maybe the multi-touch screen is a problem?)
The drag is too responsible, and flip views sometimes one by one (this is ok) and sometimes 2 by 2 or 3 by 3! That is clearly problematic!
Here is the code of my OnTouch method:
public boolean onTouch(View v, MotionEvent event) {
if (v instanceof GridView){
int eventaction = event.getAction();
switch (eventaction) {
case MotionEvent.ACTION_MOVE:
if (event.getEdgeFlags()==MotionEvent.EDGE_LEFT){
vf2.setInAnimation(this, R.anim.slide_left);
vf2.setOutAnimation(this, R.anim.slide_right);
vf2.showNext();
if (numCurrentPage==2){
numCurrentPage= 0;
} else {
numCurrentPage++;
}
notifyPageNumber(numCurrentPage);
}
if (event.getEdgeFlags()==MotionEvent.EDGE_RIGHT){
vf2.setInAnimation(this, R.anim.slide_in);
vf2.setOutAnimation(this, R.anim.slide_out);
vf2.showPrevious();
if (numCurrentPage==0){
numCurrentPage= 2;
} else {
numCurrentPage--;
}
notifyPageNumber(numCurrentPage);
}
break;
default:
break;
}
}
return false;
}
Thanks for your help!
Update : It doesn't work anymore on the Google Nexus One!
If you consider the onTouch event being handled you should return true to indicate that it should not propagate any further. If you return false other listeners will receive it and might do something about it, which could be causing this. How about trying:
if (v instanceof GridView){
...
return true;
}
return false;
Ok, I manage to have a good drag with this:
public boolean onTouch(View v, MotionEvent event) {
if (v instanceof GridView){
int eventaction = event.getAction();
switch (eventaction) {
case MotionEvent.ACTION_DOWN:
xStart = event.getX();
break;
case MotionEvent.ACTION_UP:
xEnd = event.getX();
System.out.println("Start = "+xStart+", End = "+xEnd);
if (xEnd - xStart > 100){
vf2.setInAnimation(this, R.anim.slide_in);
vf2.setOutAnimation(this, R.anim.slide_out);
vf2.showPrevious();
if (numPageActuelle==0){
numCurrentPage= 2;
} else {
numCurrentPage--;
}
notifyPageNumber(numCurrentPage);
}
if (xEnd - xStart < -100){
vf2.setInAnimation(this, R.anim.slide_left);
vf2.setOutAnimation(this, R.anim.slide_right);
vf2.showNext();
if (numPageActuelle==2){
numCurrentPage= 0;
} else {
numCurrentPage++;
}
notifyPageNumber(numCurrentPage);
}
return true;
default:
break;
}
return true;
}
return false;
}
Now, I get an other big problem : I can't click on my grid!
The code of my grid is :
private ViewFlipper vf;
......
vf.setOnTouchListener(this);
GridView pageGrid = new GridView(this);
pageGrid.setNumColumns(3);
pageGrid.setAdapter(new ModuleAdapter(this,listPages.get(j)));
pageGrid.setOnTouchListener(this);
vf.addView(pageGrid);
I don't now how to get again the clicks on my grid...
If someone have an idea...
Related
I am developing a game and I need to be able to detect that one finger is performing a MOVE while posibly another finger can TOUCH another part of the screen.
With the following code I am able to detect both the ACTION_MOVE (on certain region of the screen) and the ACTION_DOWN
public boolean onTouch(View v, MotionEvent event) {
final int dest_x = (int) event.getX();
final int dest_y = (int) event.getY();
onTrackPad = dbSettings.TRACK_PAD.contains(dest_x, dest_y);
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
if (onTrackPad)
{
//move character
}
break;
case MotionEvent.ACTION_DOWN:
// Fire bullets
break;
}
//The event was consumed
return true;
}
The problem is that I am not able to move and fire at the same time (I need to stop moving in order to fire and viceversa)
I am aware that Android can handle multi-touch events but have not figure it how to use that to be able to process these events and the same time so that the player can move and fire at the same time
I have also try using the getActionMasked without any luck
After reading this question Android MotionEvent.getActionIndex() and MultiTouch
This is how I solved the problem
public boolean onTouch(View v, MotionEvent event) {
int dest_x ;
int dest_y ;
p = event.getActionIndex() ;
dest_x = (int) event.getX(p);
dest_y = (int) event.getY(p);
onTrackPad = dbSettings.TRACK_PAD.contains(dest_x, dest_y);
action = event.getActionMasked() ;
switch (action) {
case MotionEvent.ACTION_MOVE:
if (onTrackPad)
{
//move character
}
break;
case MotionEvent.ACTION_DOWN:
// Fire bullets
break;
}
//The event was consumed
return true;
}
MotionEvent has all information about touches that you need. You can get number of touches by executing event.getPointersCount(), and try to check MotionEvent.ACTION_POINTER_2_DOWN instead of MotionEvent.ACTION_DOWN. To get coordinates of each touch you can use event.getX(0) and event.getX(1), same is for y. If you have a case of MotionEvent.ACTION_MOVE with 2 touches, you will receive all this information in your motion event.
Try below code.
when multiple pointers touches on the screen,system generates the action events.we can keep track of individual pointers with in motion event using pointer id. Pointer id persists across touch events and also allows to track individual pointer across entire gesture.
#Override
public boolean onTouch(View v, MotionEvent event) {
int index = event.getActionIndex();
int pointerID = event.getPointerId(index);
int action = event.getActionMasked();
if(event.getPointerCount() > 1)
{
Log.i("TouchType ", "Multi Touch");
for(int i = 0; i < event.getPointerCount(); i++)
{
performAction(action);
}
}else
{
Log.i("TouchType ", "Single Touch");
performAction(action);
}
return true;
}
public void performAction(int action){
switch(action)
{
case MotionEvent.ACTION_DOWN :
Log.i("OnTouch ", "Pressed");
// Fire bullets
break;
case MotionEvent.ACTION_MOVE :
Log.i("OnTiouch", "move");
//move character
break;
case MotionEvent.ACTION_UP :
Log.i("OnTiouch", "Up");
break;
default:
Log.i("OnTiouch", "None");
}
}
I'm trying just trying to make this function work but I am having troubles. When I have touch on View, getPointerCount() method always returns 0 pointers, when I touch the screen with one finger, 1. When I touch the screen with two or more fingers, it's always return 1. Have you any ideas ?
i have trying to this code,
#Override
public boolean onTouch(View view, MotionEvent me) {
// No dragging during animation at the moment.
// TODO: Stop animation on touch event and return to drag mode.
if (me.getPointerCount() >= 2) {
mAnimate = false;
mEnableTouchPressure = false;
mRenderLeftPage = false;
startCurl(CURL_NONE);
mCurlState = CURL_NONE;
mPageRight.setFlipTexture(false);
mPageLeft.setFlipTexture(false);
return false;
} else {
if (me.getAction() == MotionEvent.ACTION_DOWN) {
Log.e("TAG_EVENT", me.getPointerCount() + "");
} else {
Log.e("TAG_EVENT - 2", me.getPointerCount() + "");
}
}
}
I think is because you should return true for the touch event to be processed.
You can read the about MotionEvent.ACTION_MASK. For catching the action of multiTouch you can use the following code :
int action = (motionEvent.getAction() & MotionEvent.ACTION_MASK) % 5
switch(action) {
case MotionEvent.ACTION_DOWN:
System.out.println(motionEvent.getPointerCount());
break;
}
in my App I have a Custom View in an Activity.
To detect touch events I have the method onTouchEvent() in both of them.
Custom View: The onTouchEvent()-method basically just marks the object which is touched.
#Override
public boolean onTouchEvent(MotionEvent event) {
int maskedAction = event.getActionMasked();
switch (maskedAction) {
case MotionEvent.ACTION_DOWN:
touchedXY[0] = event.getX();
touchedXY[1] = event.getY();
mMatrix.mapPoints(touchedXY); // this is just for
event.setLocation(touchedXY[0], touchedXY[1]); // rotation purposes
for(int i = 0; i < mPoints[i]; i++){
mPoints[i].isSelected(setIsSelected(touchedXY)); //using method to
//check if point
//is selected
}
break;
default:
return false;
}
invalidate();
return true;
}
Activity: If an Object is touched a LinearLayout should appear at the Bottom of the Activity with the number of touched Points.
int key = 0;
#Override
public boolean onTouch(View v, MotionEvent event) {
// get masked (not specific to a pointer) action
int maskedAction = event.getActionMasked();
switch (maskedAction) {
case MotionEvent.ACTION_DOWN:
List<AddressPoint> selectedPoints = Arrays.asList(mPoints);
if (key == 0) {
if (selectedPoints.size() > 0) {
key = 1;
test.setText(String.valueOf(selectedPoints.size()));
popup.setVisibility(View.VISIBLE);
} else {
test.setText(String.valueOf(selectedPoints.size()));
}
} else {
if (selectedPoints.size() > 0) {
test.setText(String.valueOf(selectedPoints.size()));
} else {
key = 0;
popup.setVisibility(View.GONE);
}
}
break;
default:
return false;
}
return false;
}
So, it is working but behaves not as desired. The Activity seems only to react to the second touchevent and refreshes every second touchevent.
Like for example:
TouchEvent = 4 Points --> Activity shows no popup.
TouchEvent = 3 Points --> Activity shows popup with the number "4"
TouchEvent = 1 Point --> Activity shows popup with the number "3"
.
. and so on
.
I hope you can help me and I appreciate your help!
The problem seems to occour because your view is redrawn before the points are saved.
Therefore it might be better to save the number of points in the onTouch onTouchEvent and then invoke another function to set the text accordingly.
I'm developing an application where I'm applying on touch listener to my layout view. I move the layout over screen but that layout doesn't respond well after 10 to 15 secs. Here is my code:
base = (LinearLayout) findViewById(R.id.load);
base.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, final MotionEvent event) {
int motion = event.getAction();
int numberOfPointers = event.getPointerCount();
if (numberOfPointers < 3) {
switch (motion & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
drag = true;
break;
case MotionEvent.ACTION_POINTER_DOWN: {
drag = false;
if (drawWaveForm != null) {
zoom = true;
}
// initial x1 and x2
BitmapDetector.prevX1 = Math.min(event.getX(0), event.getX(1));
BitmapDetector.prevX2 = Math.max(event.getX(0), event.getX(1));
BitmapDetector.prevY1 = event.getY(0);
BitmapDetector.prevY2 = event.getY(1);
}
break;
case MotionEvent.ACTION_MOVE:
if (drag && event.getActionIndex() == 0) {
// Log.d("detecting","inside the action move");
if (touching == false) {
touching = detector.isWaveformAnchor(event.getX(0), event.getY(0));
} else if (touching == true) {
float diff = event.getY(0) - loadWaveFormManager.getCh1_pos();
if ((loadWaveFormManager.getCh1_pos() + diff) < (StaticValues.screenHeight - 50)) {
int tempCh1_pos = (int) (loadWaveFormManager.getCh1_pos() + diff);
loadWaveFormManager.setCh1_pos(tempCh1_pos);
}
drawWaveForm.update(loadWaveFormManager);
}
}
break;
case MotionEvent.ACTION_UP:
// Log.d("detecting","inside the action up");
drag = false;
touching = false;
zoom = false;
break;
case MotionEvent.ACTION_POINTER_UP:
// here different function
return;
}
});
Does anyone have any idea about this? Please help me on this one.
It is not clear from your code what is your problem and when does it happen. I don't see any TimerTask or AsyncTask reference.
I guess, you're trying to do some expensive operation in UI thread, and this freezes your application. Possible long-running candidate is drawWaveForm.update(loadWaveFormManager)
If this is so, you should preform your computations asynchronously, and only then update UI.
By the way, your code will not compile at all:
public boolean onTouch(View v, final MotionEvent event)
should return true or false, instead you perform return; at the end of this method. That leads to an assumption, that you're providing irrelevant code in your question, but still want to receive a relevant answer.
Provide relevant code piece for further analyze.
Currently you are starting thread on touch event use handler instead
of thread
My application have three pages (three tabs) and I want to switch beetween two gridviews by moving finger horizontaly. The touch code works fine but I can't click anymore on the grid items! I use the method onItemClickListener (onClickListener don't works on Gridview) but the grid item is not clicked.
Thanks for your help!
The code is :
myGrid.setOnTouchListener(this);
myGrid.setOnItemClickListener(this);
....
public boolean onTouch(View v, MotionEvent event) {
int eventaction = event.getAction();
switch (eventaction) {
case MotionEvent.ACTION_DOWN:
xStart = event.getX();
break;
case MotionEvent.ACTION_UP:
xEnd = event.getX();
if (xEnd - xStart > 20){
//switch to previous tab
}
if (xEnd - xStart < -20){
//switch to next tab
}
return true;
default:
break;
}
return true;
}
What view is that onTouch code in? You could try changing that last return true to return false so that if the action wasn't a motionevent, the event is not consumed by the view.