I am working on some example in which i want to drag the image corresponding to touch in Android. Does anybody have an idea about how I can do it?
public class TouchBall extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int w=getWindowManager().getDefaultDisplay().getWidth()-25;
int h=getWindowManager().getDefaultDisplay().getHeight()-25;
BallView ballView=new BallView(this,w,h);
setContentView(ballView);
}
}
public class BallView extends SurfaceView implements SurfaceHolder.Callback {
private Bitmap bitmap ;
private MyThread thread;
private int x=20,y=20;int width,height;
public BallView(Context context,int w,int h) {
super(context);
width=w;
height=h;
thread=new MyThread(getHolder(),this);
getHolder().addCallback(this);
setFocusable(true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
bitmap =BitmapFactory.decodeResource(getResources(), R.drawable.ball_green);
canvas.drawColor(Color.BLUE);//To make background
canvas.drawBitmap(bitmap,x-(bitmap.getWidth()/2),y-(bitmap.getHeight()/2),null);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
x=(int)event.getX();
y=(int)event.getY();
if(x<25)
x=25;
if(x> width)
x=width;
if(y <25)
y=25;
if(y > 405)
y=405;
return true;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
// TODO Auto-generated method stub
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
thread.startrun(true);
thread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
thread.startrun(false);
thread.stop();
}
}
thread:
public class MyThread extends Thread {
private SurfaceHolder msurfaceHolder;
private BallView mballView;
private boolean mrun =false;
public MyThread(SurfaceHolder holder, BallView ballView) {
msurfaceHolder = holder;
mballView=ballView;
}
public void startrun(boolean run) {
mrun=run;
}
@Override
public void run() {
super.run();
Canvas canvas;
while (mrun) {
canvas=null;
try {
canvas = msurfaceHolder.lockCanvas(null);
synchronized (msurfaceHolder) {
mballView.onDraw(canvas);
}
} finally {
if (canvas != null) {
msurfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
As a slight modification to the TouchBall answer - if you really don't have a game loop - in other words, the only changes to the screen are directly due to user input - then it might make more sense to leave out the thread. Otherwise it is just constantly looping and redrawing even if nothing has changed. So:
public class TouchBall extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int w=getWindowManager().getDefaultDisplay().getWidth()-25;
int h=getWindowManager().getDefaultDisplay().getHeight()-25;
BallView ballView=new BallView(this,w,h);
setContentView(ballView);
}
}
public class BallView extends SurfaceView implements SurfaceHolder.Callback {
private Bitmap bitmap ;
private int x=20,y=20;int width,height;
public BallView(Context context,int w,int h) {
super(context);
width=w;
height=h;
getHolder().addCallback(this);
setFocusable(true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
bitmap =BitmapFactory.decodeResource(getResources(), R.drawable.ball_green);
canvas.drawColor(Color.BLUE);//To make background
canvas.drawBitmap(bitmap,x-(bitmap.getWidth()/2),y-(bitmap.getHeight()/2),null);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
x=(int)event.getX();
y=(int)event.getY();
if(x<25)
x=25;
if(x> width)
x=width;
if(y <25)
y=25;
if(y > 405)
y=405;
updateBall();
return true;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
// TODO Auto-generated method stub
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
private void updateBall() {
Canvas canvas = null;
try {
canvas = getHolder().lockCanvas(null);
synchronized (getHolder()) {
this.onDraw(canvas);
}
}
finally {
if (canvas != null) {
getHolder().unlockCanvasAndPost(canvas);
}
}
}
}
Admittedly, I am new to Android development, so I may be missing something here.
Quiet simple solution in Kotlin. Does not check if the ImageView is moving outta its parent view or even the whole screen. This code must be placed inside a class that extends AppCompatImageView
private var xStart = 0
private var yStart = 0
private var leftStart = 0
private var topStart = 0
private var isDragging = false
@SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(event: MotionEvent?): Boolean {
requireNotNull(event)
when(event.action) {
MotionEvent.ACTION_DOWN -> {
xStart = event.rawX.toInt()
yStart = event.rawY.toInt()
topStart = top
leftStart = left
isDragging = true
}
MotionEvent.ACTION_MOVE -> {
if(isDragging) {
val deltaX = event.rawX.toInt() - xStart
val deltaY = event.rawY.toInt() - yStart
left = leftStart + deltaX
top = topStart + deltaY
}
}
MotionEvent.ACTION_UP -> {
isDragging = false
}
}
return true
}
Here is an example for ConstraintLayout:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="@+id/objecttodrag"
android:layout_width="250dp"
android:layout_height="250dp"
android:src="@drawable/image"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintVertical_bias="0.5"/>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
package com.kevin.dragdrop;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import android.os.Bundle;
import android.view.DragEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.objecttodrag);}
float x, y;
float dx, dy;
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
x = event.getX();
y = event.getY();}
if (event.getAction() == MotionEvent.ACTION_MOVE) {
dx = event.getX() - x;
dy = event.getY() - y;
imageView.setX(imageView.getX() + dx);
imageView.setY(imageView.getY() + dy);
x = event.getX();
y = event.getY();}
return super.onTouchEvent(event);
} }
Credits:
Special thanks to 'chandan k' for the code.
© 2022 - 2024 — McMap. All rights reserved.
SurfaceView
you can try to follow my tutorial part. droidnova.com/playing-with-graphics-in-android-part-vi,209.html In this part, I introduce you on how you can add and change the position on the SurfaceView while moving the touch. The part after that is a short game that implements all learned stuff in a short game. I think that should help you and show you how to do this... – Floribunda