Thomas
Thomas

Reputation: 385

ClassCastException on custom SurfaceView

i've got a big problem since a few days: When I try to bind the surfaceview on the layout and my custom surfaceview, i get a ClassCastException from my custom surfaceview.

here is my code:

public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);
     waveform =(WaveFormView) findViewById(R.id.surfaceView1);
}
class WaveFormView extends SurfaceView implements SurfaceHolder.Callback {        
    public WaveFormView(Context context, AttributeSet attrs) {
        super(context, attrs);
        getHolder().addCallback(this);
        _dthread = new DrawingThread(getHolder(), this);
        setFocusable(true);
        paintP.setStyle(Paint.Style.STROKE);
        paintP.setStrokeWidth(1);
        paintP.setColor(Color.WHITE);
        paintT.setStyle(Paint.Style.STROKE);
        paintT.setStrokeWidth(1);
        paintT.setColor(Color.WHITE);
    }

    @Override
    public void onDraw(Canvas canvas) {
        canvas.drawColor(Color.BLACK);
        for (int i=0;i<_athread.buffer.length-pas;i+=pas){
            canvas.drawLine(i, 150-_athread.buffer[i], i+pas, 150-_athread.buffer[i+pas], paintP);
        }
        canvas.drawText("FPS:  " + String.valueOf(FPS), 0, 10, paintT);
        //canvas.drawText("tmp:  " + tmp, 0, 20, paintT);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        _dthread.setRunning(true);
        _dthread.start();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // simply copied from sample application LunarLander:
        // we have to tell thread to shut down & wait for it to finish, or else
        // it might touch the Surface after we return and explode
        boolean retry = true;
        _dthread.setRunning(false);
        while (retry) {
            try {
                _dthread.join();
                retry = false;
            } catch (InterruptedException e) {
                // we will try it again and again...
            }
        }
    }
}

class DrawingThread extends Thread {
    private SurfaceHolder _surfaceHolder;
    private WaveFormView _waveformview;
    private boolean _run = false;

    public DrawingThread(SurfaceHolder surfaceHolder, WaveFormView waveformview) {
        _surfaceHolder = surfaceHolder;
        _waveformview = waveformview;
    }

    public void setRunning(boolean run) {
        _run = run;
    }

    public SurfaceHolder getSurfaceHolder() {
        return _surfaceHolder;
    }

    @Override
    public void run() {
        Canvas c;
        long startMs=System.currentTimeMillis();
        int frameCounter=0;
        while (_run) {
            c = null;
            frameCounter++;
            if (System.currentTimeMillis()-startMs>1000){
                startMs = System.currentTimeMillis();
                FPS = frameCounter;
                frameCounter=0;
            }
            try {
                c = _surfaceHolder.lockCanvas(null);
                synchronized (_surfaceHolder) {
                    _waveformview.onDraw(c);
                }
            } finally {
                // do this in a finally so that if an exception is thrown
                // during the above, we don't leave the Surface in an
                // inconsistent state
                if (c != null) {
                    _surfaceHolder.unlockCanvasAndPost(c);
                }
            }
        }
    }
}

When I replace:

setContentView(R.layout.main);

with this:

setContentView(new WaveFormView (this));

...it works perfectly ! But, I need to have buttons besides.

here is the layout:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
    <LinearLayout android:layout_weight="1" android:padding="0dip" android:layout_height="match_parent" android:layout_width="match_parent" android:orientation="vertical" android:id="@+id/content">
         <TextView android:layout_height="wrap_content" android:id="@+id/tvdebug" android:text="Debug" android:layout_width="wrap_content"></TextView>
         <SurfaceView android:id="@+id/surfaceView1" android:layout_height="fill_parent" android:layout_width="fill_parent"></SurfaceView>
</LinearLayout>

If someone have the solution it would me a lot !

Upvotes: 1

Views: 1966

Answers (1)

MByD
MByD

Reputation: 137332

Maybe R.id.surfaceView1 is not declared as WaveFormView but as SurfaceView? Try declare it specifically, otherwise this is illegal casting indeed.

WaveFormView is a SurfaceView, but a SurfaceView is not necessarily a WaveFormView.

You can use your own view in the layout xml, by specifying the class name (<path.to.WaveFormView instead of <SurfaceView...)

For example:

<view class = "com.mypath.WaveFormView" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:id="@+id/surfaceView1"
    android:layout_above="@id/auto_scrollview"
/>

OR

<com.mypath.WaveFormView
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:id="@+id/surfaceView1"
    android:layout_above="@id/auto_scrollview"
/>

If this class is an inner class, as seemed from your question, then use:

<com.mypath.OUTERCLASSNAME$WaveFormView

EDIT

Since this class is needed to be shown from outside your class, and be loaded not from instance but statically, you need to public static to its declaration, e.g.:

public static class WaveFormView extends SurfaceView implements SurfaceHolder.Callback

Upvotes: 7

Related Questions