0

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;
    }

..

Liam
  • 429
  • 1
  • 13
  • 33
  • see http://stackoverflow.com/a/21657145/2252830 – pskink Apr 19 '17 at 11:13
  • I tried to follow some of the answers, mainly one that used a Layer Class and Viewport class but a lot of errors occurred.. – Liam Apr 19 '17 at 11:37
  • a lot of errors? – pskink Apr 19 '17 at 11:39
  • @psink, I implemented the ViewPort class. First two errors after importing necessary packages: "cannot resolve symbol layer0" and "cannot resolve symbol MoveGestureDetector".. Same with RotateGestureDetector. I struggled to follow that answer with regards to my specific game. I have only began working with android so not familiar with this stuff. I understand drawing bitmaps & the rects associated with them in order to get them on the screen but after that not so much.. – Liam Apr 19 '17 at 11:54
  • my answer started with: `"with the help of android-gesture-detectors https://github.com/pskink/android-gesture-detectors [...]"` so did you get `android-gesture-detectors`? of course you dont have to use them in your code but reading my code you will know how it works – pskink Apr 19 '17 at 12:11
  • I honestly tried to understand the code you put on that thread & read about the gesture detectors. But I have to idea how to implement that so I can click and drag bitmaps about on my game – Liam Apr 19 '17 at 14:49
  • so you need to check `MoveGestureDetector` - it is used for moving / dragging whatever you call it, there are two others: `ScaleGestureDetector` - for zooming / scaling and `RotateGestureDetector` - for bitmap rotating – pskink Apr 19 '17 at 14:51
  • Ok I implemnted MoveGestureDetector along with the BaseGestureDetector class. I updated my main activity - now included in the main post. How do I know link this to my playScreen class and enable the moveGestureDetector on my bitmap(hazardCard) that is loading to the screen? Thanks! – Liam Apr 19 '17 at 15:19
  • just see how / where `mgd.onTouchEvent(event);` is called in my code – pskink Apr 19 '17 at 15:25
  • Your answer starts with a viewPort class then a Layer class.. Do I need them? confused how I link this to my playScreen class.. – Liam Apr 19 '17 at 15:37
  • no, you just need detector and matrix – pskink Apr 19 '17 at 15:42
  • updated my play screen class with the detector & matrix(i think).. - Image does not drag. When you say see where mgd.onTouchEvent(event); is called, can you point me to where this is? – Liam Apr 19 '17 at 15:53

0 Answers0