Android multitouch and getActionMasked() - android

I have a some small questions to do with the masking of touch events. I have read many things on here and elsewhere but am still a little confused with parts.
1) Is event.getActionMasked() same as event.getAction() & MotionEvent.ACTION_MASK (they appear to be on Samsung S2 and HTC Desire)
2) Will the two above commands give all the information and more than that event.getAction() alone will, or is it different.
3) I have written a peice of code which simple says where is being touch and with which pointerId, or if the pointer is not in use (only written for two touches at the moment). It seems to work correctly on the devices mention above, however I know how some devices can act very differently if not done absolutely correct. I am therefore wondering if the following is correct and will behave on all devices.
boolean pointer0down=false, pointer1down=false;
String st="", str0 ="", str1 ="";
public boolean onTouchEvent( MotionEvent event )
{
if (event.getActionMasked()==MotionEvent.ACTION_UP
||event.getActionMasked()==MotionEvent.ACTION_POINTER_UP
||event.getActionMasked()==MotionEvent.ACTION_CANCEL)
{
if (event.getPointerId((event.getActionIndex()& MotionEvent.ACTION_MASK))==0)
pointer0down=false;
if (event.getPointerId((event.getActionIndex()& MotionEvent.ACTION_MASK))==1)
pointer1down=false;
}
if (event.getActionMasked()==MotionEvent.ACTION_DOWN
||event.getActionMasked()==MotionEvent.ACTION_POINTER_DOWN)
{
if (event.getPointerId((event.getActionIndex()& MotionEvent.ACTION_MASK))==0)
pointer0down=true;
if (event.getPointerId((event.getActionIndex()& MotionEvent.ACTION_MASK))==1)
pointer1down=true;
}
if (pointer0down)
str0="\tx: " + event.getX(0) + "\ty: "+event.getY(0);
else
str0="\tNot down";
if (pointer1down )
str1="\tx: " + event.getX(1) + "\ty: "+event.getY(1);
else
str1="\tNot down";
st="pointer0:"+str0+"\npointer1:"+str1;
return true;
}

Some background -
The integer returned from getAction is a packed integer that encodes both the action code (e.g ACTION_DOWN) and pointer index (e.g which finger).
For single touch, since there is only one finger involved there is no need to store the pointer index so the value is just the action code. Hence its safe to do something like getAction() == ACTION_DOWN
For multi touch, this comparison is incorrect b/c you have the extra pointer index in the packaged integer. You can extract the action code by doing getAction() & ACTION_MASK and extract the pointer index by doing getAction() & ACTION_POINTER_INDEX_MASK
Now to your question -
1: Yes. think of getActionMasked as a helper method that extract the action code bits. To extract the pointer index you have the equivalent getActionIndex helper method. Both these methods will work for single or multi touch hence they are the "safest".
2: As explained above, getAction also encodes pointer index for multitouch
3: there is a bug in your code. event.getPointerId((event.getActionIndex() & MotionEvent.ACTION_MASK)) is technically incorrect. Instead you should be doing event.getPointerId(event.getActionIndex()). You are getting very lucky with the incorrect logical and operator on getActionIndex which turns out to be 2 bytes and the mask is itself 2 bytes (0xff) :)

Related

How does RemoteViewsFactory handle ViewTypes in Android?

As there is no getItemViewType() method in RemoteViewFactory - how does it actually determine the ViewType?
I just stumbled upon a case where I DEFINITELY had only 4 viewTypes, but kept getting display errors ("loading..." for one item) and a log entry that I would return more viewTypes than the getViewTypeCount suggests. So I randomly added +1 and now it works.
So it seems to me that the actual viewType is guessed by the underlying ListAdapter/AppWidgetHost and if you do heavy modifications to a RemoteViews instance it will detect it as a new viewType...
Does anyone know what's actually happening?
OK, here's the answer to the question (taken from the Android sources of RemoteViewsListAdapter):
for (RemoteViews rv: mRemoteViewsList) {
if (!mViewTypes.contains(rv.getLayoutId())) {
mViewTypes.add(rv.getLayoutId());
}
}
if (mViewTypes.size() > mViewTypeCount || mViewTypeCount < 1) {
throw new RuntimeException("Invalid view type count -- view type count must be >= 1" +
"and must be as large as the total number of distinct view types");
}
So Android uses the LayoutId as viewTypeReference. Leaves me with some research to do in my app, but answers my question.

Why is MotionEvent.ACTION_POINTER_UP not recorded consistently?

I thought pinch would always trigger MotionEvent.ACTION_POINTER_UP, but it happens only about 50% of the time (it varies a lot) for an app on at least two tested tablet devices. It appears to be random. I do not know how to pinch to make it happen consistently.
The code is very straightforward as the following overridden method of the activity in question:
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction())
{
...
case MotionEvent.ACTION_POINTER_UP:
Log.d("Debug", "ACTION_POINTER_UP triggered");
default:
break;
}
...
}
Could anyone shed some light on this?
You may change your code to use getActionMasked().
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getActionMasked())
{
//...
case MotionEvent.ACTION_POINTER_UP:
Log.d("Debug", "ACTION_POINTER_UP triggered");
default:
break;
}
//...
}
MotionEven getAction() reports an integer which consists of both ACTION_whatever and
the pointer index left-shifted by ACTION_POINTER_INDEX_SHIFT (8) bits.
Return the kind of action being performed. Consider using getActionMasked() and getActionIndex() to retrieve the separate masked action and pointer index.
Returns
The action, such as ACTION_DOWN or the combination of ACTION_POINTER_DOWN with a shifted pointer index.
getAction() can be quite confusing to work with in multi-touch situations. If you want to get the kind of action (ACTION_DOWN, ACTION_POINTER_DOWN, and so on), which your case most likely is, you may use getActionMasked() instead of getAction().
getActionMasked() always returns ACTION_whatever, without the pointer index bits.
getAction() returns (getActionIndex() << 8 | ACTION_whatever).
(pointer indexes are very counter-intuitive, with Android trying to re-use the lowest indices available giving strange behavior if you use them directly, but that's another story, here better use getActionMasked() and not worry about indices). This is numerically equal to getActionMasked() only when the pointer has index=0, therefore you will see the "random" behavior: As you complete each pinch "naturally",
sometimes you may have released pointer 0 first, then pointer 1 last,
you get 2 events that getAction() returns ACTION_POINTER_UP followed by 1<<8 | ACTION_UP respectively, and hits the case ACTION_POINTER_UP label on the first event.
The other time you may have released pointer 1 first, then pointer 0 last,
you get 2 events that getAction() return 1<<8 | ACTION_POINTER_UP followed by ACTION_UP.
There is no case label for these, all get down to the default.
If you use getActionMasked(), you get ACTION_POINTER_UP followed by ACTION_UP, in both cases consistently.

How to refresh the screen in OpenGL after something is printed?

I have a couple of if-statements and if one of them is true it will print a character on the screen.
char d = 'a';
char c = 'b';
if(A == TRUE) //see comments below
{
Print(200,200,d);
}
if(B == TRUE)
{
Print(200,200,c);
}
void Print(int x, int y, char u)
{
glRasterPos2f(x,y);
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, u);
}
The problem is that if A is true, it will print 'a' on the screen correctly, but if afterwards B is true and A not anymore it will print 'b' on the screen while the character 'a' is still there. How can I solve this so that only one character is on the screen. Any help would be appreciated.
Big thanks to datenwolf. The most important thing is to put the glutPostRedisplay in the right place. I placed it at the end of my void Print(..) function. I just looked where I should place it and for me this works now (it was just a small adjustment).
OpenGL's design is built on the premise, that the while window is redrawn if anything needs a change. Normally all drawing operations should be done from only a central display function. Changes that need to be reflected in what's visible on the screen should be dealt with by preparing the list of things to be drawn and then issue a full redraw event.
Update
Actually you have a completely different problem
In the statement if(A = TRUE) two things are happening:
A gets assigned the value TRUE
the result of that assignment (which is TRUE) is tested for truth, which it is and hence will always pass.
The same goes for if(B = TRUE).
The right operator to use is == (two equal signs in a row). With most compilers you can enable a warning and turn that into an error, that assignments are not allowed in a branching statement. A stylistic approach is to write tests for equality as
if( TRUE == A )
which avoids accidents like yours. However in your case you can simply write
if( A )
without any comparison operators at all. And I strongly suggest you do that.

Bitwise operators android

I'm new to bitwise operator, I don't know what are they use for, but I know the following:
5 & 3 = 1
because
0101 & 0011 = 0001
So yeah, I understand that we multiply each bit pair like 1 x 0 = 0, 1 x 1 = 1 and 0 x 0 = 0
Now when it comes to coding, I found the following code for onTouchEvent:
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK;
switch(action) {
case MotionEvent.ACTION_DOWN : {
break;
}
case MotionEvent.ACTION_MOVE : {
break;
}
case MotionEvent.ACTION_POINTER_DOWN : {
break;
}
case MotionEvent.ACTION_POINTER_UP : {
break;
}
case MotionEvent.ACTION_UP : {
break;
}
}
return true;
}
Ok firstable, the part int action = event.getAction() & MotionEvent.ACTION_MASK; what is the value of action after the operation, and what does it means? why not just simply use action = event.getAction() what's the meaning.
second, I've never seen the use of {} to define a code block for a case: is this specific because we're using the bitwise and operator or this is something totally normal and I happen to just notice that you can use them?
The reason the event is masked is to remove unrelated bits from the event. Performing bitwise-and with ACTION_MASK isolates only those particular bits. This is how you combine and test status flags that are packed into an integer. If you did not mask it, then if any other bit is set on the event, you would not be able to easily test your actions for equality.
What this is actually doing is reserving a small number of bits for an action, like having a 3-bit integer (or whatever it actually is). The mask just sets the relevant bits, so that all other bits are thrown away (ie are unimportant).
As for the braces in case statements, that's fine. You can put braces just about anywhere - it creates a a block-scope level, where any new variables you create inside that block will only exist in the block. In case statements this is quite normal, and prevents a variable in one case from "falling through" to subsequent cases. For example:
switch(foo)
{
case 0:
int i = 42;
// do something with i
break;
case 1:
// The variable i is still in scope here, which is often not
// intentional (but can sometimes be useful)
}
To stop i from falling through:
switch(foo)
{
case 0:
{
int i = 42;
// do something with i
}
break;
case 1:
// The variable i defined above is not available here.
}
In your case, the braces are superfluous, but are probably there because the person who wrote the code has adopted this practice into their coding style. Most likely they've been burned by an unwanted side-effect before, or their compiler emits warnings about variable fall-through and they've decided to just use braces all the time. Personally, I think it's cleaner to only use them when necessary.
The event that comes back from event.getAction() is actually an integer. It contains more than just information about the type of action apparently. It probably contains flags that describe the action in more detail. And by passing all that detail in through an int, it saves the use of a class object to represent the action itself.
The mask is bitwise for the first byte in the integer. Only the first two bytes out of the eight. And for comparison purposes, you need to remove the upper parts of the integer before comparing it against the actions, which are themselves only using the bottom byte of an integer.
The upper parts of the event integer are still useful for other purposes when checking against them. So the mask is 0x000000ff representing that you only want information related to the action type at the bottom and the entire event takes up the rest of it with other useful information.

calculator on actionscript 3

This is the simplified version of my question.
There are
movieclip1
movieClip2
movieClipadd
TextA
TextB
Text C
Text answer
Touching movieclip1 should change TextA to 1 (the content should be 1)
Touching movieclip2 should change TextC to 2 (the content should be 2)
Touching movieclipadd should change TextB to + (the content should be +)
Then automatical Textanswer should give the answer. that is 3(1+2=3)
This is for mobile and I know to use ontouchbegin and ontouchend.
There's a couple of ways to accomplish what you want to do, one way would be to have a method for each operation type that you plan to have your calculator support, then you can just have a switch statement that calls the appropriate method, something like this (I got lazy and just did the operation inline, if it were more complicated would probably want methods):
switch(textB.text)
{
case '+': textAnswer.text = parseInt(textA.text)+parseInt(textC.text);
break;
case '-': textAnswer.text = parseInt(textA.text)-parseInt(textC.text);
break;
//etc.
default: throw new Error('unhandled operator');
}
assuming that you are going to use your knowledge of the touch handlers to populate the text boxes.
While I sort of agree with arunkumar due to the lack of code provided it's a simple enough problem with enough easy solutions to provide one. But note that on SO it is standard that you provide your current work and as much background information as is relevant.

Categories

Resources