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.
Related
So I am trying to make a simple android game in which player has to move two objects in different halfs of the screen at the same time using swipes. It works just fine if I try to swipe to move one object and then the second one a moment after the first. But if I try swiping in two halfs at the same time it won't work. I tried managing with so-called multi-tuch but... well I need extra help.
public static event OnSwipeInput SwipeEvent;
public delegate void OnSwipeInput(Vector2 direction,bool side);
public static event OnSwipeInput SwipeEvent2;
private Vector2 tapPosition;
private Vector2 tapPosition2;
private Vector2 delta;
private Vector2 delta2;
private float deadZone = 30;
private bool isSwiping;
private bool isSwiping2;
private bool isMobile;
private bool left_side = true;
private bool left_side2 = true;
void Start()
{
isMobile = Application.isMobilePlatform;
isMobile = true;
Debug.Log("aaaa "+isMobile);
}
void Update()
{
float p;
if (!isMobile)
{
p = Mathf.Abs(Input.mousePosition.x) - Screen.width / 2;
if (Input.GetMouseButtonDown(0))
{
isSwiping = true;
tapPosition = Input.mousePosition;
if (p < 0)
left_side = true;
else
left_side = false;
}
else if(Input.GetMouseButtonDown(0))
ResetSwipe();
}
else
{
if (Input.touchCount >= 1) //try
{
if (Input.GetTouch(0).phase == TouchPhase.Began)
{
p = Mathf.Abs(Input.GetTouch(0).position.x) - Screen.width / 2;
if (p < 0)
left_side = true;
else
left_side = false;
isSwiping = true;
tapPosition = Input.GetTouch(0).position;
}
else if (Input.GetTouch(0).phase == TouchPhase.Canceled || Input.GetTouch(0).phase == TouchPhase.Ended)
{
ResetSwipe();
}
}
if (Input.touchCount >= 2)
{
Input.multiTouchEnabled = true;
if (Input.GetTouch(1).phase == TouchPhase.Began)
{
p = Mathf.Abs(Input.GetTouch(1).position.x) - Screen.width / 2;
if (p < 0)
left_side2 = true;
else
left_side2 = false;
isSwiping2 = true;
tapPosition2 = Input.GetTouch(1).position;
}
else if (Input.GetTouch(1).phase == TouchPhase.Canceled || Input.GetTouch(1).phase == TouchPhase.Ended)
{
ResetSwipe2();
}
}
}
CheckSwipe();
}
private void CheckSwipe(){
if(Input.touchCount >= 1 || Input.GetMouseButton(0))
{
Debug.Log("there is 1 swipe");
delta = Vector2.zero;
if (isSwiping)
{
if (!isMobile && Input.GetMouseButton(0))
{
delta = (Vector2)Input.mousePosition - tapPosition;
}
else if (Input.touchCount == 1)
{
delta = (Vector2)Input.GetTouch(0).position - tapPosition;
}
}
if (delta.magnitude > deadZone)
{
if (SwipeEvent != null)
{
if (Mathf.Abs(delta.x) > Mathf.Abs(delta.y))
{
SwipeEvent.Invoke(delta.x > 0 ? Vector2.right : Vector2.left, left_side);
}
else
{
SwipeEvent.Invoke(delta.y > 0 ? Vector2.up : Vector2.down, left_side);
}
}
ResetSwipe();
}
}
else
{
Debug.Log("there are NO swipes");
}
if (Input.touchCount == 2)
{
Debug.Log("there are 2 swipes");
delta2 = Vector2.zero;
if (isSwiping2)
{
if (Input.touchCount == 2)
{
delta2 = (Vector2)Input.GetTouch(1).position - tapPosition;
}
}
if (delta2.magnitude > deadZone)
{
if (SwipeEvent2 != null)
{
if (Mathf.Abs(delta.x) > Mathf.Abs(delta.y))
{
SwipeEvent2.Invoke(delta2.x > 0 ? Vector2.right : Vector2.left, left_side2);
}
else
{
SwipeEvent2.Invoke(delta2.y > 0 ? Vector2.up : Vector2.down, left_side2);
}
}
ResetSwipe2();
}
}
}
private void ResetSwipe()
{
isSwiping=false;
tapPosition=Vector2.zero;
delta = Vector2.zero;
}
private void ResetSwipe2()
{
isSwiping2 = false;
tapPosition2 = Vector2.zero;
delta2 = Vector2.zero;
}
As you can see I am trying to operate with swipes differently seeing how many touches there are. No luck so far.
Any advice will be appriciated!
thank you
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 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.
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 a android beginner.
I am doing a android project which has a function to reorder something in a list.
I found a open source at https://github.com/commonsguy/cwac-touchlist#readme
and the module name is CWAC: TouchListView
But during my implementation, I have some problems and hope someone can help me,
I wanna to turnoff the remove function when I move the list item at horizontal but I cannot...
If I comment the remove code at TouchListView.onTouchEvent()'s case MotionEvent.ACTION_CANCEL
It will occur the unexpected behavior.
Also, I wanna have something animation during dragging the item like dolphin browser bookmark page, but I don't know is it should be implements the DragListener??
However, I have a bug fixed on it.
#Override
public boolean onTouchEvent(MotionEvent ev) {
if (mGestureDetector != null) {
mGestureDetector.onTouchEvent(ev);
}
if ((mDragListener != null || mDropListener != null) && mDragView != null) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
Rect r = mTempRect;
mDragView.getDrawingRect(r);
stopDragging();
if (mRemoveMode == SLIDE_RIGHT && ev.getX() > r.left + (r.width() * 3 / 4)) {
if (mRemoveListener != null) {
mRemoveListener.remove(mFirstDragPos);
}
unExpandViews(true);
} else if (mRemoveMode == SLIDE_LEFT && ev.getX() < r.left + (r.width() / 4)) {
if (mRemoveListener != null) {
mRemoveListener.remove(mFirstDragPos);
}
unExpandViews(true);
} else {
if (mDropListener != null && mDragPos >= 0 && mDragPos < getCount() - 1) {
mDropListener.drop(mFirstDragPos, mDragPos);
}
unExpandViews(false);
}
break;
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
int x = (int) ev.getX();
int y = (int) ev.getY();
dragView(x, y);
int itemnum = getItemForPosition(y);
if (itemnum >= 0) {
if (action == MotionEvent.ACTION_DOWN || itemnum != mDragPos) {
if (mDragListener != null) {
mDragListener.drag(mDragPos, itemnum);
}
mDragPos = itemnum;
doExpansion();
}
int speed = 0;
adjustScrollBounds(y);
if (y > mLowerBound) {
// scroll the list up a bit
speed = y > (mHeight + mLowerBound) / 2 ? 16 : 4;
} else if (y < mUpperBound) {
// scroll the list down a bit
speed = y < mUpperBound / 2 ? -16 : -4;
}
if (speed != 0) {
int ref = pointToPosition(0, mHeight / 2);
if (ref == AdapterView.INVALID_POSITION) {
// we hit a divider or an invisible view, check
// somewhere else
ref = pointToPosition(0, mHeight / 2 + getDividerHeight() + 64);
}
View v = getChildAt(ref - getFirstVisiblePosition());
if (v != null) {
int pos = v.getTop();
setSelectionFromTop(ref, pos - speed);
}
}
}
break;
}
return true;
}
return super.onTouchEvent(ev);
}
For the case MotionEvent.ACTION_CANCEL, if I drag the item over the list.getCount, it will throw exception, so I replace the condition
from
if (mDropListener != null && mDragPos >= 0 && mDragPos < getCount() ) {
mDropListener.drop(mFirstDragPos, mDragPos);
}
to
if (mDropListener != null && mDragPos >= 0 && mDragPos < getCount() - 1) {
mDropListener.drop(mFirstDragPos, mDragPos);
}
Then the exception will be fixed.
Could anyone can help me??
Many thanks.
I wanna to turnoff the remove function when I move the list item at horizontal but I cannot
Use the custom remove_mode attribute with a value of "none". For example:
<?xml version="1.0" encoding="utf-8"?>
<com.commonsware.cwac.tlv.TouchListView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tlv="http://schemas.android.com/apk/res/com.commonsware.cwac.tlv.demo"
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:drawSelectorOnTop="false"
tlv:normal_height="64dip"
tlv:grabber="#+id/icon"
tlv:remove_mode="none"
/>
I wanna have something animation during dragging the item like dolphin browser bookmark page, but I don't know is it
I will not be able to help you with that, sorry.