I am trying to make a TicTacToe game for android . But i have the following problems.
First and foremost i would like to implement threads to my app but i have not been succesfull ( have tried almost anything ) .
Secondly i would like to know how to cope with these two errors ( i dont know if they are called errors) : Grow heap (frag case) to 65.24 MB for 2567824 byte-allocation , Skipped 118 frames ! The applcation may be doing too much work on its main thread ( though i think this would be solved with thread implementation )
public class DrawClass extends View {
int index;
int x, y, RectX, RectY;
// it will hold the rectangles dimensions depending on the screen dimensions
public Rect[] rectangles = new Rect[9];
// it will be our reference array as to what does each rectangle hold
char[] isFilledWith = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };
// bitmaps
Bitmap empty, cross, circle;
// constructor
public DrawClass(Context context) {
super(context);
// setting bitmaps and calculating screen dimensions
setBitmaps();
Calculations(context);
}
public void setBitmaps() {// set the 3 bitmaps empty , circle , cross
cross = BitmapFactory.decodeResource(getResources(), R.drawable.cross1);
circle = BitmapFactory.decodeResource(getResources(),
R.drawable.circle1);
empty = BitmapFactory.decodeResource(getResources(), R.drawable.empty1);
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
// this for updates the canvas with the appropriate bitmaps cross , circle or empty
// depending on tyhe char array isFilledWith
for (int i = 0; i < 9; i++) {
if (isFilledWith[i] == ' ') {
canvas.drawBitmap(empty, null, rectangles[i], null);
} else if (isFilledWith[i] == 'X') {
canvas.drawBitmap(cross, null, rectangles[i], null);
} else if (isFilledWith[i] == 'O') {
canvas.drawBitmap(circle, null, rectangles[i], null);
}
paint.setColor(Color.WHITE);
canvas.drawLine(x, 0, x, 3 * y, paint);// 1h
canvas.drawLine(2 * x, 0, 2 * x, 3 * y, paint);// 2h
canvas.drawLine(0, y, 3 * x, y, paint);// 3h
canvas.drawLine(0, 2 * y, 3 * x, 2 * y, paint);// 4h
}
}
protected void Calculations(Context context) {
/*
* We calculate screen dimensions and fill the rectangles array with the
* appropriate dimensions
*/
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
int width = metrics.widthPixels;
int height = metrics.heightPixels;
x = (width / 3);
y = (height / 3);
int rectanglescounter = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
rectangles[rectanglescounter] = new Rect((x * j), (y * i),
((x * j) + x), ((y * i) + y));
if (rectanglescounter < 8)
rectanglescounter++;
else
break;
}
}
Log.d("Checks", "rectangles calculated");
}
// setter for the array
public void setArray(int index, char character) {
this.isFilledWith[index] = character;
}
// getter for the array
public char getArray(int index) {
return isFilledWith[index];
}
// This method searches for tictactoe winning patterns .
public char checkForWinner() {
if (isFilledWith[0] == isFilledWith[1]
&& isFilledWith[1] == isFilledWith[2]) {// 1st horizontal
if (isFilledWith[0] == 'X') {
Log.d("WINNING CHECK", "1st row win detected");
return 'X';
}
if (isFilledWith[0] == 'O') {
Log.d("WINNING CHECK", "1st row win detected");
return 'O';
}
} else if (isFilledWith[3] == isFilledWith[4]
&& isFilledWith[4] == isFilledWith[5]) {// 2nd horizontal
if (isFilledWith[3] == 'X') {
;
Log.d("WINNING CHECK", "2st row win detected");
return 'X';
}
if (isFilledWith[3] == 'O') {
Log.d("WINNING CHECK", "2st row win detected");
return 'O';
}
} else if (isFilledWith[6] == isFilledWith[7]
&& isFilledWith[7] == isFilledWith[8]) {// 3rd horizontal
if (isFilledWith[6] == 'X') {
Log.d("WINNING CHECK", "3st row win detected");
return 'X';
}
if (isFilledWith[6] == 'O') {
Log.d("WINNING CHECK", "3st row win detected");
return 'O';
}
} else if (isFilledWith[0] == isFilledWith[3]
&& isFilledWith[3] == isFilledWith[6]) {// 1st vertical
if (isFilledWith[0] == 'X') {
Log.d("WINNING CHECK", "1st column win detected");
return 'X';
}
if (isFilledWith[0] == 'O') {
Log.d("WINNING CHECK", "1st column win detected");
return 'O';
}
} else if (isFilledWith[1] == isFilledWith[4]
&& isFilledWith[4] == isFilledWith[7]) {// 2st vertical
if (isFilledWith[1] == 'X') {
Log.d("WINNING CHECK", "2st column win detected");
return 'X';
}
if (isFilledWith[1] == 'O') {
Log.d("WINNING CHECK", "2st column win detected");
return 'O';
}
} else if (isFilledWith[2] == isFilledWith[5]
&& isFilledWith[5] == isFilledWith[8]) {// 3rd vertical
if (isFilledWith[2] == 'X') {
Log.d("WINNING CHECK", "3st column win detected");
return 'X';
}
if (isFilledWith[2] == 'O') {
Log.d("WINNING CHECK", "3st column win detected");
return 'O';
}
} else if (isFilledWith[0] == isFilledWith[4]
&& isFilledWith[4] == isFilledWith[8]) {// diagonal
if (isFilledWith[0] == 'X') {
Log.d("WINNING CHECK", "1st diagonal win detected");
return 'X';
}
if (isFilledWith[0] == 'O') {
Log.d("WINNING CHECK", "1st diagonal win detected");
return 'O';
}
} else if ((isFilledWith[2] == isFilledWith[4] && isFilledWith[4] == isFilledWith[6])) {// diagonal
if (isFilledWith[2] == 'X') {
Log.d("WINNING CHECK", "2nd diagonal win detected");
return 'X';
}
if (isFilledWith[2] == 'O') {
Log.d("WINNING CHECK", "2nd diagonal win detected");
return 'O';
}
} else
return ' ';
return ' ';
}
}
public class NewGame extends Activity implements OnTouchListener {
DrawClass drawing;
int movecounter = 0;
int playercounter = 0;
static {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
drawing = new DrawClass(this);
//setting on touch events to correspond to this class ontouchlistener
drawing.setOnTouchListener(this);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
setContentView(drawing);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
int tempx = (int) event.getX();
int tempy = (int) event.getY();
// calculating where the user touched the screen so as to fill the char
// array with the appropriate char 'x'or 'o' and then invalidate the
// drawing
for (int i = 0; i < 9; i++) {
if (drawing.rectangles[i].contains(tempx, tempy)) {
if (drawing.getArray(i) == ' ') {
if (playercounter % 2 == 0)
drawing.setArray(i, 'X');
else
drawing.setArray(i, 'O');
playercounter++;
} else if (drawing.getArray(i) != ' ')
Toast.makeText(getApplicationContext(), "DONT CHEAT",
Toast.LENGTH_SHORT).show();
// CHECKINK FOR WINNER or DRAW
movecounter++;
if (movecounter >= 5) {
if (drawing.checkForWinner() == 'X') {
Toast.makeText(getApplicationContext(), "X WIN",
Toast.LENGTH_SHORT).show();
finish();
}
if (drawing.checkForWinner() == 'O') {
Toast.makeText(getApplicationContext(), "O WIN",
Toast.LENGTH_SHORT).show();
finish();
}
if (movecounter >= 9) {
Log.d("Entered Draw ", " ok ");
Toast.makeText(getApplicationContext(),
"IT'S A DRAW ", Toast.LENGTH_SHORT).show();
finish();
}
}
drawing.invalidate();
} else
continue;
}
return false;
}
}
Thank you in advance !
Skipped 118 frames ! The applcation may be doing too much work on its main thread you are doing to much work on the UI thread. Creating a thread or using asynctask to do the heavy work will solve this error. Take a look at this http://www.vogella.com/articles/AndroidBackgroundProcessing/article.html, it is well explained.
To help you with your struggles with threads and asynctasks you have to be more specific, but to find where the performance problem is you can use the profiling tools of Android.
Related
I want to create an app to test the touch screen as shown in the above image.
My code for creating the layout as shown in the image is as follows :
private void fillScreen() {
try {
for (int i = 1; i < 14; i++) {
layoutMain = new LinearLayout(getApplicationContext());
for (int j = 1; j < 14; j++) {
b = new Button(getApplicationContext());
b.setTag("btn" + i + j);
b.setBackgroundColor(getResources().getColor(R.color.orange));
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
b.setBackgroundDrawable(getResources().getDrawable(R.drawable.my_button_bg));
} else {
b.setBackground(getResources().getDrawable(R.drawable.my_button_bg));
}
b.setOnTouchListener(getOnClickDoSomething(b));
b.setLayoutParams(param);
layoutMain.addView(b);
if (i == j || j == (15 - i - 1) || j == 13 || j == 1 || i == 1 || i == 13) {
b.setVisibility(View.VISIBLE);
}
else {
b.setVisibility(View.INVISIBLE);
}
}
layoutMain.setLayoutParams(layoutParams);
layoutButtons.addView(layoutMain);
}
} catch (Exception e) {
Log.e("promptMessage,RotationActivity Exception", e.toString());
}
}
View.OnTouchListener getOnClickDoSomething(final Button btn) {
return new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (!buttons.contains(btn.getTag())) {
buttons.add(btn.getTag());
btnCounter++;
}
btn.setBackgroundColor(getResources().getColor(R.color.videocon_header_green));
if ((btnCounter) == 67) {
flag++;
if (flag == 2)
promptMessage("Touch Screen test pass?");
}
return false;
}
};
}
I can change the colors of the button on touch but i want to "change the colors of the button when i swipe my fingers on the screen to left right top bottom".
So here is my code,
public class GameView extends SurfaceView {
private SurfaceHolder holder;
private GameLoopThread gameLoopThread;
private List<Sprite> sprites = new ArrayList<Sprite>();
private long lastClick;
public int d = 0;
public int color;
TextView tv;
public int score;
public GameView(Context context) {
super(context);
gameLoopThread = new GameLoopThread(this);
holder = getHolder();
holder.addCallback(new Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
createSprites();
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int arg2, int height) {
}
});
}
private void createSprites() {
int c = 10;
{
Random rnd = new Random();
color = Color.argb(255, rnd.nextInt(256), rnd.nextInt(256),
rnd.nextInt(256));
for (int b = 1; b <= c; b++) {
int random = (int) Math.ceil(Math.random() * 24);
if (random == 1) {
sprites.add(createSprite(R.drawable.bad1));
} else if (random == 2) {
sprites.add(createSprite(R.drawable.bad2));
} else if (random == 3) {
sprites.add(createSprite(R.drawable.bad3));
} else if (random == 4) {
sprites.add(createSprite(R.drawable.bad4));
} else if (random == 5) {
sprites.add(createSprite(R.drawable.bad5));
} else if (random == 6) {
sprites.add(createSprite(R.drawable.bad6));
} else if (random == 7) {
sprites.add(createSprite(R.drawable.bad7));
} else if (random == 8) {
sprites.add(createSprite(R.drawable.bad8));
} else if (random == 9) {
sprites.add(createSprite(R.drawable.bad9));
} else if (random == 10) {
sprites.add(createSprite(R.drawable.bad10));
} else if (random == 11) {
sprites.add(createSprite(R.drawable.bad11));
} else if (random == 12) {
sprites.add(createSprite(R.drawable.bad12));
} else if (random == 13) {
sprites.add(createSprite(R.drawable.bad13));
} else if (random == 14) {
sprites.add(createSprite(R.drawable.bad14));
} else if (random == 15) {
sprites.add(createSprite(R.drawable.bad15));
} else if (random == 16) {
sprites.add(createSprite(R.drawable.bad16));
} else if (random == 17) {
sprites.add(createSprite(R.drawable.bad17));
} else if (random == 18) {
sprites.add(createSprite(R.drawable.good1));
} else if (random == 19) {
sprites.add(createSprite(R.drawable.good2));
} else if (random == 20) {
sprites.add(createSprite(R.drawable.good3));
} else if (random == 21) {
sprites.add(createSprite(R.drawable.good4));
} else if (random == 22) {
sprites.add(createSprite(R.drawable.good5));
} else if (random == 23) {
sprites.add(createSprite(R.drawable.good6));
} else if (random == 24) {
sprites.add(createSprite(R.drawable.good7));
}
}
}
}
private Sprite createSprite(int resource) {
Bitmap bmp = BitmapFactory.decodeResource(getResources(), resource);
return new Sprite(this, bmp);
}
#SuppressLint({ "WrongCall", "DrawAllocation" })
#Override
public void onDraw(Canvas canvas) {
canvas.drawColor(color);
Paint paint = new Paint();
paint.setColor(Color.CYAN);
canvas.drawText("SCORE " + score, 10, 10, paint);
for (Sprite sprite : sprites) {
sprite.onDraw(canvas);
}
}
// this is the ontouch event to destroy the sprites and make the blood splat
// effect
#Override
public boolean onTouchEvent(MotionEvent event) {
if (System.currentTimeMillis() - lastClick > 200) {
lastClick = System.currentTimeMillis();
synchronized (getHolder()) {
float x = event.getX();
float y = event.getY();
for (int i = sprites.size() - 1; i >= 0; i--) {
Sprite sprite = sprites.get(i);
if (sprite.isCollition(x, y)) {
{
if ((sprites).equals (R.drawable.bad1))
score = score + 5;
else if ((sprites).equals(R.drawable.bad2))
score = score + 5;
else if ((sprites).equals(R.drawable.bad3))
score = score + 5;
else if ((sprites).equals(R.drawable.bad4))
score = score + 5;
else if ((sprites).equals(R.drawable.bad5))
score = score + 5;
else if ((sprites).equals(R.drawable.bad6))
score = score + 5;
else if ((sprites).equals(R.drawable.bad7))
score = score + 5;
else if ((sprites).equals(R.drawable.bad8))
score = score + 5;
else if ((sprites).equals(R.drawable.bad9))
score = score + 5;
else if ((sprites).equals(R.drawable.bad10))
score = score + 5;
else if ((sprites).equals(R.drawable.bad11))
score = score + 5;
else if ((sprites).equals(R.drawable.bad12))
score = score + 5;
else if ((sprites).equals(R.drawable.bad13))
score = score + 5;
else
score = score - 5;
}
d++;
if (d >= 10) {
d = 0;
createSprites();
}
break;
}
}
}
}
return true;
}
}
What I am trying to do is get,
if ((sprites).equals(R.drawable.bad1))
score = score + 5;
To check to see if somewhere in this code,
#Override
public boolean onTouchEvent(MotionEvent event) {
if (System.currentTimeMillis() - lastClick > 200) {
lastClick = System.currentTimeMillis();
synchronized (getHolder()) {
float x = event.getX();
float y = event.getY();
for (int i = sprites.size() - 1; i >= 0; i--) {
Sprite sprite = sprites.get(i);
Holds the value of one of the pics that are being deleted, but I am not sure how to code this properly. I am not sure if I need to place the pics into an array each time the randomizer runs or what but the code is taken from the "edu4java" tutorial from youtube.
I have the program on a loop as you can tell that I can delete the pics on touch and the score was right I just am not sure how to get the,
if ((sprites).equals(R.drawable.bad1))
score = score + 5;
To check to "see" the proper pic string. Do I need to check the array that the code "auto creates"? Is there a way to check and see what the value of a string is? Such as "seeing" what is actually being "held" by "sprite" or "sprites" ?
One problem is that you do not supply the source code for Sprite, but perhaps it looks like the code here? Given the code there, there is no neat solution to your problem with the class as it is.
So, how I would approach solving this problem is to add to each sprite a resource ID:
private Sprite createSprite(int resource) {
Bitmap bmp = BitmapFactory.decodeResource(getResources(), resource);
return new Sprite(this, bmp, resource);
}
Note that I add the extra resource parameter to the constructor. Furthermore, I would add to the Sprite class a method int Sprite.getResource(), so your collision detection code becomes:
if (sprite.isCollition(x, y))
{
if (sprite.getResource() == R.drawable.bad1)
score = score + 5;
else if (sprite.getResource() == R.drawable.bad2)
score = score + 5;
else ...
}
Note: this code is in no way optimal, but hopefully this will point you in the right direction to discover for yourself a better solution. Here in Stack Overflow we don't throw fishes, we teach people to fish.
You can't compare a bitmap with a resource Id, and actually trying to do it manually your self would end up in quiet exhaustive performance for a simple validation, what i would do and to keep it simple, i would create my own class that extends from Sprite, and in stead of passing the context and bitmap, i would pass the context and resource Id, then within this class i would decode the resource and keep a reference of the resource id, i would override the equal method from Sprites and use the reference used to create the object to do the comparison, this would be my class
public class MySprite extends Sprite{
private int bmpID;
public MySprite(Context context, int bmpID){
this.bmpID = bmpID;
Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), bmpID);
super(context, bmp);
}
#Override
public boolean equals(Object o) {
if(!(o instanceof MySprite))return false;
return this.bmpID == MySprite.class.cast(o).getBmpId();
}
public int getBmpId(){
return bmpID;
}
}
This way i keep it as a simple int comparison, and most important you can use it to compare two objects of same bmpID, or something like what u wanted by doing this:
if ((sprites).getBmpId() == R.drawable.bad1))
score = score + 5;
Regards!
I have a custom view, and within the custom view I create 4 text views. I want each of these text views to respond to on touch events. However, the textviews themselves do not respond to an on touch event. I can however, make an ontouch listener for the entire custom view. However, I do not want the whole view to have an ontouch event because I want the textviews that I have created to be dragged and dropped. I tried going the route of registering the x and y coordinates of the ontouch event and assuming that if the ontouch event is within the bounds of a textview, to change the coordinates of the textview, but that was overly complicated because if one textview got dragged to the coordinates of another one, then the ontouch event would "pick up" the other textview, so then I'd be moving two text views, which is not what I want. So, to sum it up, I want to know if it's possible to set in ontouch listener for a textview inside a customview, and if possible, why it is not working:
mScale.mPositive.get(0).setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
mScale.mCurrentXPos[0] = event.getX();
mScale.mCurrentYPos[0] = event.getY();
mScale.mDrag = true;
return true;
}
});
This same code works for the custom view, but not for the specific textviews inside that customview.
Here is the custom view code:
public class Scale extends View
{
public Scale(Context context, AttributeSet attrs)
{
super(context, attrs);
mContext = this.getContext();
h = new Handler();
mCalendarDbHelper=new CalendarDbAdapter(mContext);
mCalendarDbHelper.open();
Cursor thoughts = mCalendarDbHelper.fetchThoughts();
//create a string array of negative thoughts from the db
while (thoughts.moveToNext())
{
if (thoughts.getString(thoughts.getColumnIndexOrThrow(CalendarDbAdapter.COLUMN_NAME_THOUGHT)).length() > 0 && thoughts.getString(thoughts.getColumnIndexOrThrow(CalendarDbAdapter.COLUMN_NAME_THOUGHT)).charAt(0) == '-')
{
negative_thoughts.add(thoughts.getString(thoughts.getColumnIndexOrThrow(CalendarDbAdapter.COLUMN_NAME_THOUGHT)));
}
}
thoughts.close();
array_size = negative_thoughts.size();
mBag =BitmapFactory.decodeResource(getResources(), R.drawable.bag);
mGreenBag = BitmapFactory.decodeResource(getResources(), R.drawable.green_bag);
for (int i = 0; i < 72; i ++)
{
try
{
mScale[i] = BitmapFactory.decodeStream(context.getAssets().open("scale_"+i+".gif"));
}
catch (IOException e)
{
}
}
}
private Runnable r= new Runnable()
{
#Override
public void run() {
invalidate();
}
};
protected void onDraw (Canvas canvas)
{
if (first == true)
{
width = this.getWidth();
height = this.getHeight();
mScale[i] = Bitmap.createScaledBitmap(mScale[i], (int) (width * 1.5), height, true);
mBag = Bitmap.createScaledBitmap(mBag, width/2, height/2, true);
negative = new TextView(mContext);
word = negative_thoughts.get((int) (Math.random() * array_size));
negative.setText(word);
negative.layout(0, 0, width/3, height/4);
negative.setGravity(Gravity.CENTER);
negative.setTextSize(15);
negative.setTextColor(Color.BLACK);
negative.setTypeface(Typeface.DEFAULT_BOLD);
negative.setShadowLayer(5, 2, 2, Color.WHITE);
negative.setDrawingCacheEnabled(true);
negative.setBackgroundResource(R.drawable.graycloud);
positive_paint.setColor(Color.parseColor("#FF4444"));
positive_paint.setShadowLayer(5, 2, 2, Color.YELLOW);
positive_paint.setTypeface(Typeface.DEFAULT_BOLD);
positive_paint.setTextSize(25);
mCurrentXPos[0] = (width/2);
mCurrentYPos[0] = height/4;
mCurrentXPos[1] = (width/2) + (width/8);
mCurrentYPos[1] = height/6;
mCurrentXPos[2] = width/2;
mCurrentYPos[2] = height/12;
mCurrentXPos[3] = (width/2) + (width/8);
mCurrentYPos[3] = height/18;
mMoveXPos[0] = ((width/2) - width)/FRAME_RATE;
mMoveYPos[0] = ((height/4) - (height + (height/4)))/FRAME_RATE;
mMoveXPos[1] = (((width/2) + (width/8)) - width)/ FRAME_RATE;
mMoveYPos[1] = ((height/6) - (height + (height/4)))/FRAME_RATE;
mMoveXPos[2] = ((width/2) - width)/ FRAME_RATE;
mMoveYPos[2] = ((height/12) - (height + (height/4)))/FRAME_RATE;
mMoveXPos[3] = (((width/2) + (width/8)) - width)/ FRAME_RATE;
mMoveYPos[3] = ((height/18) - (height + (height/4)))/FRAME_RATE;
mMoveByXPos[0] = -(width/2)/ FRAME_RATE;
mMoveByYPos[0] = -(height/4)/FRAME_RATE;
mMoveByXPos[1] = ((width - (width/3)) - (width/2 + (width/8)))/ FRAME_RATE;
mMoveByYPos[1] = -(height/6)/FRAME_RATE;
mMoveByXPos[2] = - (width/2)/ FRAME_RATE;
mMoveByYPos[2] = ((height) - (height/12))/FRAME_RATE;
mMoveByXPos[3] = ((width - (width/3)) - (width/2 + (width/8)))/ FRAME_RATE;
mMoveByYPos[3] = ((height) - (height/18))/FRAME_RATE;
currentX = width;
currentY = height + height/4;
first = false;
}
if (game_over == false)
{
canvas.drawBitmap(mScale[i], 0 - (width/4), 0, null);
canvas.drawBitmap(negative.getDrawingCache(),(int) (width/12), (int) (height - (height)/2.5) - (j), null);
}
else
{
canvas.drawBitmap(mBag, width/4, height/4, null);
}
if (mMoveScale == true)
{
i++;
j+=3;
ScaleIt(canvas, i);
if (i == 21 || i == 37 || i == 53 || i == 71)
{
mMoveScale = false;
}
}
if (tracker > 0)
{
if (tracker == 1)
{
if (currentX > width/2 && currentY > height/4 && sStop == false)
{
currentX += mMoveXPos[0];
currentY += mMoveYPos[0];
canvas.drawBitmap(mPositive.get(tracker -1 ).getDrawingCache(), currentX, currentY, null);
}
else
{
if (sStop == false)
{
mMoveScale = true;
sStop = true;
currentX = width;
currentY = height + height/4;
draw_em++;
}
}
}
if (tracker == 2)
{
if (currentX > width/2 + (width/8) && currentY > (height/6) && sStop == false)
{
currentX += mMoveXPos[1];
currentY += mMoveYPos[1];
canvas.drawBitmap(mPositive.get(tracker -1 ).getDrawingCache(), currentX, currentY, null);
}
else
{
if (sStop == false)
{
mMoveScale = true;
sStop = true;
currentX = width;
currentY = height + height/4;
draw_em++;
}
}
}
if (tracker == 3)
{
if (currentX > width/2 && currentY > height/12 && sStop == false)
{
currentX += mMoveXPos[2];
currentY += mMoveYPos[2];
canvas.drawBitmap(mPositive.get(tracker -1 ).getDrawingCache(), currentX, currentY, null);
}
else
{
if (sStop == false)
{
mMoveScale = true;
sStop = true;
currentX = width;
currentY = height + height/4;
draw_em++;
}
}
}
if (tracker == 4)
{
if (currentX > width/2 + (width/8) && currentY > (height/18) && sStop == false)
{
currentX += mMoveXPos[3];
currentY += mMoveYPos[3];
canvas.drawBitmap(mPositive.get(tracker -1 ).getDrawingCache(), currentX, currentY, null);
}
else
{
if (sStop == false)
{
mMoveScale = true;
sStop = true;
game_over = true;
currentX = width;
currentY = height + height/4;
draw_em++;
}
}
}
if (draw_em > 0 && game_over == false)
{
for (int i = 0; i < draw_em; i ++)
{
if (i == 0)
{
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), width/2, height/4 + j, null);
}
if (i == 1)
{
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), width/2 + (width/8), height/6 + j, null);
}
if (i == 2)
{
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), width/2, height/12 + j, null);
}
if (i == 3)
{
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), width/2 + (width/8), height/18 + j, null);
}
}
}
else if (game_over == true)
{
for (int i = 0; i < draw_em; i++)
{
if (i == 0 && mCurrentXPos[0] > 0 && mCurrentYPos[0] > 0 && mDrag == false)
{
mCurrentXPos[0] += mMoveByXPos[0];
mCurrentYPos[0] += mMoveByYPos[0];
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), mCurrentXPos[0], mCurrentYPos[0], null);
}
else if (i == 0 && mCurrentXPos[0] <= 0 || mCurrentYPos[0] <= 0 && mDrag == false)
{
canvas.drawBitmap(mPositive.get(0).getDrawingCache(), 0, 0, null);
}
else if (i == 0 && mDrag == true)
{
canvas.drawBitmap(mPositive.get(0).getDrawingCache(), mCurrentXPos[0], mCurrentYPos[0], null);
}
if (i == 1 && mCurrentXPos[1] < (width - (mPositive.get(i).getWidth()/2)) && mCurrentYPos[1] > mPositive.get(i).getHeight()/2)
{
mCurrentXPos[1] += mMoveByXPos[1];
mCurrentYPos[1] += mMoveByYPos[1];
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), mCurrentXPos[1], mCurrentYPos[1], null);
}
else if (i == 1 && mCurrentXPos[1] >= (width - (mPositive.get(i).getWidth()/2)) || mCurrentYPos[1] <= mPositive.get(i).getHeight()/2)
{
canvas.drawBitmap(mPositive.get(1).getDrawingCache(), width - (width/3), 0, null);
}
if (i == 2 && mCurrentXPos[2] > (mPositive.get(i).getWidth()/2) && mCurrentYPos[2] < (height - mPositive.get(i).getHeight()/2))
{
mCurrentXPos[2] += mMoveByXPos[2];
mCurrentYPos[2] += mMoveByYPos[2];
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), mCurrentXPos[2], mCurrentYPos[2], null);
}
else if (i == 2 && mCurrentXPos[2] <= (mPositive.get(i).getWidth()/2) || mCurrentYPos[2] >= (height - mPositive.get(i).getHeight()/2))
{
canvas.drawBitmap(mPositive.get(2).getDrawingCache(), 0, height - (height/4), null);
}
if (i == 3 && mCurrentXPos[3] < (width - (mPositive.get(i).getWidth()/2)) && mCurrentYPos[3] < (height - mPositive.get(i).getHeight()/2))
{
mCurrentXPos[3] += mMoveByXPos[3];
mCurrentYPos[3] += mMoveByYPos[3];
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), mCurrentXPos[3], mCurrentYPos[3], null);
}
else if (i == 3 && mCurrentXPos[3] >= (width - (mPositive.get(i).getWidth()/2)) || mCurrentYPos[3] >= (height - mPositive.get(i).getHeight()/2))
{
canvas.drawBitmap(mPositive.get(3).getDrawingCache(), width - (width/3), height - (height/4), null);
}
}
}
}
h.postDelayed(r, FRAME_RATE);
}
protected void moveIt(Canvas canvas, int moveX,int moveY, int i)
{
if (i == 0)
{
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), moveX, moveY, null);
}
if (i == 1)
{
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), moveX, moveY, null);
}
if (i == 2)
{
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), moveX, moveY, null);
}
if (i == 3)
{
canvas.drawBitmap(mPositive.get(i).getDrawingCache(), moveX, moveY, null);
}
}
protected void moveEm(Canvas canvas, int[]mMovePosX, int[] mMovePosY)
{
for (int i = 0; i < 4; i++)
{
}
}
protected void ScaleIt(Canvas canvas, int i)
{
mScale[i] = Bitmap.createScaledBitmap(mScale[i], (int) (width * 1.5), height, true);
mScale[i-1].recycle();
}
}
And here is the activity:
public class ScaleView extends Activity
{
Context mContext;
Scale mScale;
EditText positive_thought;
Button fire;
TextView pos;
private static Set<String> mPositiveWords;
private static Set<String> mNegativeWords;
int count;
private Pattern four_letter_words = Pattern.compile("not|cant|cnt|can't");
String inputLine;
private String[] inputTokens;
Button question;
Button skip;
public static boolean populatePositiveWords(Context context)
{
mNegativeWords = new HashSet<String>();
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(context.getAssets().open("negative_words.txt")));
String line = reader.readLine();
while (line != null)
{
mNegativeWords.add(line.toLowerCase(Locale.US));
line = reader.readLine();
}
reader.close();
}
catch (IOException exception)
{
return false;
}
return true;
//TODO list of negative words
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.getActionBar().hide();
mContext = this;
populatePositiveWords(mContext);
setContentView(R.layout.activity_scale);
mScale = (Scale) findViewById(R.id.anim_view);
mScale.setClickable(true);
positive_thought = (EditText) findViewById(R.id.thoughts);
fire = (Button) findViewById(R.id.scale_it);
skip = (Button) findViewById(R.id.skip);
question = (Button) findViewById(R.id.question);
InputFilter[] FilterArray = new InputFilter[1];
FilterArray[0] = new InputFilter.LengthFilter(60);
positive_thought.setFilters(FilterArray);
fire.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View view)
{
//if the button is clicked invalidate the ondraw method and pass in the text of the positive word
inputLine = positive_thought.getText().toString();
inputTokens = inputLine.split(" ");
if (inputLine.isEmpty())
{
Toast.makeText(mContext, "You have to write something!", Toast.LENGTH_SHORT).show();
return;
}
if (inputTokens.length < 3)
{
Toast.makeText(mContext, "At least three words are required.", Toast.LENGTH_SHORT).show();
return;
}
if (four_letter_words.matcher(inputLine).find() == true)
{
Toast.makeText(mContext, "Make an affirmative statement!", Toast.LENGTH_SHORT).show();
return;
}
boolean matchesToken = false;
for (int i = 0; i < inputTokens.length; i++)
{
String token = inputTokens[i];
if (mNegativeWords.contains(token.toLowerCase(Locale.US)))
{
matchesToken = true;
break;
}
}
if (matchesToken == true)
{
Toast.makeText(mContext, "Use positive words!", Toast.LENGTH_SHORT).show();
return;
}
else
{
InputMethodManager imm = (InputMethodManager)mContext.getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(positive_thought.getWindowToken(), 0);
pos = new TextView (mContext);
pos.layout(0, 0, mScale.width/3, mScale.height/4);
pos.setGravity(Gravity.CENTER);
pos.setTextSize(15);
pos.setTextColor(Color.RED);
pos.setTypeface(Typeface.DEFAULT_BOLD);
pos.setShadowLayer(5, 2, 2, Color.YELLOW);
pos.setText(positive_thought.getText().toString());
pos.setDrawingCacheEnabled(true);
pos.setBackgroundResource(R.drawable.whitecloud);
pos.setClickable(true);
mScale.mPositive.add(pos);
mScale.scale_it = true;
count++;
mScale.sStop = false;
mScale.tracker = count;
if (count == 4)
{
((RelativeLayout)question.getParent()).removeView(question);
((RelativeLayout)skip.getParent()).removeView(skip);
mScale.mPositive.get(0).setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
mScale.mCurrentXPos[0] = event.getX();
mScale.mCurrentYPos[0] = event.getY();
mScale.mDrag = true;
return true;
}
});
}
}
positive_thought.setText(null);
}
});
}
}
The reason your TextView cannot receive touch events is that the TextView is drawn on the canvas just as a bitmap, not as a View. An excerpt from your code shown below illustrates this.
protected void onDraw(Canvas canvs)
{
....
negative = new TextView(mContext);
...
canvas.drawBitmap(negative.getDrawingCache(), ...)
To deliver touch events to your TextView, your Scale class should extend not View but ViewGroup and the TextView needs to be added as a subview to Scale class by using ViewGroup.addView() or addViewInLayout(). It is not a simple task to implement a ViewGroup subclass. You may have to implement onInterceptTouchEvent(MotionEvent) depending on your needs.
Android's source code will be of help.
Is your CustomView also sets some TouchListner??
If yes then this might causing issue..Remove TouchListner from CustomView and see if it works..
I am creating a game which uses andendgine and here is my code:
Player stanley = new Player();
...
scene.registerUpdateHandler(new IUpdateHandler() {
public void onUpdate(float pSecondsElapsed) {
stanX = stanley.getX();
destX = x.getX();
if(destX < stanX){
if(hasMovedRight == 1){
stanley.stop();
hasMovedRight = 0;
}
else{
stanley.moveLeft();
hasMovedRight = 0
hasMovedLeft = 1;
}
}
if(destX > stanX){
if(hasMovedLeft == 1){
stanley.stop();
hasMovedLeft == 0;
}
else{
stanley.moveRight();
hasMovedLeft = 0;
hasMovedRight = 1;
}
}
}
}
what i want is to stop Player from walking whenever his position X is equal to the touched area X. The problem is it never stop from walking. Thanks!
Your if statements are missing an element where destX == stanX. and you should really use else if. See modified code below.
if(destX + 8 < stanX){
if(hasMovedRight == 1){
stanley.stop();
hasMovedRight = 0;
}
else{
stanley.moveLeft();
hasMovedRight = 0
hasMovedLeft = 1;
}
}
else if(destX - 8 > stanX){
if(hasMovedLeft == 1){
stanley.stop();
hasMovedLeft == 0;
}
else{
stanley.moveRight();
hasMovedLeft = 0;
hasMovedRight = 1;
}
}
else //makes stanley stop. (calls stop method), if at touched x.
{
stanley.stop();
hasMovedRight = 0;
hasMovedLeft = 0;
}
try this one
setOnSceneTouchListener(new IOnSceneTouchListener() {
#Override
public boolean onSceneTouchEvent(Scene scene, TouchEvent event) {
int touchX = (int) (event.getX() - (sCHARStanley.getWidth() / 2));
//so that your sprite will go to the touched part of the screen
}
I am creating softkeyboard for android 2.2 and higher. everything is fine but when i type really quick then some time my ACTION_DOWN method is not calling. Actual flow of called method should look like
1) motionEvent.ACTION_DOWN
2) OnPress()
3) motionEvent.ACTION_UP
4) OnRelease() and repeat same order for next word.
if i type at normal speed then it works fine but if i type fast then above order of method execution looks like
1) motionEvent.ACTION_DOWN
2) OnPress()
3) OnRelease()
4) motionEvent.ACTION_UP and for next word OnPress and OnRelease() methods are being called.
any suggestions?
Edit
My LatinKeyboardView class that contains MotionActionEvents
enter code here #Override
public boolean onTouchEvent(MotionEvent me) {
// Moved next line and added lines to help solve reentrant problem.
int action = me.getAction();
// next 2 lines required for multitouch Andr 2+
int act = action & MotionEvent.ACTION_MASK;
final int ptrIndex = (act & MotionEvent.ACTION_POINTER_ID_MASK) //Renamed to ACTION_POINTER_INDEX_MASK in later Andro versions
>> MotionEvent.ACTION_POINTER_ID_SHIFT;//Renamed to ACTION_POINTER_INDEX_SHIFT in later Andro versions
// currentX = me.getX();
// currentY = me.getY();
calcMinSlide();
// int act = me.getAction();
if (act == android.view.MotionEvent.ACTION_DOWN) {
Log.v(tag, "ANGLE_ACTION_DOWN : ");
if (pw != null) {
pw.dismiss();
pw = null;
}
lastDirection = direction = 0;
touchDownPoint.set(me.getX(), me.getY());
// Will added next two lines
touchDragPoint.set(me.getX(), me.getY());
thresholdPoint.set(me.getX(), me.getY());
// Will6 added to improve accuracy
thresholdPoint1_5 = false;
// Will7 added next 4 for Andro 2+
currentX = me.getX();
currentY = me.getY();
// Save the ID of this first pointer (touch) down
currentPointerID = me.getPointerId(0);
nextPointerID = INVALID_POINTER_ID;
previousDownTime = me.getEventTime();
me.setLocation(touchDownPoint.x, touchDownPoint.y);
// start timer on touch down
startTimer(me, 300); // 150); Will7 changed this and removed method: checkLongPress
} else if (act == android.view.MotionEvent.ACTION_UP
|| act == android.view.MotionEvent.ACTION_MOVE) {
Log.v(tag, "ANGLE_ACTION_UP : ");
//touchdragPoint and previoustouchPoint for calculating velocity
PointF previousTouchPoint = new PointF(touchDragPoint.x,touchDragPoint.y);
//Will7 added next if for Andro 2+: Find the index of the active pointer and fetch its position
if (act == android.view.MotionEvent.ACTION_MOVE && me.getPointerId(ptrIndex) != currentPointerID) {
//Log.v(tag, "Cancel ATION_MOVE!! ID: "+me.getPointerId(ptrIndex));
return super.onTouchEvent(me);
}
touchDragPoint.set(me.getX(), me.getY());
dy = me.getY() - touchDownPoint.y;
dx = me.getX() - touchDownPoint.x;
// added for Andro 2+
currentX = touchDragPoint.x;
currentY = touchDragPoint.y;
//calculate time interval from down time to current time
long timeInterval = me.getEventTime() - previousDownTime;
previousDownTime = me.getEventTime();
velocityThresDir = VELOCITY_THRESHOLD;
float touchVelocity = Math.abs(distanceBetweenPoints(touchDragPoint, previousTouchPoint) / timeInterval);
if (distanceFromCenter(dx,dy) > minSlide) {
// Log.v(tag, "direction to detect angle....after... dx..."+dx+" dy "+dy);
//Log.v(tag, "ANGLE angle.... after..."+distanceFromCenter(dx,dy)+" slide distance "+ minSlide);
/* cancel the timer*/
if (cDownTimer != null) {
cDownTimer.cancel();
cDownTimer = null;
}
/* coding for calculating velocity threshold*/
float angleThreshold = 0.0f;
if ((thresholdPoint.x == touchDownPoint.x) && (thresholdPoint.y == touchDownPoint.y)){
thresholdPoint.set(touchDragPoint.x, touchDragPoint.y);
}
else {
//Will6 - added next if to improve accuracy
if ((distanceFromCenter(dx,dy) > (minSlide * 1.5)) && !thresholdPoint1_5){
thresholdPoint.set(me.getX(),me.getY());
thresholdPoint1_5 = true;
}
float angleP1= calcAngle(touchDownPoint, thresholdPoint);
float angleP2= calcAngle(previousTouchPoint, touchDragPoint);
angleThreshold = Math.abs(angleP1 - angleP2);
if (angleThreshold > Math.PI) angleThreshold = (float) (2.0 * Math.PI) - angleThreshold;
}
// velocityThresDir = (float) Math.abs((Math.cos(angleThreshold) * touchVelocity*1000));
velocityThresDir = (float) (Math.cos(angleThreshold) * touchVelocity*1000);
//end of calculation for velocity threshold
double angle = newM(touchDownPoint.x, touchDownPoint.y, touchDragPoint.x, touchDragPoint.y);
// Log.v(tag, "ANGLE_FIRST_X "+touchDownPoint.x+"FIRST_Y "+touchDownPoint.y);
// Log.v(tag, "ANGLE_SECOND_X "+touchDragPoint.x+"SECOND_Y "+touchDragPoint.y);
// Log.v(tag, "ANGLE_FIRST"+angle);
if ((touchDownPoint.x != thresholdPoint.x) || (touchDownPoint.y != thresholdPoint.y)) {
double angleThresh = newM(touchDownPoint.x, touchDownPoint.y, thresholdPoint.x, thresholdPoint.y);
double angleBetween = Math.abs(angle - angleThresh);
if(angleBetween < 45 || angleBetween > 315){
if(angleBetween > 315) {
if (angle < angleThresh) {
angle += 360;
}
else if (angle > angleThresh) {
angleThresh += 360;
}
angle = Math.abs((angle - angleThresh)%360) / 2.0;
// Log.v(tag, "ANGLE_SECOND"+angle);
}
else {
angle = (angle + angleThresh * 1.0) / 2.0;
// Log.v(tag, "ANGLE_THIRD"+angle);
}
}
}
if (angle > 337.5){
direction = 3;
}else if (angle > 292.5){
direction = 5;
}else if (angle > 247.5){
direction = 4;
}else if (angle > 202.5){
direction = 6;
}else if (angle > 157.5){
direction = 1;
}else if (angle > 112.5){
direction = 7;
}else if (angle > 67.5){
direction = 2;
}else if (angle > 22.5){
direction = 8;
}else{
direction = 3;
}
/* start timer if velocity is below velocity threshold*/
if ((velocityThresDir < VELOCITY_THRESHOLD) &&
(act == android.view.MotionEvent.ACTION_MOVE) && (cDownTimer == null) &&
(pw == null)) { //"&& cDownTimer" can be removed I think
/* start timer with motionEvent and time in ms as a parameter */
// added next two lines
callOnLongPress(me);
startTimerShowPopup(me,100);//Will changed from 150
}
} else {
direction = 0;
}
if (act == android.view.MotionEvent.ACTION_MOVE) {
return true;
} else if (act == android.view.MotionEvent.ACTION_UP) {
if (cDownTimer != null) {
cDownTimer.cancel();
cDownTimer = null;
}
if (pw != null)
pw.dismiss();
if (longPressedKey) {
SoftKeyboard.mComposing
.append(charset[mappedKey][direction]);
popUpTextEntryScheme = true;
}
longPressedKey = false;
currentPointerID = INVALID_POINTER_ID;
}
}
else if (act == android.view.MotionEvent.ACTION_POINTER_DOWN) {
// if (me.getPointerCount() > 1) { //Should always be true, I think
nextPointerID = me.getPointerId(ptrIndex);
nextTouchDownPoint.set(me.getX(ptrIndex),me.getY(ptrIndex));
// }
}
else if (act == android.view.MotionEvent.ACTION_CANCEL) {
currentPointerID = INVALID_POINTER_ID;
nextPointerID = INVALID_POINTER_ID;
}
else if (act == android.view.MotionEvent.ACTION_POINTER_UP) {
// Extract the index of the pointer that left the touch sensor
final int pointerId = me.getPointerId(ptrIndex);
if (pointerId == currentPointerID) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = ptrIndex == 0 ? 1 : 0;
currentPointerID = nextPointerID;//(0);
touchDownPoint.set(nextTouchDownPoint.x,nextTouchDownPoint.y);
if (cDownTimer != null) {
cDownTimer.cancel();
cDownTimer = null;
}
if (pw != null) {
pw.dismiss();
pw = null;
}
if (longPressedKey) {
SoftKeyboard.mComposing
.append(charset[mappedKey][direction]);
popUpTextEntryScheme = true;
}
longPressedKey = false;
lastDirection = direction = 0; // keysAtOnce=0;
touchDragPoint.set(me.getX(newPointerIndex),me.getY(newPointerIndex));
thresholdPoint.set(nextTouchDownPoint.x,nextTouchDownPoint.y);
//added to improve accuracy
thresholdPoint1_5 = false;
// added next 3 for Andro 2+
currentX = touchDragPoint.x;
currentY = touchDragPoint.y;
// Save the ID of this first pointer (touch) down
previousDownTime = me.getEventTime();
me.setLocation(touchDownPoint.x, touchDownPoint.y);
//start timer on touch down
startTimer(me,300); //150); Will7 changed this and removed method: checkLongPress
} else { //Second pointer up before first. (Not handling 3 or more pointers yet!)
// nextPointerID = INVALID_POINTER_ID;
}
} //else
return super.onTouchEvent(me); // after we return here the service will get notified, etc
// return true;
}
and my SoftKeyboard class..
public void onPress(int primaryCode) {
Log.v("SoftKeyboard", "ANGLE_ACTION_ON_PRESS : ");
// added next section for repeating backspace
if (RepeatBSTimer != null) {
RepeatBSTimer.cancel();
RepeatBSTimer = null;
}
if (mp != null) { // /Will7 moved this from just above keystroke
// statement
mp.release();
mp = null;
}
// added for Andro 2+ multitouch
if (primaryCode == pressedCode
&& LatinKeyboardView.nextPointerID != LatinKeyboardView.INVALID_POINTER_ID) {
// I need to look up the real primaryCode here. (Not sure how!)
// Android gives wrong values when touches overlap.
wrongPrimaryCode = true;
return;
} else
wrongPrimaryCode = false;
pressedCode = primaryCode;
// added next section for repeating backspace
if (primaryCode == Keyboard.KEYCODE_DELETE) {
RepeatBSTimer = new CountDownTimer(1500000, 75) {
#Override
public void onTick(long millisUntilFinished) {
int primaryCode2;
if (LatinKeyboardView.longPressedKey
|| (1500000 - millisUntilFinished > 500)) {
primaryCode2 = getCharFromKey(pressedCode,
LatinKeyboardView.direction, mInputView
.getKeyboard());
if (primaryCode2 == Keyboard.KEYCODE_DELETE) {
repeating = true;
handleBackspace();
} else if (primaryCode2 == KEYCODE_DELETEWORD
&& (millisUntilFinished % 150) < 75) {
repeating = true;
deleteLastWord();
}
}
}
#Override
public void onFinish() {
}
};
RepeatBSTimer.start();
}
// added section for repeating backspace
Uri uri = Uri.parse("android.resource://" + getPackageName() + "/"
+ R.raw.keystroke);// Play Key Click
try {
mp = new MediaPlayer();
mp.setDataSource(this, uri);
mp.prepare();
mp.start();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void onRelease(int primaryCode) {
// Will7 added next line if for Andro 2+ multitouch
if (wrongPrimaryCode
&& LatinKeyboardView.nextPointerID != LatinKeyboardView.INVALID_POINTER_ID) {
return;
}
// else pressedCode = primaryCode;
// added next sections for repeating backspace
primaryCode = getCharFromKey(pressedCode, LatinKeyboardView.direction,mInputView.getKeyboard());
if (primaryCode == Keyboard.KEYCODE_DELETE && !repeating)
handleBackspace();
if (primaryCode == KEYCODE_DELETEWORD && !repeating)
deleteLastWord();
repeating = false;
if (RepeatBSTimer != null) {
RepeatBSTimer.cancel();
RepeatBSTimer = null;
}
// moved all the rest of this method from onKey()
int[] keyCodes;
// added this var for Andro 2+ multitouch
keyCodes = keyCodesSave;
commitTyped(getCurrentInputConnection());
if (isWordSeparator(primaryCode) && (char) primaryCode != '.'
&& (char) primaryCode != '!' && (char) primaryCode != '?') {
// Handle separator
if (mComposing.length() > 0) {
commitTyped(getCurrentInputConnection());
}
sendKey(primaryCode);
updateShiftKeyState(getCurrentInputEditorInfo());
} else if (primaryCode == Keyboard.KEYCODE_DELETE) {
// commented out next line for repeating backspace
// handleBackspace();
} else if (primaryCode == Keyboard.KEYCODE_SHIFT || primaryCode == -1) {
handleShift();
} else if (primaryCode == Keyboard.KEYCODE_CANCEL) {
handleClose();
return;
} else if (primaryCode == KEYCODE_ESCAPE) {
// Do nothing on Escape key
} else if (primaryCode == LatinKeyboardView.KEYCODE_OPTIONS) {
// Show a menu or something
} else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE
&& mInputView != null) {
Keyboard current = mInputView.getKeyboard();
if (current == mSymbolsKeyboard
|| current == mSymbolsShiftedKeyboard) {
getCurrentInputConnection().finishComposingText();
current = mQwertyKeyboard;
} else {
getCurrentInputConnection().finishComposingText();
current = mSymbolsKeyboard;
}
mInputView.setKeyboard(current);
if (current == mSymbolsKeyboard) {
current.setShifted(false);
}
} else if (primaryCode == KEYCODE_CAPSLOCK)// handle caps lock
{
if (mInputView.getKeyboard() == mQwertyKeyboard
|| mInputView.getKeyboard() == mSymbolsKeyboard) {
mInputView.setKeyboard(mQwertyKeyboardUpperCase);
mQwertyKeyboardUpperCase.setShifted(true);
mCapsLock = true;
} else {
mQwertyKeyboard.setShifted(false);
mInputView.setKeyboard(mQwertyKeyboard);
mCapsLock = false;
}
} else if (primaryCode == KEYCODE_DELETEWORD) {
// commented out next line for repeating backspace
// deleteLastWord();
} else if (primaryCode == KEYCODE_FULL_STOP_AND_SPACE) {
// added next line
backspaceIfSpaceLeft();
getCurrentInputConnection().finishComposingText();
handleCharacter((int) '.', keyCodes);
handleCharacter((int) ' ', keyCodes);
handleShift();
}
// added next 5 KEYCODES
else if (primaryCode == KEYCODE_EXCLAMATION) {
// added next line
backspaceIfSpaceLeft();
getCurrentInputConnection().finishComposingText();
handleCharacter((int) '!', keyCodes);
handleCharacter((int) ' ', keyCodes);
handleShift();
} else if (primaryCode == KEYCODE_QUESTION_MARK) {
// added next line
backspaceIfSpaceLeft();
getCurrentInputConnection().finishComposingText();
handleCharacter((int) '?', keyCodes);
handleCharacter((int) ' ', keyCodes);
handleShift();
} else if (primaryCode == KEYCODE_COMMA) {
// added next line
backspaceIfSpaceLeft();
getCurrentInputConnection().finishComposingText();
handleCharacter((int) ',', keyCodes);
handleCharacter((int) ' ', keyCodes);
} else if (primaryCode == KEYCODE_COLON) {
// added next line
backspaceIfSpaceLeft();
getCurrentInputConnection().finishComposingText();
handleCharacter((int) ':', keyCodes);
handleCharacter((int) ' ', keyCodes);
} else if (primaryCode == KEYCODE_SEMICOLON) {
// added next line
backspaceIfSpaceLeft();
getCurrentInputConnection().finishComposingText();
handleCharacter((int) ';', keyCodes);
handleCharacter((int) ' ', keyCodes);
} else {
handleCharacter(primaryCode, keyCodes);
}
}
Thanks..
This is a very long onTouchEvent handler, I suggest breaking it up into more logical steps. I also have had the issue of seemingly "out-of-order" events when trying to handle the touchscreen.
I found that I wasn't handling the events per pointer ID correctly. I'd check to make sure you are handling multiple pointers as expected. The device I test with (N1) only supports two pointers, but others support many more, and those should be accounted for.
For handling touchscreen "soft-buttons" as an onTouchEvent event, I've found it useful to create a state machine class. Use the MotionEvent parameters as input events to the state machine, and cause state transitions to trigger your wanted events. An explicit, state-driven approach will give you the expected results you are looking for.