I have an image overlaid on top of a Camera Preview. The camera preview starts inside a FrameLayout on click of a button. The image is also overlaid on the camera preview on click of another button.
Here goes the code below --
MainActivity:
public class MainActivity extends AppCompatActivity {
public Camera mCamera;
public CameraPreview mCameraPreView;
Bitmap bitmap;
FrameLayout frameLayout;
DrawOnTop drawOnTop;
FrameLayout.LayoutParams layoutParams;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
frameLayout = (FrameLayout)findViewById(R.id.camera_preview);
drawOnTop = null;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void onCamViewButtonClicked (View view)
{
mCamera = getCameraInstance();
mCameraPreView = new CameraPreview(this,mCamera);
frameLayout.addView(mCameraPreView);
}
public Camera getCameraInstance()
{
Camera camera = null;
try
{
camera = Camera.open();
}
catch(Exception e)
{
e.printStackTrace();
}
return camera;
}
public void onOverlayImageButtonClicked(View view)
{
if(mCameraPreView == null)
{
Toast.makeText(getApplicationContext(),"Preview is not available now!",Toast.LENGTH_LONG).show();
return;
}
else {
if(drawOnTop != null)
{
frameLayout.removeView(drawOnTop);
drawOnTop = null;
}
else
{
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.internetothings);
drawOnTop = new DrawOnTop(this, bitmap);
layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT);
layoutParams.gravity = Gravity.CENTER_HORIZONTAL;
frameLayout.addView(drawOnTop, layoutParams);
Toast.makeText(getApplicationContext(),"Click again to remove!",Toast.LENGTH_LONG).show();
}
}
}
}
CameraPreview.java:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder surfaceHolder;
private android.hardware.Camera camera;
public CameraPreview (Context context, android.hardware.Camera cam)
{
super(context);
camera = cam;
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
}
public void surfaceCreated(SurfaceHolder holder)
{
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
public void surfaceDestroyed(SurfaceHolder holder)
{
camera.stopPreview();
camera.release();
camera = null;
}
public void surfaceChanged(SurfaceHolder holder,int format,int w,int h)
{
if(surfaceHolder.getSurface() == null)
{
return;
}
camera.stopPreview();
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
DrawOnTop.java:
public class DrawOnTop extends View {
Bitmap bitmap;
private int mActivePointerId = 9999;
public static float mLastTouchX,mLastTouchY,mPosX,mPosY;
ImageView view = null;
public DrawOnTop (Context context, Bitmap bmp)
{
super(context);
bitmap = bmp;
}
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.drawBitmap(bitmap, canvas.getWidth() / 2, canvas.getHeight() / 2, null);
}
}
I have used the below code for dragging, but this is getting fired even if I touch the camera preview, which I don't want.
public boolean onTouchEvent(MotionEvent event)
{
int action = event.getActionMasked();
switch (action)
{
case MotionEvent.ACTION_DOWN:
{
int pointerIndex = event.getActionIndex();
final float x = MotionEventCompat.getX(event, pointerIndex);
final float y = MotionEventCompat.getY(event, pointerIndex);
mLastTouchX = x;
mLastTouchY = y;
mActivePointerId = event.getPointerId(pointerIndex);
break;
}
case MotionEvent.ACTION_MOVE:
{
final int pointerIndex =
MotionEventCompat.findPointerIndex(event, mActivePointerId);
final float x = MotionEventCompat.getX(event, pointerIndex);
final float y = MotionEventCompat.getY(event, pointerIndex);
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mPosX += dx;
mPosY += dy;
invalidate();
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_UP:
{
mActivePointerId = 9999;
break;
}
case MotionEvent.ACTION_CANCEL:
{
mActivePointerId = 9999;
break;
}
case MotionEvent.ACTION_POINTER_UP:
{
final int pointerIndex = MotionEventCompat.getActionIndex(event);
final int pointerId = MotionEventCompat.getPointerId(event, pointerIndex);
if (pointerId == mActivePointerId) {
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = MotionEventCompat.getX(event, newPointerIndex);
mLastTouchY = MotionEventCompat.getY(event, newPointerIndex);
mActivePointerId = MotionEventCompat.getPointerId(event, newPointerIndex);
}
break;
}
}
return true;
}
My question is: How to drag this particular image on touching it? Touching the camera preview should do nothing, only by touching the image I should be able to drag it.
Thanks in advance!
After several trials and banging my head, finally I got this issue fixed and working! I am able to drag the image over the Camera Preview. :)
Now I am not going to use DrawOnTop.java. Instead of that, I have created an ImageView under the FrameLayout and populating that same ImageView with the required image. Then I have added OnTouchListener on the ImageView.
Here goes the code below --
public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
public Camera mCamera;
public CameraPreview mCameraPreView;
FrameLayout frameLayout;
ImageView imageView;
float mLastTouchX,mLastTouchY,mPosX,mPosY;
Boolean clicked;
Bitmap bitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
frameLayout = (FrameLayout)findViewById(R.id.camera_preview);
imageView = new ImageView(this);
ActionBar.LayoutParams layoutParams = new ActionBar.LayoutParams(ActionBar.LayoutParams.WRAP_CONTENT,ActionBar.LayoutParams.WRAP_CONTENT);
layoutParams.gravity = Gravity.CENTER_HORIZONTAL;
imageView.setLayoutParams(layoutParams);
clicked = false;
}
public void onCamViewButtonClicked (View view)
{
mCamera = getCameraInstance();
mCameraPreView = new CameraPreview(this,mCamera);
frameLayout.addView(mCameraPreView);
}
public Camera getCameraInstance()
{
Camera camera = null;
try
{
camera = Camera.open();
}
catch(Exception e)
{
e.printStackTrace();
}
return camera;
}
public void onOverlayImageButtonClicked(View view)
{
if(mCameraPreView == null)
{
Toast.makeText(getApplicationContext(),"Preview is not available now!",Toast.LENGTH_LONG).show();
return;
}
else
{
if(clicked)
{
imageView.setImageDrawable(null);
clicked = false;
}
else
{
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.internetothings);
imageView.setImageBitmap(bitmap);
frameLayout.addView(imageView);
Toast.makeText(getApplicationContext(),"Click again to remove!",Toast.LENGTH_LONG).show();
imageView.setOnTouchListener(this);
clicked = true;
}
}
}
public boolean onTouch(View view, MotionEvent event)
{
switch (event.getAction()){
case MotionEvent.ACTION_DOWN: {
final float x = event.getX();
final float y = event.getY();
// Remember where we started
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_MOVE: {
final float x = event.getX();
final float y = event.getY();
// Calculate the distance moved
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
// Move the object
mPosX += dx;
mPosY += dy;
// Remember this touch position for the next move event
mLastTouchX = x;
mLastTouchY = y;
imageView.setTranslationX(mPosX);
imageView.setTranslationY(mPosY);
break;
}
default:
break;
}
return true;
}
}