Многослойные SurfaceViews в FrameLayout в Android - PullRequest
6 голосов
/ 11 февраля 2011

Я пытаюсь создать приложение с дополненной реальностью для Android и столкнулся с проблемой наслоения поверхностей. Мне нужен вид поверхности для отображения предварительного просмотра камеры, на который я буду накладывать графику, и мне нужен вид поверхности для рисования моей графики. Эта вторая поверхность также должна быть нарисована над предварительным просмотром камеры, но иметь прозрачный фон. В моей текущей реализации оба вида поверхности работают и отображаются так, как они должны, но фон не прозрачен, и поэтому нет второго вида поверхности, когда нарисованная графика накладывается на вид поверхности предварительного просмотра камеры. Как это могло быть достигнуто? При поиске многочисленных вопросов переполнения стека, а также на других форумах я натолкнулся на множество противоречивых мнений по этому вопросу. Некоторые говорят, что наложение слоев в Android невозможно, в то время как другие говорят, что это вопрос использования другого макета (FrameLayout и LinearLayout?). В частности, моя реализация включает в себя два представления: класс, CustomCameraView, который расширяет SurfaceView, и класс CustomDrawView, который также расширяет SurfaceView, содержащийся в FrameLayout, с CustomDrawView, появляющимся после CustomCameraView. Как они могут быть наслоены так, что CustomDrawView кажется наложенным на CustomCameraView?

Ответы [ 2 ]

9 голосов
/ 16 февраля 2011

Я думаю, что многие люди пробовали это. Google Enginee четко заявил ( здесь ), что вам следует избегать укладки Surface Views. Даже если кто-то нашел какой-то трюк для этого, он, вероятно, несовместим и приведет к проблемам.

Я думаю, что это дает три варианта, в зависимости от ваших требований:

  • Вид сверху на поверхность

Используйте вид поверхности для предварительного просмотра камеры и накладывайте поверх него вид. Недостатком этого подхода является то, что рисование в «нормальных» представлениях а) медленнее, а б) происходит в потоке пользовательского интерфейса. Вы можете обойти б), если вы реализуете потоки самостоятельно. Но, в общем, это, вероятно, тот путь, если ваши оверлеи содержат что-то вроде элементов пользовательского интерфейса или несколько Drawables, которые не нужно обновлять слишком часто.

  • Делать все в SurfaceView

Это даст вам лучшую производительность и меньше накладных расходов во время выполнения. У вас есть только один SurfaceView. Скомпонуйте оверлеи на вашем SurfaceView и нарисуйте там все. Конечно, вы можете комбинировать оба подхода.

  • Делайте все в GLSurfaceView

Это, вероятно, путь к реальной производительности. Как и выше, но с визуализацией вида камеры в текстуру OpenGL в GLSurfaceView .

2 голосов
/ 11 февраля 2011

Я получил эту работу, имея 2 прозрачных вида над SurfaceView камеры, используя следующий подход:

Моя деятельность настраивает все свои представления в методе onCreate(), я не использую для этого никакого файла макета. Это выглядит следующим образом:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(null); //savedInstanceState);

    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

    cameraPreview = new CameraPreview(this);
    addContentView(cameraPreview, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

    animationView = new AnimationView(this);
    addContentView(animationView, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

    crosslinesView = new CrosslinesView(this);
    addContentView(crosslinesView, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
}

cameraPreview относится к типу SurfaceView, animationView и crosslinesViews относятся к типу View. onDraw() из двух последних представлений выглядит следующим образом:

protected void onDraw(Canvas canvas) {
    // Have the view being transparent
    canvas.drawARGB(0, 0, 0, 0);
    // Your drawing code goes here
    // ...
}

Удачи!

...