自定义 SurfaceView 上的 ClassCastException

发布于 2024-11-05 16:55:30 字数 4526 浏览 3 评论 0 原文

几天来我遇到了一个大问题: 当我尝试在布局和自定义 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>

如果有人有解决方案,我会很高兴!

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 !

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

清音悠歌 2024-11-12 16:55:30

也许R.id.surfaceView1没有声明为WaveFormView而是声明为SurfaceView?尝试明确声明它,否则这确实是非法铸造。

WaveFormView 是一个 SurfaceView,但 SurfaceView 不一定是 WaveFormView

您可以通过指定类名称( 而不是 )在布局 xml 中使用自己的视图,

例如:

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

或者

<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< /code> 到其声明,例如:

public static class WaveFormView extends SurfaceView implements SurfaceHolder.Callback

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文