So I'm attempting to make a "magnetic poetry" type application. Users will move various Button widgets on the screen. I am using a Button widget since it is the closest to the look of the magnet, though I am open to other options!
The objects are not properly moving with my finger. They're close but they're not exactly in line with my finger. The X coordinate on my phone seems to be fine, but the Y corrdinate is off. Is this perhaps due to the title bar?
private final static int DRAGGING_OFF = 0;
private final static int DRAGGING_ON = 1;
private int dragStatus;
private GestureDetector mGestureDetector;
private int mOffsetX;
private int mOffsetY;
private LayoutParams mOldParams;
private RelativeLayout.LayoutParams lp;
#Override
public boolean onTouchEvent(MotionEvent event) {
if(!mGestureDetector.onTouchEvent(event)) {
if(event.getAction() == MotionEvent.ACTION_MOVE) {
if(dragStatus == DRAGGING_ON) {
Log.e(VIEW_LOG_TAG, "Dragging! RAW -- " + event.getRawX() + " : " + event.getRawY() + " NOT RAW -- " + event.getX() + " : " + event.getY());
int rawX, rawY;
int finalX, finalY;
rawX = (int) event.getRawX();
rawY = (int) event.getRawY();
finalX = rawX - mOffsetX;
finalY = rawY - mOffsetY;
lp.setMargins(finalX, finalY, 0, 0);
this.setLayoutParams(lp);
}
return true;
} else if(event.getAction() == MotionEvent.ACTION_UP) {
if(dragStatus == DRAGGING_ON) {
dragStatus = DRAGGING_OFF;
Log.e(VIEW_LOG_TAG, "Stopped dragging!");
}
return true;
} else {
return super.onTouchEvent(event);
}
} else {
return true;
}
}
private final GestureDetector.SimpleOnGestureListener mListener = new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onDown(MotionEvent e) {
int[] location = new int[2];
Log.e(VIEW_LOG_TAG, "Down! RAW -- " + e.getRawX() + " : " + e.getRawY() + " NOT RAW -- " + e.getX() + " : " + e.getY());
dragStatus = DRAGGING_ON;
// Sets the current location of the View in the int[] passed to it; x then y.
getLocationInWindow(location);
Log.e(VIEW_LOG_TAG, "Down location: " + location[0] + " " + location[1]);
mOffsetX = (int) e.getRawX() - location[0];
mOffsetY = (int) e.getRawY() - location[1];
mOldParams = getLayoutParams();
return true;
}
};
I think the issue is that you're not getting the DELTA of the current touch point Y and the cached, last touch point y. You need something like this:
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final TextView textView = (TextView) findViewById(R.id.text);
final ImageView image = (ImageView) findViewById(R.id.image);
matrix.setTranslate(1f, 1f);
image.setImageMatrix(matrix);
image.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
matrix.getValues(m); //copy matrix values into array
PointF currentXYTouchPoint = new PointF(event.getX(), event.getY());
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN: //start of pressed gesture
lastXYTouchPoint.set(event.getX(), event.getY()); //save the last touchpoint
mode = DRAG;
break;
case MotionEvent.ACTION_MOVE:
//calculate the change in finger position
float deltaX = currentXYTouchPoint.x - lastXYTouchPoint.x;
float deltaY = currentXYTouchPoint.y - lastXYTouchPoint.y;
matrix.postTranslate(deltaX, deltaY); //move the entire image by the deltas
image.setImageMatrix(matrix);
// save this last starting touchpoint
lastXYTouchPoint.set(currentXYTouchPoint.x, currentXYTouchPoint.y);
break;
}
textView.setText("TouchPoint started at " + currentXYTouchPoint.x + ", " + currentXYTouchPoint.y + " & the matrix is now " + Arrays.toString(m));
return true;
}
});
}
Adapt it to your own purposes, but the basic idea is there.
Related
I'm developing an Android application, I need to implement placing user signature(image) on pdf draging by user. I'm using pdf viewer(com.github.barteksc.pdfviewer.PDFView) to show pdf and I'm using drag and drop listener to get coordinates from view. but it is not placing in proper position on pdf. I spent lot of time on other solutions, but there is no help. (or please suggest any free SDK available in Android to achieve the same.)
Please help me resolve this. Here is my code sample.
public class MainActivity extends AppCompatActivity implements View.OnTouchListener, View.OnDragListener, OnPageChangeListener, OnPageScrollListener {
private PDFView pdfViewDemo;
private Button buttonGetPage;
private ImageView imageViewDemo;
private ImageView imageDrag;
private String pdfUrl = "/sdcard/sample.pdf";
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pdf_view);
findViewById(R.id.rootView).setOnDragListener(this);
pdfViewDemo = findViewById(R.id.pdfView);
final File file = new File(pdfUrl);
pdfViewDemo.setMaxZoom(0);
pdfViewDemo.fromFile(file)
.onPageChange(this)
.onPageScroll(this)
.spacing(10)
.swipeHorizontal(true)
.enableDoubletap(false)
.load();
//Implementation of Drag and Drop---------------------------------------------
imageDrag = findViewById(R.id.imageDrag);
imageDrag.setOnTouchListener(this);
//Implementation of Drag and Drop---------------------------------------------
imageViewDemo = findViewById(R.id.imageDemo);
buttonGetPage = findViewById(R.id.buttonGetPage);
buttonGetPage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ArrayList<Bitmap> bitmaps = pdfToBitmap(file);
pdfViewDemo.setVisibility(View.GONE);
imageViewDemo.setVisibility(View.VISIBLE);
imageViewDemo.setImageBitmap(bitmaps.get(0));
Log.e("test", "Bitmaps: " + bitmaps.size());
}
});
}
private ArrayList<Bitmap> pdfToBitmap(File pdfFile) {
ArrayList<Bitmap> bitmaps = new ArrayList<>();
try {
PdfRenderer renderer = new PdfRenderer(ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY));
Bitmap bitmap;
final int pageCount = renderer.getPageCount();
for (int i = 0; i < pageCount; i++) {
PdfRenderer.Page page = renderer.openPage(i);
int width = getResources().getDisplayMetrics().densityDpi / 72 * page.getWidth();
int height = getResources().getDisplayMetrics().densityDpi / 72 * page.getHeight();
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
bitmaps.add(bitmap);
// close the page
page.close();
}
// close the renderer
renderer.close();
} catch (Exception ex) {
ex.printStackTrace();
}
return bitmaps;
}
#Override
public void onPageChanged(int page, int pageCount) {
Log.e("test", "onPageChanged() called with: page = [" + page + "], pageCount = [" + pageCount + "]");
}
#Override
public void onPointerCaptureChanged(boolean hasCapture) {
Log.e("test", "onPointerCaptureChanged() called with: hasCapture = [" + hasCapture + "]");
}
#Override
public void onPageScrolled(int page, float positionOffset) {
Log.e("test", "onPageScrolled() called with: page = [" + page + "], positionOffset = [" + positionOffset + "]");
}
#Override
public boolean onTouch(View view, MotionEvent event) {
Log.e("test", "onTouch() called with: v = [" + view + "], event = [" + event + "]");
if (event.getAction() == MotionEvent.ACTION_DOWN) {
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
view.startDrag(null, shadowBuilder, view, 0);
return true;
} else {
return false;
}
}
#Override
public boolean onDrag(View v, DragEvent event) {
int action = event.getAction();
switch (action) {
case DragEvent.ACTION_DRAG_STARTED:
Log.e("test", "onDrag: ACTION_DRAG_STARTED");
break;
case DragEvent.ACTION_DRAG_ENTERED:
Log.e("test", "onDrag: ACTION_DRAG_ENTERED");
break;
case DragEvent.ACTION_DRAG_EXITED:
Log.e("test", "onDrag: ACTION_DRAG_EXITED");
break;
case DragEvent.ACTION_DROP:
Log.e("test", "onDrag: ACTION_DROP");
Log.e("test-", "X: " + (int) event.getX());
Log.e("test-", "Y: " + (int) event.getY());
getPdfCoordinates((int) event.getX(), (int) event.getY());
/*View tvState = (View) event.getLocalState();
val tvParent = tvState.parent as ViewGroup
tvParent.removeView(tvState)
val container = view as LinearLayout
container.addView(tvState)
tvParent.removeView(tvState)
tvState.x = dragEvent.x
tvState.y = dragEvent.y
view.addView(tvState)
view.setVisibility(View.VISIBLE)
int x = (int) v.getX();
int y = (int) v.getY();
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(x, y);
textTitle.setLayoutParams(layoutParams);*/
break;
case DragEvent.ACTION_DRAG_ENDED:
Log.e("test", "onDrag: ACTION_DRAG_ENDED" + v.getX() + ":" + v.getY());
imageDrag.setVisibility(View.VISIBLE);
break;
default:
break;
}
return true;
}
private void getPdfCoordinates(int x, int y) {
Log.e("test-", "PDF: getMeasuredWidth: " + pdfViewDemo.getMeasuredWidth());
Log.e("test-", "PDF: getWidth: " + pdfViewDemo.getWidth());
Log.e("test-", "PDF: getOptimalPageHeight: " + pdfViewDemo.getOptimalPageHeight());
Log.e("test-", "PDF: getOptimalPageWidth: " + pdfViewDemo.getOptimalPageWidth());
Log.e("test-", "PDF: getMeasuredWidthAndState: " + pdfViewDemo.getMeasuredWidthAndState());
Log.e("test-", "PDF: getMinimumHeight: " + pdfViewDemo.getMinimumHeight());
Log.e("test-", "PDF: getMinimumWidth: " + pdfViewDemo.getMinimumWidth());
x= (int) pdfViewDemo.getOptimalPageHeight()/2-x;
y=(int)pdfViewDemo.getOptimalPageWidth()/2-y;
addImageToPdf(x, y);
}
private void addImageToPdf(int x, int y) {
Log.e("test", "addImageToPdf() called with: x = [" + x + "], y = [" + y + "]" + pdfViewDemo.getCurrentPage());
try {
PdfReader reader = new PdfReader(pdfUrl);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("/sdcard/test_pdf.pdf"));
PdfContentByte content = stamper.getOverContent(pdfViewDemo.getCurrentPage()+1);
com.itextpdf.text.Image image = Image.getInstance("/sdcard/sign_1.jpg");
image.scaleAbsoluteHeight(50);
image.scaleAbsoluteWidth((image.getWidth() * 50) / image.getHeight());
image.setAbsolutePosition(y, x);
content.addImage(image);
stamper.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here are the screenshots of input and output
According to this answer, the coordinates of a given page can be anything and must be checked using the PdfReader.
There may also be a handful of other factors influencing the positioning.
PDF coordinate system may be scaled differently than androids.
PdfStamper may place stamp in an unexpected way (I could not find sufficient documentation) thus some testing is required to find out where exactly the stamp is placed for given coordinates.
The coordinates of the touch event which you are intercepting at the drop are absolute but should be relative to the position of the PdfView. This can be achieved getting the absolute position of the PdfView and subtracting it from the TouchEvent coordinates.
Just a few thoughts to help with your debugging.
I'm facing an issue on how to control Seekbar progress when user ONLY touching the Thumb
I knew it is a duplicated question but here are the links that gave me an idea about it this and this.
After several rounds of testing, below are my working logic result
mySeekbar.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Rect rcThumb = mySeekbar.getThumb().getBounds();
int iWidth = rcThumb.width();
if (event.getX() >= (rcThumb.left - iWidth) && event.getX() <= (rcThumb.right + iWidth)) {
return false;
} else
return true;
}
});
Expected result
no drag or tap
during drag or tap
Problem
You can just copy and paste the above code for testing. As we know that when touching or dragging the thumb will be larger, but there is an issue were thumb will be large when not touching it. This issue will not happen often but seldom. Anyway to solve this ? Much help is appreciated.
Problem result
no drag or tap
during drag or tap
After few rounds of testing, I was able to accomplish the result. Cheers :)
private boolean mIsDragging;
private boolean isWithinThumb(MotionEvent event, SeekBar seekBar) {
Rect rcThumb = seekBar.getThumb().getBounds();
Rect rcDetectTouchArea = new Rect();
int iWidth = rcThumb.width();
int iHeight = rcThumb.height();
rcDetectTouchArea.left = rcThumb.left - iWidth;
rcDetectTouchArea.right = rcThumb.right + iWidth;
rcDetectTouchArea.bottom = rcThumb.bottom + iHeight;
Log.i("TAG", "rcDetectSize.left = " + rcDetectTouchArea.left + " | rcDetectSize.right = " + rcDetectTouchArea.right + " | rcDetectSize.bottom = " + rcDetectTouchArea.bottom + " | event.getX()= " + event.getX() + " | event.getY()= " + event.getY() + " | rcThumb area = " + rcDetectTouchArea.contains((int) event.getX(), (int) event.getY()));
return rcDetectTouchArea.contains((int) event.getX(), (int) event.getY());
}
mSbTest.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (isWithinThumb(event, mSbTest)) {
mIsDragging = true;
return false;
}
case MotionEvent.ACTION_UP:
if (mIsDragging) {
mIsDragging = false;
return false;
}
if (isWithinThumb(event, mSbTest)) {
return false;
} else {
return true;
}
case MotionEvent.ACTION_MOVE:
if (!mIsDragging) {
return true;
}
}
return onTouchEvent(event);
}
});
So I have a view under my view, that I need to pass to the pinch to zoom. BUT, if the user double taps, than I do not want to pass the double tap to my second view. Because I need the functionality that is set on a double tap to be ignored.
The only problem is that that functionality is set to be called on 2 ACTION_DOWN events received from the touch listener.
Now I tried to make a logic to prevent from doubletapping to work, but make the pinch to zoom work, but it still isn't perfect. IF I tap with 2 fingers, 1 in 1 place of the screen, and then the other in another place, a bit further it will get it as a double tap, and not consume the Touch, as I need.
This is the code for my touchEventListener:
viewTop.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.i("","double touch event action: ===========================");
Log.i("","double touch event test action:" + event.getPointerId(0));
if(event.getPointerId(0) == 0) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (secondPressed) {
Log.i("", "double touch test : FIRST FINGER: CONSUMED TRUE");
timeLastTouch = System.currentTimeMillis();
return true;
}else {
Log.i("", "double touch DOWN : " + timeLastTouch + "... time passed: " + (System.currentTimeMillis() - timeLastTouch) + "..... location diff: " + (event.getX() - xLastTouch));
Log.i("", "double touch test XLAST : " + xLastTouch + "/" + yLastTouch + " ... XLAST 2 : " + xLastTouch2 + "/" + yLastTouch2);
if (System.currentTimeMillis() - timeLastTouch < 1000 && Math.abs(event.getX() - xLastTouch) < 150 && Math.abs(event.getY() - yLastTouch) < 150) {
Log.i("", "double touch test TRUE DOWN");
secondPressed = true;
timeLastTouch = System.currentTimeMillis();
xLastTouch = event.getX();
yLastTouch = event.getY();
return true;
} else if (System.currentTimeMillis() - timeLastTouch < 1000 && Math.abs(event.getX() - xLastTouch2) < 150 && Math.abs(event.getY() - yLastTouch2) < 150) {
Log.i("", "double touch test TRUE DOWN");
secondPressed = true;
timeLastTouch = System.currentTimeMillis();
return true;
} else {
timeLastTouch = System.currentTimeMillis();
if(xLastTouch2 == -1) {
xLastTouch2 = event.getX();
yLastTouch2 = event.getY();
}else {
xLastTouch = event.getX();
yLastTouch = event.getY();
}
Log.i("", "double touch test FALSE DOWN!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! X : " + event.getX() + "/" + event.getY() + ".... TIME: " + (System.currentTimeMillis() - timeLastTouch));
Log.i("", "double touch test FALSE DOWN!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DIFF LAST TOUCH: " + Math.abs(event.getX() - xLastTouch) + "/" + Math.abs(event.getY() - yLastTouch));
Log.i("", "double touch test FALSE DOWN!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DIFF LAST TOUCH2: " + Math.abs(event.getX() - xLastTouch2) + "/" + Math.abs(event.getY() - yLastTouch2));
return false;
}
}
} else if (event.getAction() == MotionEvent.ACTION_UP) {
handlerTouch.removeCallbacksAndMessages(null);
Log.i("", "double touch test FALSE UP");
timeLastTouch = System.currentTimeMillis();
handlerTouch.postDelayed(new Runnable() {
#Override
public void run() {
resetTouches();
Log.i("", "double touch test : SECOND PRESSED BECOMES FALSE");
}
}, 300);
return true;
} else {
timeLastTouch = System.currentTimeMillis();
xLastTouch = event.getX();
yLastTouch = event.getY();
Log.i("", "double touch ELSE FALSE");
return false;
}
}else if(event.getPointerId(0) == 1){
timeLastTouch = System.currentTimeMillis();
if(event.getAction() == MotionEvent.ACTION_DOWN) {
xLastTouch2 = event.getX();
yLastTouch2 = event.getY();
secondPressed = true;
return false;
}else if(event.getAction() == MotionEvent.ACTION_UP){
Log.i("","double touch test : SECONDARY FINGER: SECOND PRESSED BECOMES FALSE");
handlerTouch.postDelayed(new Runnable() {
#Override
public void run() {
resetTouches();
Log.i("", "double touch test : SECOND PRESSED BECOMES FALSE");
}
}, 300);
}else {
Log.i("","double touch test : SECONDARY FINGER: SECOND PRESSED BECOMES TRUE");
secondPressed = true;
}
return false;
}else {
timeLastTouch = System.currentTimeMillis();
secondPressed = true;
return false;
}
}
});
Where resetTouches is:
private void resetTouches() {
xLastTouch = -1f;
yLastTouch = -1f;
xLastTouch2 = -1f;
yLastTouch2 = -1f;
secondPressed = false;
}
Now I'm kinda blocked here, and don't know what or how to change in order to prevent the double tap to work. Is there by any change any implementation of this that might be easier? What could I change to improve on this?
This did it for me:
final ScaleGestureDetector mScaleDetector = new ScaleGestureDetector(InCallActivity.this, new ScaleGestureDetector.OnScaleGestureListener() {
#Override
public void onScaleEnd(ScaleGestureDetector detector) {
Log.i("", "double touch test2 onScaleEnd: " + detector.getScaleFactor());
app.TouchEvent(0, 1, (int) xFinger1, (int) yFinger1);
if (xFinger2 != 0) {
app.TouchEvent(1, 1, (int) xFinger2, (int) yFinger2);
} else scale(1, (int) (yFinger1));
}
#Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
Log.i("", "double touch test2 onScaleBegin: " + detector.getScaleFactor());
app.TouchEvent(0, 0, (int) xFinger1, (int) yFinger1);
if (xFinger2 != 0) {
app.TouchEvent(1, 0, (int) xFinger2, (int) yFinger2);
} else app.TouchEvent(1, 0, (int) xFinger1, (int) yFinger1);
return true;
}
#Override
public boolean onScale(ScaleGestureDetector detector) {
Log.i("", "double touch test2 zoom ongoing, scale: " + detector.getScaleFactor());
app.TouchEvent(0, 2, (int) xFinger1, (int) yFinger1);
if (xFinger2 != 0) {
app.TouchEvent(1, 2, (int) xFinger2, (int) yFinger2);
} else {
scaleValue = detector.getScaleFactor();
scale(2, (int) (yFinger1));
}
return false;
}
});
viewTop.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.i("", "double touch test2 ON TOUCH: " + event.getPointerId(0) + "x/y: " + event.getX() + "/" + event.getY());
xFinger1 = event.getX(0);
yFinger1 = event.getY(0);
try {
xFinger2 = event.getX(1);
yFinger2 = event.getY(1);
mScaleDetector.onTouchEvent(event);
} catch (Exception e) {
return logicFor1Finger(event, e);
}
return true;
}
});
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
I am trying to play two sound together when two button is touch together at the same time. I have button1 and button2, while button1 is touch, button2 wont play the sound. But when I put my finger off button1 then touching button2 plays the sound.
I have tried googling around but couldn't find an answer.
What I wanted to do is clear. Play two sound together when two buttons are touch together.
Below is my code so far.
public class MultitouchtestActivity extends MultiTouchActivity {
/** Called when the activity is first created. */
private Button btn1;
private Button btn2;
SoundPool soundPool;
AudioManager audioManager;
int soundId;
int kID, sID;
#Override
public void onCreate(Bundle savedInstanceState)
{
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
super.onCreate(savedInstanceState);
audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
setContentView(R.layout.main);
btn1 = (Button) findViewById(R.id.button1);
btn2 = (Button) findViewById(R.id.button2);
//the maximum number of simultaneous streams for this SoundPool object
int maxStreams = 4;
//the audio stream type as described in AudioManager
int streamType = AudioManager.STREAM_MUSIC;
//the sample-rate converter quality. Currently has no effect. Use 0 for the default.
int srcQuality = 0;
soundPool = new SoundPool(maxStreams, streamType, srcQuality);
soundPool.setOnLoadCompleteListener(soundPoolOnLoadCompleteListener);
soundId = soundPool.load(this, R.raw.c, 1);
kID = soundPool.load(this, R.raw.k, 1);
sID = soundPool.load(this, R.raw.s, 1);
btn1.setOnTouchListener(new View.OnTouchListener()
{
public boolean onTouch(View v, MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_DOWN)
{
float vol = audioManager.getStreamVolume(
AudioManager.STREAM_MUSIC);
float maxVol = audioManager.getStreamMaxVolume(
AudioManager.STREAM_MUSIC);
float leftVolume = vol/maxVol;
float rightVolume = vol/maxVol;
int priority = 1;
int no_loop = 0;
float normal_playback_rate = 1f;
soundPool.play(kID,
leftVolume,
rightVolume,
priority,
no_loop,
normal_playback_rate);
return true;
}
return false;
}
});
btn2.setOnTouchListener(new View.OnTouchListener()
{
public boolean onTouch(View v, MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_DOWN)
{
float vol = audioManager.getStreamVolume(
AudioManager.STREAM_MUSIC);
float maxVol = audioManager.getStreamMaxVolume(
AudioManager.STREAM_MUSIC);
float leftVolume = vol/maxVol;
float rightVolume = vol/maxVol;
int priority = 1;
int no_loop = 0;
float normal_playback_rate = 1f;
soundPool.play(sID,
leftVolume,
rightVolume,
priority,
no_loop,
normal_playback_rate);
return true;
}
return false;
}
});
}
SoundPool.OnLoadCompleteListener soundPoolOnLoadCompleteListener = new SoundPool.OnLoadCompleteListener()
{
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status)
{
if(status==0)
{
btn1.setEnabled(true);
btn2.setEnabled(true);
}
else
{
Toast.makeText(MultitouchtestActivity.this,"SoundPool.load() fail", Toast.LENGTH_LONG).show();
}
}
};
}
public class MultiTouchActivity extends Activity implements OnTouchListener {
private View parent;
public void onCreate(Bundle instance)
{
super.onCreate(instance);
parent = findViewById(android.R.id.content).getRootView();
parent.setOnTouchListener(this);
}
public boolean onTouch(View v, MotionEvent event) {
for (int ptrIndex = 0; ptrIndex < event.getPointerCount(); ptrIndex++) {
// index of the pointer which starts this Event
int actionPointerIndex = event.getActionIndex();
// resolve the action as a basic type (up, down or move)
int actionResolved = event.getAction() & MotionEvent.ACTION_MASK;
if (actionResolved < 7 && actionResolved > 4) {
actionResolved = actionResolved - 5;
}
if (actionResolved == MotionEvent.ACTION_MOVE) {
dealEvent(ptrIndex, event, v, actionResolved);
Log.v("tag", "move" + ptrIndex);
} else {
dealEvent(actionPointerIndex, event, v, actionResolved);
}
}
return false;
}
private void dealEvent(int actionPointerIndex, MotionEvent event,
View eventView, int actionresolved) {
int rawX, rawY;
int location[] = { 0, 0 };
eventView.getLocationOnScreen(location);
// Log.v("tag", location + "");
rawX = (int) event.getX(actionPointerIndex) + location[0];
rawY = (int) event.getY(actionPointerIndex) + location[1];
ArrayList<View> views = getTouchedViews(rawX, rawY, actionresolved);
// dumpEvent(event);
for (View view : views) {
int x, y;
view.getLocationOnScreen(location);
x = rawX - location[0];
y = rawY - location[1];
// Log.v("tag", "touched" + view.toString());
/*
* view.onTouchEvent(MotionEvent.obtain(event.getDownTime(),
* event.getEventTime(), event.getActionMasked(), x, y,
* event.getMetaState()));
*/
// MotionEvent me = MotionEvent.obtain(event);
MotionEvent me = MotionEvent.obtain(event.getDownTime(),
event.getEventTime(), actionresolved, x, y,
event.getPressure(actionPointerIndex),
event.getPressure(actionPointerIndex),
event.getMetaState(), event.getXPrecision(),
event.getYPrecision(), event.getDeviceId(),
event.getEdgeFlags());
me.setLocation(x, y);
// Log.v("tag", "oldeventid: " + event.getAction() + " #" +
// actionPointerIndex+ " id" + ptrId+ " resolved "+ actionResolved);
// Log.v("tag", "neweventid: " + me.getAction() + " #" +
// actionPointerIndex+ " id" + ptrId+ " resolved "+ actionResolved);
if (!me.equals(event)) {
/*
* Log.v("tag", "actionindex: " + actionPointerIndex +
* " resolved: " + actionPointerIndex + " to " + view.toString()
* + " y:" + view.getTop() + "-" + (view.getTop() +
* view.getHeight()));
*/
// me.setAction(actionresolved);
view.onTouchEvent(me);
}
if (actionresolved == MotionEvent.ACTION_MOVE) {
Log.v("tag",
"#" + actionPointerIndex + "Rawx:" + rawX + " rawy:"
+ rawY + "x:" + x + " y:" + y + " "
+ view.toString());
}
}
}
private ArrayList<View> getTouchedViews(int x, int y, int action) {
int moveGap = 0;
if (action == MotionEvent.ACTION_MOVE) {
moveGap = 0;
}
ArrayList<View> touchedViews = new ArrayList<View>();
ArrayList<View> possibleViews = new ArrayList<View>();
if (parent instanceof ViewGroup) {
possibleViews.add(parent);
for (int i = 0; i < possibleViews.size(); i++) {
View view = possibleViews.get(i);
int location[] = { 0, 0 };
view.getLocationOnScreen(location);
if (((view.getHeight() + location[1] + moveGap >= y)
& (view.getWidth() + location[0] + moveGap >= x)
& (view.getLeft() - moveGap <= x) & (view.getTop()
- moveGap <= y))
|| view instanceof FrameLayout) {
touchedViews.add(view);
possibleViews.addAll(getChildViews(view));
}
}
}
return touchedViews;
}
private ArrayList<View> getChildViews(View view) {
ArrayList<View> views = new ArrayList<View>();
if (view instanceof ViewGroup) {
ViewGroup v = ((ViewGroup) view);
if (v.getChildCount() > 0) {
for (int i = 0; i < v.getChildCount(); i++) {
views.add(v.getChildAt(i));
}
}
}
return views;
}
}