So, I went through all the discussions on the issue here.
I return true, there is no other place where the ACTION_UP is handled .
I use a thread to handle graphics and calculations, although I can't figure out why this should matter.
this is my implementation of the onTouch method:
#Override
public boolean onTouch(View v, MotionEvent event) {
synchronized (this) {
int action = event.getAction() & MotionEvent.ACTION_MASK;
int pointerIndex = event.getAction()
& MotionEvent.ACTION_POINTER_INDEX_MASK >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
int pointerCount = event.getPointerCount();
TouchEvent touchEvent;
for (int i = 0; i < MAX_TOUCHPOINTS; i++) {
if (i >= pointerCount) {
isTouched[i] = false;
id[i] = -1;
continue;
}
int pointerId = event.getPointerId(i);
if ((event.getAction() != MotionEvent.ACTION_MOVE && i != pointerIndex)) {
// if its an up/down/cancel/out event mask the id to see if
// we should process it for this touch point
continue;
}
Log.i("Logged TouchEvents", "" + event.getAction());
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
touchEvent = touchEventPool.newObject();
touchEvent.type = TouchEvent.TOUCH_DOWN;
touchEvent.pointer = pointerId;
touchEvent.x = touchX[i] = (int) (event.getX() * scaleX);
touchEvent.y = touchY[i] = (int) (event.getY() * scaleY);
isTouched[i] = true;
id[i] = pointerId;
toucheventBuffer.add(touchEvent);
Log.d("MultiTouchHandler", "TouchEvent.Down ("
+ touchEvent.x + "," + touchEvent.y + ")");
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_CANCEL:
touchEvent = touchEventPool.newObject();
touchEvent.type = TouchEvent.TOUCH_UP;
touchEvent.pointer = pointerId;
touchEvent.x = touchX[i] = (int) (event.getX() * scaleX);
touchEvent.y = touchY[i] = (int) (event.getY() * scaleY);
isTouched[i] = false;
id[i] = -1;
toucheventBuffer.add(touchEvent);
Log.d("MultiTouchHandler", "TouchEvent.TouchUp ("
+ touchEvent.x + "," + touchEvent.y + ")");
break;
case MotionEvent.ACTION_MOVE:
touchEvent = touchEventPool.newObject();
touchEvent.type = TouchEvent.TOUCH_DRAG;
touchEvent.pointer = pointerId;
touchEvent.x = touchX[i] = (int) (event.getX() * scaleX);
touchEvent.y = touchY[i] = (int) (event.getY() * scaleY);
isTouched[i] = true;
id[i] = pointerId;
toucheventBuffer.add(touchEvent);
Log.d("MultiTouchHandler", "TouchEvent.TouchDrag ("
+ touchEvent.x + "," + touchEvent.y + ")");
break;
default:
break;
}
}
}
return true;
}
Please note that the variable 'action'(checked before the switch/case) never equals 1(ACTION_UP)
Thanks in advance.
Related
Here is my sample code:
#Override
public boolean onTouchEvent(MotionEvent e) {
float center = mScrubberX + mScrubberWidth / 2;
float handleLeft = center - HANDLE_WIDTH;
float handleRight = center + HANDLE_WIDTH;
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
if (e.getX() > handleLeft && e.getX() < handleRight) {
mActionDown = true;
mActionDownX = e.getX() - mScrubberX;
}
break;
case MotionEvent.ACTION_MOVE:
float newLeft = e.getX() - mActionDownX;
float newRight = newLeft + mScrubberWidth;
if (mActionDown && !mIsStreaming) {
if (newLeft > mScrubberContainer.getLeft() &&
newRight < mScrubberContainer.getRight()) {
mScrubberX = e.getX() - mActionDownX;
textView.setText(""+mScrubberX)
} else if (newRight < mScrubberContainer.getRight()) {
mScrubberX = mScrubberContainer.getLeft();
} else if (newLeft > mScrubberContainer.getLeft()) {
mScrubberX = mScrubberContainer.getRight() - mScrubberWidth;
}
}
break;
case MotionEvent.ACTION_UP:
mActionDown = false;
break;
default:
//Do nothing
}
invalidate();
return true;
}
Please check line "textView.setText(""+mScrubberX)" struck the UI. I have tried putting this inside Handler, Asynctask.executor, runOnUIThread but nothing worked.
Please suggest some solution to get rid of this issue.
I am developing an android application, in my application I dynamically create some ImageViews and set that ImageViews in to a RelativeLayout. So I want to drag each image in the layout independently.Now its working but not properly, when I drag image then the image start vibrating and moving slowly. And I wanted to implement Pinch Zoom in this image.Is it possible? And how how can I remove the vibration on moving the image ? If any one know it please help me..
Thanks
This is my onTouchListener()
canvasImage[i].setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
x1 = motionEvent.getX();
y1 = motionEvent.getY();
//Log.v("vvvvvv", "" + x1 + " " + y1);
final int action = motionEvent.getAction();
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
String w = imglayout.getTop() + " " + imglayout.getHeight();
Log.v("wwww", "" + w);
x2 = motionEvent.getX();
y2 = motionEvent.getY();
dx = x2 - canvasImage[finalI].getX();
dy = y2 - canvasImage[finalI].getY();
//Log.v("cccccc", "" + x2 + " " + y2);
moving = true;
break;
case MotionEvent.ACTION_UP:
moving = false;
break;
case MotionEvent.ACTION_MOVE:
if (moving) {
canvasImage[finalI].setX(motionEvent.getX() - dx);
canvasImage[finalI].setY(motionEvent.getY() - dy);
//Log.v("qqqqqq", "" + canvasImage[finalI].getX());
}
break;
}
//mainLayout.invalidate();
return true;
}
});
This is my setCanvasImage() method used to set images into RelativeLayout
public void setCanvasImage() {
int screenSize = getResources().getConfiguration().screenLayout &
Configuration.SCREENLAYOUT_SIZE_MASK;
final int imgCount = dbobj.getFromTemp();
canvasImage = new ImageView[imgCount];
imglayout = (RelativeLayout) findViewById(R.id.canvas);
final String[] strImage = dbobj.getdImage();
imglayout.removeAllViews();
for (int i = 0; i < imgCount; i++) {
canvasImage[i] = new ImageView(this);
canvasImage[i].setTag("img_" + i);
boolean tabletSize = getResources().getBoolean(R.bool.isTablet);
if (tabletSize) {
int imgWidth = 130;
int imgHeight = 130;
RelativeLayout.LayoutParams paramss = new RelativeLayout.LayoutParams(imgWidth, imgHeight);
paramss.setMargins(posLeft, posTop, 0, 0);
canvasImage[i].setLayoutParams(paramss);
canvasImage[i].setScaleType(ScaleType.FIT_XY);
canvasImage[i].setTag(strImage[i]);
setImage(strImage[i], canvasImage[i]);
imglayout.addView(canvasImage[i]);
}
if( screenSize == Configuration.SCREENLAYOUT_SIZE_NORMAL){
int imgWidth = 100;
int imgHeight = 100;
RelativeLayout.LayoutParams paramss = new RelativeLayout.LayoutParams(imgWidth, imgHeight);
paramss.setMargins(posLeft, posTop, 0, 0);
canvasImage[i].setLayoutParams(paramss);
canvasImage[i].setTag(strImage[i]);
setImage(strImage[i], canvasImage[i]);
imglayout.addView(canvasImage[i]);
}
posLeft = posLeft + 15;
}
}
RelativeLayout xml file
<RelativeLayout
android:layout_below="#+id/btnhorscrolvw"
android:layout_width="match_parent"
android:layout_height="500dp"
android:id="#+id/canvas"
android:background="#ffff"
android:orientation="horizontal"
>
</RelativeLayout>
I think this will work.
float dX, dY;
#Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
dX = view.getX() - event.getRawX();
dY = view.getY() - event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
view.animate()
.x(event.getRawX() + dX)
.y(event.getRawY() + dY)
.setDuration(0)
.start();
break;
default:
return false;
}
return true;
}
You need to use scalx and scaley factor of imageview for implementing pinch zooming
imageview.setScaleX(scalefactor);
imageview.setScaleY(scalefacto);
Android you can adjust the margin left and margin top to for draging the imageview
public boolean onTouchEvent(MotionEvent event) {
//Log.e(Codistan_Tag, "Touch Event: " + MotionEvent.actionToString(event.getAction()));
if(isImageReady) {
if(isSelectionDragEnabled)
mPanListener.onTouchEvent(event);
if (isZoomEnabled) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
anchor_scale = mScaleFactor;
}
mScaleDetector.onTouchEvent(event);
mPanListener.onTouchEvent(event);
}
else {
switch (event.getAction()) {
case MotionEvent.ACTION_POINTER_3_DOWN:
break;
case MotionEvent.ACTION_POINTER_2_DOWN:
break;
case MotionEvent.ACTION_POINTER_1_UP:
break;
case MotionEvent.ACTION_DOWN:
if (isSelectionToolEnabled)
isDrawFinished = false;
orig_x = event.getX();
orig_y = event.getY();
//Log.e(Codistan_Tag, "-------ORIGIN-------s: " + String.valueOf(orig_x) + " " + String.valueOf(orig_y));
orig_x = (orig_x - (dest.left));
orig_y = (orig_y - (dest.top));
if(java.lang.Math.round(mScaleFactor) > 2) {
orig_x += (scale_cur_x * (riz_scale));
orig_y += (scale_cur_y * (riz_scale));
} else {
orig_x += (scale_cur_x);
orig_y += (scale_cur_y);
}
orig_x /= java.lang.Math.round(mScaleFactor);
orig_y /= java.lang.Math.round(mScaleFactor);
orig_x *= scale;
orig_y *= scale;
//mSelectionTaskManager.setOrigin((int) orig_x, (int) orig_y);
if(isSelectionToolEnabled)
MovementStack.add(new Pair((int)orig_x, (int)orig_y));
Log.e(Codistan_Tag, "Codistan Origins: " + String.valueOf(orig_x) + ", " + String.valueOf(orig_y));
break;
case MotionEvent.ACTION_MOVE:
max_dist = dist * scale;
if (event.getAction() != 1) {
move_x = event.getX();
move_y = event.getY();
//Log.e(Codistan_Tag, "Move: " + String.valueOf(move_x) + ", " + String.valueOf(move_y));
move_x = (move_x - dest.left);
move_y = (move_y - dest.top);
if(java.lang.Math.round(mScaleFactor) > 2) {
move_x += (scale_cur_x * riz_scale);
move_y += (scale_cur_y * riz_scale);
} else {
move_x += (scale_cur_x);
move_y += (scale_cur_y);
}
move_x /= java.lang.Math.round(mScaleFactor);
move_y /= java.lang.Math.round(mScaleFactor);
move_x *= scale;
move_y *= scale;
Log.e(Codistan_Tag, "Codistan Move: " + String.valueOf(move_x) + ", " + String.valueOf(move_y));
if (move_x >= 0 && move_y >= 0) {
if (!isSelectionToolEnabled && isDistortionEnabled) {
warpPhotoFromC(image, height, width, max_dist/mScaleFactor, orig_x, orig_y, move_x, move_y);
first++;
distortedBmp.setPixels(image, 0, width, 0, 0, width, height);
fg = false;
} else {
//Cut Tool Enabled
distortedBmp.setPixels(image, 0, width, 0, 0, width, height);
MovementStack.add(new Pair((int) move_x, (int) move_y));
}
}
}
orig_x = move_x;
orig_y = move_y;
break;
case MotionEvent.ACTION_UP:
if (isSelectionToolEnabled)
isDrawFinished = true;
break;
}
}
v.invalidate();
}
return true;
}
basically m taking the screen shot and applying cropping on it i m selecting the cropping area using finger to draw a portion to crop . when i left moving my finger then the line appear but i want the line to follow my finger
Create a customView over which you can draw the line.As it appears that this view should appear above your image then better extend it with Framelayout with same .And place it above image.
FingerLine.class
public class FingerLine extends FrameLayout {
private final Paint mPaint;
private float startX;
private float startY;
private float endX;
private float endY;
public FingerLine(Context context) {
this(context, null);
}
public FingerLine(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Style.STROKE);
mPaint.setColor(Color.RED);
}
#Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawLine(startX, startY, endX, endY, mPaint);
}
#Override
public boolean onTouchEvent(#NonNull MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();
invalidate();
break;
case MotionEvent.ACTION_MOVE:
endX = event.getX();
endY = event.getY();
invalidate();
break;
case MotionEvent.ACTION_UP:
endX = event.getX();
endY = event.getY();
invalidate();
break;
}
return true;
}
}
Note:Don't forget to call invalidate() because it will be responsible to call onDraw
I am trying to do swipe from both side in Listview but now i only able to do from right side, but i want to do swipe from both left and right please can any one tell me how to do that.
private void swipe(int dis) {
if (dis > mMenuView.getWidth()) {
dis = mMenuView.getWidth();
}
if (dis < 0) {
dis = 0;
}
mContentView.layout(-dis, mContentView.getTop(), mContentView.getWidth() - dis, getMeasuredHeight());
mMenuView.layout(mContentView.getWidth() - dis, mMenuView.getTop(),
mContentView.getWidth() + mMenuView.getWidth() - dis,
mMenuView.getBottom());
}
/onSwipe Function/
public boolean onSwipe(MotionEvent event) {
mGestureDetector.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mDownX = (int) event.getX();
isFling = false;
break;
case MotionEvent.ACTION_MOVE:
// Log.i("byz", "downX = " + mDownX + ", moveX = " + event.getX());
int dis = (int) (mDownX - event.getX());
if (state == STATE_OPEN) {
dis += mMenuView.getWidth();
}
swipe(dis);
break;
case MotionEvent.ACTION_UP:
if (isFling
|| (mDownX - event.getX()) > (mMenuView.getWidth() / 1.5)) {
// open
smoothOpenMenu();
} else {
// close
smoothCloseMenu();
return false;
}
break;
}
return true;
}
Please go through the above code and suggest me some solution.
I have been studying multitouch on android but i got couldn't understand some of the lines i found.i searched google but couldn't find that understandable resources. i am posting the code.
I understand most of the part except "first two lines of onTouch method", if (event.getAction() != MotionEvent.ACTION_MOVE && i != pointerIndex) and case MotionEvent.ACTION_MOVE:
Please explain them.
Thanks for your help~~
package --- ;
--imports--
#TargetApi(5)
public class MultiTouchTest extends Activity implements OnTouchListener {
StringBuilder builder = new StringBuilder();
TextView textView;
float[] x = new float[10];
float[] y = new float[10];
boolean[] touched = new boolean[10];
int[] id = new int[10];
private void updateTextView() {
builder.setLength(0);
for (int i = 0; i < 10; i++) {
builder.append(touched[i]);
builder.append(", ");
builder.append(id[i]);
builder.append(", ");
builder.append(x[i]);
builder.append(", ");
builder.append(y[i]);
builder.append("\n");
}
textView.setText(builder.toString());
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
textView = new TextView(this);
textView.setText("Touch and drag(multiple fingers supported!");
textView.setOnTouchListener(this);
setContentView(textView);
for (int i = 0; i < 10; i++) {
id[i] = -1;
}
updateTextView();
}
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK;
int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
int pointerCount = event.getPointerCount();
for (int i = 0; i < 10; i++) {
if (i >= pointerCount) {
touched[i] = false;
id[i] = -1;
continue;
}
if (event.getAction() != MotionEvent.ACTION_MOVE
&& i != pointerIndex) {
continue;
}
int pointerId = event.getPointerId(i);
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
touched[i] = true;
id[i] = pointerId;
x[i] = (int) event.getX(i);
y[i] = (int) event.getY(i);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_OUTSIDE:
case MotionEvent.ACTION_CANCEL:
touched[i] = false;
id[i] = -1;
x[i] = (int) event.getX(i);
y[i] = (int) event.getY(i);
break;
case MotionEvent.ACTION_MOVE:
touched[i] = true;
id[i] = pointerId;
x[i] = (int) event.getX(i);
y[i] = (int) event.getY(i);
break;
}
}
updateTextView();
return true;
}
}
/*Extract the index of the pointer that touch the sensor
Return the masked action being performed, without pointer index
information.
May be any of the actions: ACTION_DOWN, ACTION_MOVE, ACTION_UP,
ACTION_CANCEL, ACTION_POINTER_DOWN, or ACTION_POINTER_UP.
And return the index associated with pointer actions.*/
**int action = event.getAction() & MotionEvent.ACTION_MASK;**
/* Extract the index of the pointer that left the touch sensor
For ACTION_POINTER_DOWN or ACTION_POINTER_UP as returned by getActionMasked(),
this returns the associated pointer index. The index may be used with
getPointerId(int), getX(int), getY(int), getPressure(int), and getSize(int)
to get information about the pointer that has gone down or up.*/
**int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;**
For more details refer:
Link 1
Link 2