android - 如何将现有的全屏面板放入普通 Activity 的 SurfaceView 元素中

标签 android android-canvas panel surfaceview

我有一个以全屏模式显示 map 的 map Activity :

public class MapActivity extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(new Panel(this));
}

public class Panel extends SurfaceView implements SurfaceHolder.Callback {

public Panel(Context context) {
        super(context);
        getHolder().addCallback(this);

        // initiate new thread for drawing
        _thread = new CanvasThread(getHolder(), this);
}

// start thread 
@Override
public void surfaceCreated(SurfaceHolder holder) {
        CanvasThread.setRunning(true);
        _thread.start();
}

// start drawing objects on canvas
@Override
public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
     /* several canvas operations ...
     */
}

// Thread specific class
static class CanvasThread extends Thread {
    private SurfaceHolder _surfaceHolder;
    private Panel _panel;
    private static boolean _run = false;

    public CanvasThread(SurfaceHolder surfaceHolder, Panel panel) {
        _surfaceHolder = surfaceHolder;
        _panel = panel;
    }

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

    @Override
    public void run() {
        Canvas c;
        Log.d("Thread", "start");
        while (_run) {
            c = null;
            try {
                c = _surfaceHolder.lockCanvas(null);
                synchronized (_surfaceHolder) {
                    Log.d("Thread", "Canvas c init");
                    _panel.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);
                }
            }
        }
    }
}
}

现在,我想使用相同的类在 SurfaceView 元素内的其他 Activity 中显示我的 map 。因此,我尝试在新的 Activity 中获取 SurfaceView 元素,如下所示:

....
Panel surface = new KarteActivity().new Panel(this);
    surface._thread.start();
    CanvasThread.setRunning(true);
    LinearLayout midLL = new LinearLayout(this);

    midLL.findViewById(R.id.surfaceView1);
    midLL.addView(surface);

这会导致空指针异常,因为 Canvas 为空。在全屏模式下我没有错误。 我的错误是什么?

解决此类问题的常用方法是什么?

最佳答案

好的,最后我自己得到了答案 :) 这是解决方案:

  1. 包含SurfaceView元素的activity必须交出SurfaceHolder

    SurfaceView surface = (SurfaceView) findViewById(R.id.surfaceView1);
    SurfaceHolder surfaceHolder = surface.getHolder();
    Panel panel = new Panel(this,surfaceHolder);
    
  2. Surface 类必须在其构造函数中初始化 Surface,线程将在创建 Surface 时启动。

    public class Panel extends SurfaceView implements SurfaceHolder.Callback {
    
    public Panel(Context context, SurfaceHolder surfaceHolder) {
        super(context);
        surfaceHolder.addCallback(this);
    }
    
    // start thread 
    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        // initiate new thread for drawing
        _thread = new CanvasThread(surfaceHolder, this);
        _thread.setRunning(true);
        _thread.start();
    }
    
    // start drawing objects on canvas
    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
     /* several canvas operations ...
     */
    }
    
    // Thread specific class
    class CanvasThread extends Thread {
        private SurfaceHolder _surfaceHolder;
        private Panel _panel;
        private boolean _run = false;
    
        public CanvasThread(SurfaceHolder surfaceHolder, Panel panel) {
            _surfaceHolder = surfaceHolder;
            _panel = panel;
        }
    
        public void setRunning(boolean run) {
            _run = run;
        }
    
        @Override
        public void run() {
            Canvas c;
            Log.d("Thread", "start");
            while (_run) {
                c = null;
                try {
                    c = _surfaceHolder.lockCanvas(null);
                    synchronized (_surfaceHolder) {
                        Log.d("Thread", "Canvas c init");
                        _panel.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);
                    }
                }
            }
        }
    }
    }
    

这对我有用,但我决定将 Panel 类与 MapActivity 类分开(在我的问题中显示)

关于android - 如何将现有的全屏面板放入普通 Activity 的 SurfaceView 元素中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13544377/

相关文章:

android - 如何复制此 UI 模式 : click ListView item and expand below it?

java - 用于计算 mfcc vector 的库

android - 来自 Canvas.setBitmap(Bitmap) 的 UnsupportedException

android - 使用 Canvas 将圆圈转换为环形?

html - 如何正确设置面板的最小高度和最大高度并 overflow hidden 的任何内容?

ruby-on-rails - Ruby on Rails 虚拟主机控制面板/服务器管理

javascript - 当我点击其他地方时如何隐藏我的滑动sidenav?

java - 按字母顺序对 ListView 的元素进行排序

Android - 图像变形效果

gwt - 在 GWT 2.1.1 中使用 RootLayoutPanel 时完全禁用浏览器级别的滚动条,如何重新启用它们?