javaandroidandroid-canvasandroid-framelayoutandroid-viewgroup

SubClass of FrameLayout Class doesn't redraw canvas screens?


When I am using FrameLayout Class(GameView) to use addView(object) so that I can use ontouchlistener() but it only draws Rocket and shooter (classes used to draw , all are called in GameView ) but it didn't reDraws it (refer summary at bottom)

GameView.java

//Package and Imports
public class GameView extends FrameLayout implements View.OnTouchListener {

    public GameView(Context context, AttributeSet attrs) {
        super(context,attrs);
        mContext = context;
        startTime = (int)(SystemClock.elapsedRealtime());
        cannon = new shooter(Color.BLUE,mContext); bullets = new ArrayList<> ();            explosions =new ArrayList<>(); item = new Rocket( Color.RED,mContext);
addView(item);
        addView(cannon);
        cannon.setOnTouchListener(this);
        for (int i = 0; i < bullets.size(); i++) {
            addView(bullets.get(i));
            bullets.get(i).setOnTouchListener(this);
        }
    }
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            for (int i = bullets.size() - 1; i >= 0; i--) {
                if (//if bullet is touched) {
                    if (bullets.size() > 0) {
                        bullets.subList(i, bullets.size()).clear();
                    } } }
            if (//if cannon is touched)) {
                cannon.move();
            }
        }
        return true;
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int time = (int)(SystemClock.elapsedRealtime() - startTime);
        drawGameBoard(canvas);
        if((time/6000)%2==0) // Code to alter cannon color at every 6000 sec which also didn't work
{    
  if(cannon.paint.getColor()!=Color.BLUE) {
                cannon.paint.setColor(Color.BLUE);
                cannon.invalidate();
            }
        }
        else {
            if(cannon.paint.getColor()!=Color.RED) {
                cannon.paint.setColor(Color.RED);
                cannon.invalidate();
            }
        }
        invalidate();
    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        width = w;
        height = h;

        cannon.setBounds(0,0,width,height);
        item.setBounds(0,0,width,height);
        for (int i = 0; i < bullets.size(); i++ ) {
            bullets.get(i).setBounds(0,0,width,height);
        }

    }

    public void drawGameBoard(Canvas canvas) {


        cannon.draw(canvas);
        for (int i = bullets.size() - 1; i >= 0; i--) {
            if (bullets.get(i) != null) {
                bullets.get(i).draw(canvas);

                if (!bullets.get(i).move()) {
                    bullets.remove(i);
                }
            }
        }


        for (int i = explosions.size() - 1; i >= 0; i--) {
            if (explosions.get(i) != null) {
                if (!explosions.get(i).draw(canvas)) {
                    explosions.remove(i);
                }
            }
        }

        if (item!= null) {
            item.draw(canvas);
            RectF guyRect = item.getRect();
            for (int i = bullets.size() - 1; i >= 0; i--) {
                if (RectF.intersects(guyRect, bullets.get(i).getRect())) {
                    explosions.add(new Blast(Color.RED,mContext, item.getX(), item.getY()));
                    item.reset();
                    bullets.remove(i);
                    break;
                }
            }

            if (!item.move()) {
                item = null;
            }
        }
    }
    // Whenever the user shoots a bullet, create a new bullet moving upwards
    public void shootCannon() {

        bullets.add(new Goliyaan(cannon.paint.getColor() ,mContext, cannon.getPosition(), (float) (height-100)));

    }
}

Shooter(cannon) Class use to draw a cannon at bottom<-- only this is drawn (works)

//package and imports
public class shooter extends View  {
   //declared variables as used
    public shooter(int color, Context c) {
        super(c);
       //initialized paint objects
    }
    public void setBounds(int lx, int ly, int ux, int uy) {
        lowerX = lx;
        lowerY = ly;
        upperX = ux;
        upperY = uy;

    }
    public void move() {
       //moves cannon 
        invalidate();
    }
    public float getPosition()
    {
        return shootPoint;
    }
    public int shooterY(){ return (int)top;}
    public void draw(Canvas canvas)
    {
        super.draw(canvas);
    //draws a cannon(drawRect and circle)
    }
}

SameWay Goliyaan(Bullets) class extends view
/* Actually in hindi spoken language goliyaan means bullet*/

package and import
public class Goliyaan extends View {
//DECLARED VARIABLES AS USED
    // Constructor
    public Goliyaan(int color, Context c, float startx, float starty) {
        super(c);
        //INITIALIZed
    }

 //Here is some less important functions like setbounds,getters and rect(use for collision detection)
    public boolean move() {
        // Get new (x,y) position
        y -= stepY;
        if (y - radius < 0) {
            return false;
        }
        else
            return true;
    }

    // draw the bullet on the canvas
    public void draw(Canvas canvas) {
        super.draw(canvas);

        canvas.drawCircle(x, y, radius, paint);
    }
}

Might You Need Rocket(item) class

//Package and Imports
public class Rocket extends View

// INITIALIZED VARIABLES HERE AS USED
        // Constructor
        public Rocket(int color, Context c) {
            super(c);
            mContext = c;
            // create a bitmap from the supplied image 
            aliens = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(c.getResources(),
                    R.drawable.rocket),dst,dst, false);

        }

        public void setBounds(int lx, int ly, int ux, int uy) {
            lowerX = lx;
            lowerY = ly;
            upperX = ux;
            upperY = uy;

            x = (float) ((upperX-50)*Math.random());
            y = 0;
        }

        public boolean move() {
            // Get new (x,y) position. Movement is always in vertical direction downwards
            y += stepY;

            if (y + 50 > upperY) {
               reset();
                return true;
            }
            else
                return true;
        }


        public void reset() {
            x = (float) ((upperX-50)*Math.random());
            y = 0;
        }

        // Returns the rectangle enclosing the Rocket. Used for collision detection
        public RectF getRect() {
            return new RectF(x,y,x+50,y+50);
        }

        // HERE IS getX() and getY() Function

        public void draw(Canvas canvas) {
super.draw(canvas);
            canvas.drawBitmap(aliens, x, y, null);
        }
    }

Summary

  1. I have GameView Class(Custom View) that draws a cannon , bullets , item and explosions(Blast class)
  2. But after extending FrameLayout class (earlier view class) to use addView and ontouchlistener only it draws but doesn't move means didn't invalidate() it
  3. Before that all was drawn and moves, when I extended View class and didn't used addView(..)
  4. Also, i didn't need addView(items) but when I remove it , it didn't draw Rocket
  5. Feel free to Ignore but If you can please help me

Solution

  • you need to call setWillNotDraw(false) in the constructor of your FrameLayout otherwise its onDraw won't be called.