Search code examples
androidandroid-custom-view

Issue with CustomView


I am creating an application. If the custom View goes off the screen, a method is called. Here is my code for the custom View.

     public class CustomView extends View {
    private boolean bubbleOver;
    private static final int BITMAP_SIZE = 64;
    private static final int REFRESH_RATE = 40;
    private final Paint mPainter = new Paint();
    private ScheduledFuture<?> mMoverFuture;
    private int mScaledBitmapWidth;
    private Bitmap mScaledBitmap;
    // location, speed and direction of the bubble
    private float mXPos, mYPos, mDx, mDy, mRadius, mRadiusSquared;
    private long mRotate, mDRotate;

    CustomView (Context context, float x, float y) {
        super (context);
        // Create a new random number generator to randomize size, rotation, speed and direction
        Random r = new Random ();
        // Creates the bubble bitmap for this BubbleView
        createScaledBitmap (r);
        // Radius of the Bitmap
        mRadius = mScaledBitmapWidth / 2;
        mRadiusSquared = mRadius * mRadius;
        // Adjust position to center the bubble under user's finger
        mXPos = x - mRadius;
        mYPos = y - mRadius;
        // Set the BubbleView's speed and direction
        setSpeedAndDirection(r);
        // Set the BubbleView's rotation
        setRotation(r);
        mPainter.setAntiAlias(true);
    }

    private void setRotation(Random r) {
        if (speedMode == RANDOM) {
            // TODO - set rotation in range [1..3]
            mDRotate = r.nextInt (3) + 1;
        } else {
            mDRotate = 0;
        }
    }

    private void setSpeedAndDirection(Random r) {
        // Used by test cases
        switch (speedMode) {
            case SINGLE:
                mDx = 20;
                mDy = 20;
                break;
            case STILL:
                // No speed
                mDx = 0;
                mDy = 0;
                break;
            default:
                // Limit movement speed in the x and y direction to [-3..3] pixels per movement.
                mDx = r.nextFloat() * 6.0f - 3.0f;
                mDy = r.nextFloat() * 6.0f - 3.0f;
        }
    }

    private void createScaledBitmap (Random r) {
        if (speedMode != RANDOM) {
            mScaledBitmapWidth = BITMAP_SIZE * 3;
        } else {
            mScaledBitmapWidth = (r.nextInt(3) + 1) * BITMAP_SIZE;
        }
        mScaledBitmap = Bitmap.createScaledBitmap(mBitmap, mScaledBitmapWidth, mScaledBitmapWidth, true);
    }


    // Start moving the BubbleView & updating the display
    private void start () {
        // Creates a WorkerThread
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
        // Execute the run() in Worker Thread every REFRESH_RATE milliseconds. Save reference to this job in mMoverFuture
        mMoverFuture = executor.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {

                if (moveWhileOnScreen()) {
                    stop (false);
                } else {
                    BubbleView.this.postInvalidate();
                }
            }
        }, 0, REFRESH_RATE, TimeUnit.MILLISECONDS);

    }

    // Returns true if the BubbleView intersects position (x,y)
    private synchronized boolean intersects(float x, float y) {
        // TODO - Return true if the BubbleView intersects position (x,y)
        if ((mXPos <= x) && (x <= mXPos + mScaledBitmapWidth) && (mYPos <= y) && (y <= mYPos + mScaledBitmapWidth)) {
            return true;
        }
        return false;
    }

    // Cancel the Bubble's movement. Remove Bubble from mFrame.
    // Play pop sound if the BubbleView was popped
    private void stop (final boolean wasPopped) {
        if (null != mMoverFuture && !mMoverFuture.isDone()) {
            mMoverFuture.cancel(true);
        }
        // This work will be performed on the UI Thread
        mFrame.post(new Runnable() {
            @Override
            public void run() {
                mFrame.removeView(BubbleView.this);
                if (wasPopped) {
                    mSoundPool.play(mSoundID, mStreamVolume, mStreamVolume, 1, 0, 1f);
                }
            }
        });
    }

    // Change the Bubble's speed and direction
    private synchronized void deflect(float velocityX, float velocityY) {
        mDx = velocityX / REFRESH_RATE;
        mDy = velocityY / REFRESH_RATE;
    }

    // Draw the Bubble at its current location
    @Override
    protected synchronized void onDraw(Canvas canvas) {
        canvas.save();
        mRotate += mDRotate;
        canvas.rotate(mRotate, mXPos + (mScaledBitmapWidth / 2), mYPos + (mScaledBitmapWidth / 2));
        canvas.drawBitmap(mScaledBitmap, mXPos, mYPos, mPainter);
        canvas.restore();
    }

    // Returns true if the BubbleView is still on the screen after the move operation
    private synchronized boolean moveWhileOnScreen() {
        mXPos += mDx;
        mYPos += mDy;
        return isOutOfView();
    }

    // Return true if the BubbleView is off the screen after the move operation
    private boolean isOutOfView() {
        if ((mXPos + mDisplayWidth < 0) || (mYPos + mDisplayHeight < 0) || (mXPos> mDisplayWidth) || (mYPos > mDisplayHeight)) {
            loseGame();
            return true;
        }
        return false;
    }
}

When the View goes off the screen, loseGame() is not called. Only if another CustomView is created, loseGame() is called.


Solution

  • You have wrong sum to check, try with mScaledBitmapWidth not the mDisplayWidth.

    if ((mXPos + mScaledBitmapWidth < 0) 
        || (mYPos + mScaledBitmapWidth < 0)
        || (mXPos> mDisplayWidth)
        || (mYPos > mDisplayHeight)
    {
        loseGame();
        return true;
    }