自定义SurfaceView上的ClassCastException

时间:2011-05-07 21:11:41

标签: android surfaceview classcastexception

几天后我遇到了一个大问题: 当我尝试在布局和我的自定义surfaceview上绑定surfaceview时,我从自定义surfaceview获得了ClassCastException。

这是我的代码:

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

当我替换:

  

的setContentView(R.layout.main);

用这个:

  

setContentView(new WaveFormView(this));

......它完美无缺!  但是,我需要有按钮。

这是布局:

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

如果有人有解决方案,我会帮助很多!

1 个答案:

答案 0 :(得分:7)

可能R.id.surfaceView1未声明为WaveFormView,而是SurfaceView?尝试专门声明它,否则这是非法的投射。

WaveFormViewSurfaceView,但SurfaceView不一定是WaveFormView

您可以在布局xml中使用自己的视图,方法是指定类名(<path.to.WaveFormView而不是<SurfaceView...

例如:

<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"
/>

如果这个类是一个内部类,如你的问题所示,那么使用:

<com.mypath.OUTERCLASSNAME$WaveFormView

修改

由于需要从类外部显示此类,并且不是从实例加载而是静态加载,因此需要public static声明它,例如:

public static class WaveFormView extends SurfaceView implements SurfaceHolder.Callback