Setting image background in SurfaceView, getting black screen

13,229

First, you should implement SurfaceHolder.Callback interface with your MapView class and set it as a callback for its SurfaceHolder to make the app call your onSurfaceCreated() metod. Second, if you want your onDraw() method to be called, then call setWillNotDraw(false) in your MapView's constructor.

I've done that as following:

public class MapView extends SurfaceView implements SurfaceHolder.Callback {

    private Bitmap scaled;

    public MapView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setWillNotDraw(false);
        getHolder().addCallback(this);
    }

    public void onDraw(Canvas canvas) {
        canvas.drawBitmap(scaled, 0, 0, null); // draw the background
    }

    @Override
    public void surfaceCreated(SurfaceHolder arg0) {
        Bitmap background = BitmapFactory.decodeResource(getResources(), R.drawable.dr);
        float scale = (float) background.getHeight() / (float) getHeight();
        int newWidth = Math.round(background.getWidth() / scale);
        int newHeight = Math.round(background.getHeight() / scale);
        scaled = Bitmap.createScaledBitmap(background, newWidth, newHeight, true);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // TODO Callback method contents
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Callback method contents
    }
}

And it works well. NOTE: Moved MapView class to a separate *.java file. Update Watch Duplicate Copy Move

Share:
13,229
Hallow
Author by

Hallow

Updated on June 04, 2022

Comments

  • Hallow
    Hallow almost 2 years

    Okay so Im trying to set the background of a SurfaceView to a JPG file. But it doesn't seem to want to draw the image, and all I get is a black screen.

    Here:s my code:

        public class FloorplanActivity extends Activity{
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MapView mapView = new MapView(getApplicationContext());
        setContentView(mapView);
    
    
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.floorplan, menu);
        return true;
    }
    
    class MapView extends SurfaceView{
    
        Rect testRectangle1 = new Rect(0, 0, 50, 50);
        Bitmap scaled;
        int x;
        int y;
    
        public MapView(Context context) {
            super(context);
    
        }
    
        public void surfaceCreated(SurfaceHolder arg0){
            Bitmap background = BitmapFactory.decodeResource(getResources(), R.drawable.floorplan);
            float scale = (float)background.getHeight()/(float)getHeight();
            int newWidth = Math.round(background.getWidth()/scale);
            int newHeight = Math.round(background.getHeight()/scale);
            scaled = Bitmap.createScaledBitmap(background, newWidth, newHeight, true);
        }
    
     public void onDraw(Canvas canvas) {
            canvas.drawBitmap(scaled, 0, 0, null); // draw the background
        }
    

    Not sure why it won't draw the "floorplan" image I have saved in the drawable-mdpi folder.

    Anyone got any suggestions?

    Thanks.

    EDIT: After doing some debugging with breakpoints, it seems like the "scaled" variable becomes "Infinity" for some reason and as such the newWidth and newHeight variables become less than 0 and the application crashes.

    This is only if I move the entire surfaceCreated into the contstructor, if I leave the code as is here then it doesn't do anything beyind displaying a black screen.

    No idea what's causing it to do that though...

  • Alastair
    Alastair almost 11 years
    While this is old, THANKS. I've been smashing my head on this exact same problem for too long now.
  • Braj
    Braj over 10 years
    If u want to draw something on this surfaceview with background, u hv to remove call to setWillNotDraw(false) else u whatever u draw, wont be visible
  • fadden
    fadden over 9 years
    Bear in mind that SurfaceView has two parts, the Surface and the View. The Surface is a separate layer that is composited behind the layer with all the Views, so normally the SurfaceView's View is just a transparent window that the layout code uses to figure out where the Surface should peek through. If you override onDraw(), you're rendering on the View; if you fill the View with opaque pixels, then there's no reason to be using a SurfaceView at all (just create a custom View).