Android 用の拡張現実アプリケーションを構築しようとしていますが、サーフェス ビューのレイヤー化の問題に遭遇しました。グラフィックをオーバーレイするカメラ プレビューを表示するためのサーフェス ビューと、グラフィックを描画するためのサーフェス ビューが必要です。この 2 番目のサーフェスもカメラ プレビューの上に描画する必要がありますが、背景は透明です。私の現在の実装では、両方のサーフェス ビューが動作し、想定どおりに表示されていますが、背景が透明ではないため、カメラ プレビュー サーフェス ビューに重ねて描画されたグラフィックスを含む 2 番目のサーフェス ビューは表示されません。これはどのように達成できますか?多数のスタック オーバーフローの質問や他のフォーラムを検索すると、この問題に関して多くの矛盾する意見に出会いました。Android でサーフェス ビューをレイヤー化することは不可能だと言う人もいれば、別のレイアウトを使用することの問題だと言う人もいます (FrameLayout と LinearLayout?) 具体的には、私の実装には、SurfaceView を拡張するクラス、CustomCameraView、およびクラスの 2 つのビューが含まれます。 、CustomDrawView も FrameLayout に含まれる SurfaceView を拡張し、CustomDrawView は CustomCameraView の後に表示されます。CustomDrawView が CustomCameraView に重なっているように見えるように、これらをどのように階層化できますか? また、FrameLayout に含まれる SurfaceView を拡張し、CustomDrawView を CustomCameraView の後に表示します。CustomDrawView が CustomCameraView に重なっているように見えるように、これらをどのように階層化できますか? また、FrameLayout に含まれる SurfaceView を拡張し、CustomDrawView を CustomCameraView の後に表示します。CustomDrawView が CustomCameraView に重なっているように見えるように、これらをどのように階層化できますか?
2 に答える
多くの人がこれを試したと思います。Google Engineeは(ここで)SurfaceViewsのスタックを避けるべきであると明確に述べました。誰かがそれを行うためのトリックを見つけたとしても、それはおそらく互換性がなく、問題につながるでしょう。
要件に応じて、これには3つのオプションがあると思います。
- サーフェスビューの上部に表示
カメラプレビューにサーフェスビューを使用し、その上にビューをスタックします。このアプローチの欠点は、「通常の」ビューでの描画がa)遅く、b)UIスレッドで行われることです。スレッドを自分で実装する場合は、b)を回避できます。ただし、一般的に、オーバーレイにUI要素や、頻繁に更新する必要のないいくつかのDrawableのようなものが含まれている場合は、これがおそらく最適な方法です。
- SurfaceViewですべてを行う
これにより、実行時のパフォーマンスが向上し、オーバーヘッドが減少します。SurfaceViewは1つだけです。SurfaceViewにオーバーレイを合成し、そこにすべてを描画します。もちろん、両方のアプローチを組み合わせることができます。
- GLSurfaceViewですべてを行う
これはおそらく実際のパフォーマンスを実現するための方法です。上記と同様ですが、 GLSurfaceViewのOpenGLテクスチャへのカメラビューレンダリングを使用します。
次のアプローチを使用して、カメラのSurfaceViewの上に2つの透明なビューを作成して、これを機能させました。
私のアクティビティはメソッド内のすべてのビューを設定します。その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()
の 2 つのビューは次のようになります。
protected void onDraw(Canvas canvas) {
// Have the view being transparent
canvas.drawARGB(0, 0, 0, 0);
// Your drawing code goes here
// ...
}
幸運を!