I have tried implementing a method to drag& drop a bitmap around on the screen. The method I tried worked when the card was an imageView and in the XML file, but I have changed my approach and I am just loading the bitmaps in to rects on the screen when the draw method is called.
Can anyone advise me the best way to implement dragging and dropping for bitmaps that are loaded on to the screen? Thanks in advance.
My Code: Play Screen Class:(Where bitmaps are loaded and drawn onto screen)
package com.example.llave_000.shootout.screens;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.view.View.OnTouchListener;
import com.example.llave_000.shootout.Game;
import com.example.llave_000.shootout.MoveGestureDetector;
import com.example.llave_000.shootout.R;
import com.example.llave_000.shootout.Settings.Settings;
import com.example.llave_000.shootout.engine.AssetStore;
import com.example.llave_000.shootout.engine.ElapsedTime;
import com.example.llave_000.shootout.engine.audio.Music;
import com.example.llave_000.shootout.engine.graphics.IGraphics2D;
import com.example.llave_000.shootout.engine.input.Input;
import com.example.llave_000.shootout.engine.input.TouchEvent;
import com.example.llave_000.shootout.world.GameObject;
import com.example.llave_000.shootout.world.GameScreen;
import com.example.llave_000.shootout.world.LayerViewport;
import com.example.llave_000.shootout.world.ScreenViewport;
import java.util.List;
import static com.example.llave_000.shootout.R.id.imageView;
public class PlayScreen extends GameScreen {
// /////////////////////////////////////////////////////////////////////////
// Properties
// /////////////////////////////////////////////////////////////////////////
private Rect backButtonBound;
private Rect hazardCardBound;
private Music screenClickMusic;
/**
* Width and height of the level
*/
// private final float LEVEL_WIDTH = 1000.0f;
//private final float LEVEL_HEIGHT = 1000.0f;
/**
* Define viewports for this layer and the associated screen projection
*/
private ScreenViewport mScreenViewport;
private LayerViewport mLayerViewport;
private Bitmap backgroundBitmap;
private Bitmap backButton;
private Bitmap PlayScreenTitle;
private Bitmap hazardCard;
private Rect frontLayerBound;
private Rect playScreenTitleBound;
private ImageView cardImage1;
private ViewGroup rootLayout;
private int _xDelta;
private int _yDelta;
public View view;
/**
* User input controls for managing the player and the game
*/
// protected InputControl pauseButton
// /////////////////////////////////////////////////////////////////////////
// Constructors
// /////////////////////////////////////////////////////////////////////////
/**
* Create a game
*
* @param game
* Game to which this screen belongs */
public PlayScreen(Game game) {
super("PlayScreen", game);
//Define the rects what will be used to 'hold' the images
int spacingX = game.getScreenWidth() / 8;
int spacingY = game.getScreenHeight() / 8;
int padding = spacingY / 10; //padding between each button
int line = 1; //each button is on a new 'line' (under each other)
// Load in the assets used by the demo
AssetStore assetManager = game.getAssetManager();
assetManager.loadAndAddBitmap("pitch", "img/pitch.png");
assetManager.loadAndAddBitmap("backButton", "img/back_button.png");
assetManager.loadAndAddBitmap("hazardCard", "img/hazard_card.jpg");
// Define Rectangles for Bitmaps
// playScreenTitleBound = new Rect(spacingX * 2, spacingY * 0, spacingX * 6, spacingY * 1);
this.backgroundBitmap = assetManager.getBitmap("pitch");
this.backButton = assetManager.getBitmap("backButton");
this.hazardCard = assetManager.getBitmap("hazardCard");
//load in sounds
assetManager.loadAndAddMusic("screenClickMusic", "music/buttonPress.mp3");
//initialise
this.screenClickMusic = assetManager.getMusic("screenClickMusic");
}
// /////////////////////////////////////////////////////////////////////////
// Support methods
// /////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////
// Update and Draw methods
// /////////////////////////////////////////////////////////////////////////
@Override
public void update(ElapsedTime elapsedTime) {
//process any touch events occurring since the update
Input input = game.getInput();
List<TouchEvent> touchEvents = input.getTouchEvents();
if (touchEvents.size() > 0) {
//Just check the first touch event that occurred in the frame.
//It means pressing the screen with several fingers may not
//trigger a 'button'.
TouchEvent touchEvent = touchEvents.get(0);
if (backButtonBound.contains((int) touchEvent.x, (int) touchEvent.y)
&& touchEvent.type == TouchEvent.TOUCH_UP) {
// If the play game area has been touched then swap screens
game.getScreenManager().removeScreen(this.getName());
MenuScreen menuScreen = new MenuScreen(game);
if (Settings.soundEnabled) {
screenClickMusic.play();
}
// As it's the only added screen it will become active.
game.getScreenManager().addScreen(menuScreen);
}
/*else if (hazardCardBound.contains((int) touchEvent.x, (int) touchEvent.y)
&& touchEvent.type == TouchEvent.TOUCH_DOWN) {
RelativeLayout.LayoutParams lparams = (RelativeLayout.LayoutParams) view.getLayoutParams();
_xDelta = X - lparams.leftMargin;
_yDelta = Y - lparams.topMargin;
}*/
}
}
@Override
public void draw(ElapsedTime elapsedTime, IGraphics2D graphics2D) {
// load hazard playing card
/*ImageView hazardCardImageView = (ImageView) view.findViewById(R.id.hazardCardImageView);
if (hazardCard != null) {
hazardCardImageView.setImageBitmap(hazardCard);
}
cardImage1 = (ImageView) rootLayout.findViewById(R.id.hazardCardImageView);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(500, 150);
cardImage1.setLayoutParams(layoutParams);
cardImage1.setOnTouchListener(new ChoiceTouchListener());*/
// Get and draw the bitmaps into the defined rectangles
Bitmap backButton = game.getAssetManager().getBitmap("backButton");
// Create the screen to black and define a clip based on the viewport
graphics2D.clear(Color.BLACK);
//graphics2D.clipRect(mScreenViewport.toRect());
// Define the rects what will be used to 'hold' the images
int spacingX = game.getScreenWidth() / 8;
int spacingY = game.getScreenHeight() / 8;
int padding = spacingY / 10; //padding between each button
int line = 1; //each button is on a new 'line' (under each other)
hazardCardBound = new Rect(spacingX, spacingY * 2 + padding, spacingX * 7, spacingY * 3);
if (frontLayerBound == null) {
frontLayerBound = new Rect(0, 0, graphics2D.getSurfaceWidth(),
graphics2D.getSurfaceHeight());
}
if (backButtonBound == null) {
int left = 10;
int bottom = (graphics2D.getSurfaceHeight() - 120);
backButtonBound = new Rect(left, bottom, left + 100, bottom + 120);
}
//cardImage1 = (ImageView)view.findViewById(R.id.hazardCardImageView);
/* RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(500, 150);
cardImage1.setLayoutParams(layoutParams);
cardImage1.setOnTouchListener(new ChoiceTouchListener());
cardImage1.setOnTouchListener(new ChoiceTouchListener());
cardImage1.setImageBitmap(hazardCard);*/
// RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(500, 150);
//draw bitmaps with relative bounds
graphics2D.drawBitmap(backgroundBitmap, null, frontLayerBound,null);
graphics2D.drawBitmap(backButton, null, backButtonBound, null);
graphics2D.drawBitmap(hazardCard,null, hazardCardBound, null);
// RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(500, 150);
// cardImage1.setLayoutParams(layoutParams);
// cardImage1.setImageBitmap(hazardCard);
//cardImage1.setOnTouchListener(new ChoiceTouchListener());
}
/* @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_play_screen, container, false);
FragmentManager fm = getFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.fragment_play_screen);
if (fragment == null) {
// Log.d("","@ PLAY SCREEN"); --logcat shows execution reaches this point
fragment = createFragment();
fm.beginTransaction().add(R.id.fragment_play_screen, fragment)
.commit();
}
AssetManager assetManager = getActivity().getAssets();
Bitmap backButton = loadBitmap(assetManager, "img/back_button.png");
ImageView backButtonimageView = (ImageView) view.findViewById(R.id.backButton);
if (backButton != null) {
backButtonimageView.setImageBitmap(backButton);
}
backButtonimageView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.d("BACK BUTTON CLICKED", "BACK BUTTON CLICKED");
FragmentTransaction transaction = getFragmentManager().beginTransaction();
//go back to main menu screen
transaction.replace(R.id.fragment_play_screen, new MenuScreen());
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
});
private Layer target;
}
class Layer {
Matrix matrix = new Matrix();
Matrix inverse = new Matrix();
RectF bounds;
View parent;
Bitmap bitmap;
MoveGestureDetector mgd;
public Layer(Context ctx, View p, Bitmap b) {
parent = p;
bitmap = b;
bounds = new RectF(0, 0, b.getWidth(), b.getHeight());
mgd = new MoveGestureDetector(ctx, mgl);
matrix.postTranslate(50 + (float) Math.random() * 50, 50 + (float) Math.random() * 50);
}
public boolean contains(MotionEvent event) {
matrix.invert(inverse);
float[] pts = {event.getX(), event.getY()};
inverse.mapPoints(pts);
if (!bounds.contains(pts[0], pts[1])) {
return false;
}
return Color.alpha(bitmap.getPixel((int) pts[0], (int) pts[1])) != 0;
}
public boolean onTouchEvent(MotionEvent event) {
mgd.onTouchEvent(event);
return true;
}
public void draw(Canvas canvas) {
canvas.drawBitmap(bitmap, matrix, null);
}
MoveGestureDetector.SimpleOnMoveGestureListener mgl = new MoveGestureDetector.SimpleOnMoveGestureListener() {
@Override
public boolean onMove(MoveGestureDetector detector) {
PointF delta = detector.getFocusDelta();
matrix.postTranslate(delta.x, delta.y);
parent.invalidate();
return true;
}
};
}
IGraphics2D Class:
/**
* The graphics 2D interface defines the set of graphical operations that can be
* applied to a render surface.
*
* @version 1.0
*/
public interface IGraphics2D {
/**
* Get the width of the render surface
*
* @return Width of the render surface
*/
public int getSurfaceWidth();
/**
* Get the height of the render surface
*
* @return Height of the render surface
*/
public int getSurfaceHeight();
/**
* Insert the specified rectangular clip region
*
* @param clipRegion
*/
public void clipRect(Rect clipRegion);
/**
* Set the surface colour to that specified colour (assumed to be in the
* same format as the Color class - ARGB).
*
* @param colour
* ARGB formatted colour
*/
public void clear(int colour);
/**
* Draw the specified text string
*
* @param text
* String of text to be rendered
* @param x
* Location of text on x-axis
* @param y
* Location of text on y-axis
* @param paint
* Paint parameters controlling text render format
*/
public void drawText(String text, float x, float y, Paint paint);
/**
* Draw the specified bitmap
*
* @param bitmap
* Bitmap to be rendered
* @param srcRect
* Source region to be rendered (if null full source is rendered)
* @param desRect
* Destination region for the render
* @param paint
* Paint parameters controlling how the bitmap is rendered
*/
public void drawBitmap(Bitmap bitmap, Rect srcRect, Rect desRect,
Paint paint);
/**
* Draw the specified bitmap
*
* @param bitmap
* Bitmap to be rendered
* @param matrix
* Matrix defining bitmap scaling, rotation, translation, etc.
* @param paint
* Paint parameters controlling how the bitmap is rendered
*/
public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint);
}
Edit: The method that worked was using this:
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(500, 150);
cardImage.setLayoutParams(layoutParams);
cardImage.setOnTouchListener(new ChoiceTouchListener());
//load hazard playing card
Bitmap hazardCard = loadBitmap(assetManager, "img/hazard_card.jpg");
ImageView hazardCardimageView = (ImageView) view.findViewById(R.id.hazardCardImageView);
if (hazardCard != null) {
hazardCardimageView.setImageBitmap(hazardCard);
}
private final class ChoiceTouchListener implements View.OnTouchListener {
public boolean onTouch(View view, MotionEvent event) {
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams lparams = (RelativeLayout.LayoutParams) view.getLayoutParams();
_xDelta = X - lparams.leftMargin;
_yDelta = Y - lparams.topMargin;
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
layoutParams.leftMargin = X - _xDelta;
layoutParams.topMargin = Y - _yDelta;
layoutParams.rightMargin = 0b11111111111111111111111100000110;
layoutParams.bottomMargin = 0b11111111111111111111111100000110;
view.setLayoutParams(layoutParams);
break;
}
rootLayout.invalidate();
return true;
}
}
Main Activity class: package com.example.llave_000.shootout;
import android.app.Activity;
import android.app.FragmentManager;
import android.graphics.PointF;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import com.example.llave_000.shootout.world.DemoGame;
import com.example.llave_000.shootout.BaseGestureDetector;
import com.example.llave_000.shootout.MoveGestureDetector;
import android.widget.ImageView;
public class MainActivity extends Activity implements View.OnTouchListener {
private float mScaleFactor = 1.0f;
private float mRotationDegrees = 0.f;
private float mFocusX = 0.f;
private float mFocusY = 0.f;
private ImageView cardImage1;
private ViewGroup rootLayout;
public View view;
private MoveGestureDetector mMoveDetector;
private ScaleGestureDetector mScaleDetector;
/* private RotationGestureDetector mRotateDetector;
private MoveGestureDetector mMoveDetector;*/
/**
* Game fragment instance
*/
private Game mGame;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//ImageView hazardCardImageView = (ImageView) view.findViewById(R.id.hazardCardImageView);
cardImage1 = (ImageView)findViewById(R.id.hazardCardImageView);
// Setup Gesture Detectors
mMoveDetector = new MoveGestureDetector(getApplicationContext(), new MoveListener());
//mScaleDetector = new ScaleGestureDetector(getApplicationContext(), new ScaleListener());
/*mRotateDetector = new RotationGestureDetector(getApplicationContext(), new RotateListener());
mMoveDetector = new MoveGestureDetector(getApplicationContext(), new MoveListener());*/
// Setup the window as suitable for a game, namely: full screen
// with no title and a request to keep the screen on. The changes
// are made before any content is inflated.
Window window = getWindow();
window.requestFeature(Window.FEATURE_NO_TITLE);
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// Set the content view to use a simple frame layout
setContentView(R.layout.activity_main);
// Add in the main game fragment..
FragmentManager fm = getFragmentManager();
// MenuScreen menuScreen = (MenuScreen)fm.findFragmentById(R.id.activity_main_id);
mGame = (Game)fm.findFragmentById(R.id.activity_main_id);
if (mGame == null) {
mGame = new DemoGame(); //not sure if correct
fm.beginTransaction().add(R.id.activity_main_id, mGame)
.commit();
}
// Add in the main game fragment
/* if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.activity_main_id, new MenuScreen()).commit();
}*/
}
public boolean onTouch(View view, MotionEvent event) {
mScaleDetector.onTouchEvent(event);
mMoveDetector.onTouchEvent(event);
/* mRotateDetector.onTouchEvent(event);
mMoveDetector.onTouchEvent(event);
*/
// Mmmmmhhhagic!!!
// with: mScaleFactor, mRotationDegrees, mFocusX and mFocusY
return true; // indicate event was handled
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor(); // scale change since previous event
return true;
}
}
/* private class RotateListener extends RotateGestureDetector.SimpleOnRotateGestureListener {
@Override
public boolean onRotate(RotateGestureDetector detector) {
mRotationDegrees -= detector.getRotationDegreesDelta();
return true;
}
}
*/
private class MoveListener extends MoveGestureDetector.SimpleOnMoveGestureListener {
@Override
public boolean onMove(MoveGestureDetector detector) {
PointF d = detector.getFocusDelta();
mFocusX += d.x;
mFocusY += d.y;
return true;
}
}
@Override
public void onBackPressed() {
// If the fragment does not consume the back event then
// trigger the default behaviour
if(!mGame.onBackPressed())
super.onBackPressed();
}
/* public boolean onTouchEvent(MotionEvent me) {
if (me.getAction() == MotionEvent.ACTION_DOWN) {
//code in here to take me to new screen with match attax background
//with new screen displaying a card. then work on being able to move that card.
//playButtonY -= 20;
}*/
// playButton.setY(playButtonY);
//code in here to take me to new screen with match attax background
//with new screen displaying a card. then work on being able to move that card.
//return true;
}
..