web-dev-qa-db-ja.com

Android SDK-camera2-TextureViewの上に長方形を描く

Android開発に不慣れです。camera2apiで良い例を見つけるのは難しいです。

私はほとんどの問題をゆっくりと処理していますが、これについては行き詰まっています。デフォルトのカメラでは、画面にタッチしてフォーカスすると、フォーカスエリアの長方形が一瞬表示されます。私は似たようなことをしたいです(またはこの場合、それを理解するために、最初はまったく同じことを行います)。

カメラのプレビューとして使用されている間、textureviewに描画できないとどこかで読みました(SDKドキュメントのTextureViewページだと思います)。lockメソッドを呼び出すと、キャンバスではなくnullが返されます。

私はこれをオンラインで見つけました: https://github.com/commonsguy/vidtry/ しかし、私はそれを動作させることができません。メインビューをドローアブルビューにキャストできない、またはその逆のエラーが発生する-または、ドローアブルビューが上部にあり、画面が黒くなる-または、下部にあり、タッチイベントに応答しない(強制しようとしない)上のビューからのperformClickはクラッシュを引き起こします。)

動かなくなった!誰かがイベントの位置に数秒かけて長方形を描く方法の説明や例を教えてもらえますか?

ありがとう!

14
aescript
  1. まず、camera2 api Androidの例には、オープンソースのgoogleサンプルコードがあります。 https://github.com/googlesamples/Android-Camera2Basic
  2. 次に、長方形を描画したい部分(タッチしてフォーカスする)について、次の手順に従います-
    • SurfaceViewを拡張するカスタムクラスを作成します。
    • このカスタムクラスでonTouchListenerメソッドを呼び出して、指の座標を検出し、AndroidのPaintクラスを使用して長方形を描画します。 -このカスタムクラスを、camera2からのプレビューを表示しているTextureViewの上に追加します。
    • カスタムビューを透明にします。
    • デバイス画面のある時点でタッチすると、onTouchListenerが呼び出され、カメラプレビューの上に追加したカスタムビューのキャンバスに描画されます。
    • 最後に、一度に1つの四角形しか必要ないため、カスタムビューに長方形を追加し続けないようにキャンバスをクリアします。
    • また、しばらくタッチしないと、長方形が消えるはずです。カスタムビューのハンドラーを使用してこれを行います。

これを行うためのテスト済みコードをいくつか提供します。お役に立てば幸いです。ベストオブラック。

 private class CustomView extends SurfaceView {

    private final Paint paint;
    private final SurfaceHolder mHolder;
    private final Context context;

    public CustomView(Camera2BasicFragment context) {
        super(context.getActivity().getBaseContext());
        mHolder = getHolder();
        mHolder.setFormat(PixelFormat.TRANSPARENT);
        this.context = context.getActivity().getBaseContext();
        Paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        Paint.setColor(Color.WHITE);
        Paint.setStyle(Paint.Style.STROKE);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            invalidate();
            if (mHolder.getSurface().isValid()) {
                final Canvas canvas = mHolder.lockCanvas();
                Log.d("touch", "touchReceived by camera");
                if (canvas != null) {
                    Log.d("touch", "touchReceived CANVAS STILL Not Null");
                    canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
                    canvas.drawColor(Color.TRANSPARENT);
                    canvas.drawCircle(event.getX(), event.getY(), 100, Paint);
                    mHolder.unlockCanvasAndPost(canvas);
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            Canvas canvas1 = mHolder.lockCanvas();
                            if(canvas1 !=null){
                                canvas1.drawColor(0, PorterDuff.Mode.CLEAR);
                                mHolder.unlockCanvasAndPost(canvas1);
                            }

                        }
                    }, 1000);

                }
                mHolder.unlockCanvasAndPost(canvas);
            }
        }

        return false;
    }
}
6
Sahil Deswal

完全なコードを探している人のために、このサンプルコードはカメラプレビューの上に小さな長方形を描画します。表面ビューを追加して、Camera2BasicFragmentプロジェクトのonViewCreated関数を変更するだけです。

public class Camera2BasicFragment extends Fragment
        implements View.OnClickListener, ActivityCompat.OnRequestPermissionsResultCallback {

    SurfaceView surfaceView;

    @Override
    public void onViewCreated(final View view, Bundle savedInstanceState) {
        view.findViewById(R.id.picture).setOnClickListener(this);
        view.findViewById(R.id.info).setOnClickListener(this);
        mTextureView = (AutoFitTextureView) view.findViewById(R.id.texture);

        surfaceView = (SurfaceView) view.findViewById(R.id.surfaceView);
        surfaceView.setZOrderOnTop(true);
        SurfaceHolder mHolder = surfaceView.getHolder();
        mHolder.setFormat(PixelFormat.TRANSPARENT);
        mHolder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                Canvas canvas = holder.lockCanvas();
                if (canvas == null) {
                    Log.e(TAG, "Cannot draw onto the canvas as it's null");
                } else {
                    Paint myPaint = new Paint();
                    myPaint.setColor(Color.rgb(100, 20, 50));
                    myPaint.setStrokeWidth(10);
                    myPaint.setStyle(Paint.Style.STROKE);
                    canvas.drawRect(100, 100, 200, 200, myPaint);

                    holder.unlockCanvasAndPost(canvas);
                }
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {

            }
        });
    }

そして、fragment_camera2_basic.xmlファイルには追加の表面ビューがあります

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent">

        <com.example.Android.camera2basic.AutoFitTextureView
            Android:id="@+id/texture"
            Android:layout_width="wrap_content"
            Android:layout_height="wrap_content"
            Android:layout_alignParentStart="true"
            Android:layout_alignParentTop="true" />
        <SurfaceView
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:id="@+id/surfaceView"/>

        <FrameLayout
            Android:id="@+id/control"
            Android:layout_width="match_parent"
            Android:layout_height="112dp"
            Android:layout_alignParentBottom="true"
            Android:layout_alignParentStart="true"
            Android:background="@color/control_background">



            <Button
                Android:id="@+id/picture"
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:layout_gravity="center"
                Android:text="@string/picture" />

            <ImageButton
                Android:id="@+id/info"
                Android:contentDescription="@string/description_info"
                style="@Android:style/Widget.Material.Light.Button.Borderless"
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:layout_gravity="center_vertical|right"
                Android:padding="20dp"
                Android:src="@drawable/ic_action_info" />

        </FrameLayout>

    </RelativeLayout>
3
Sourav301

私はそれを解決しました-フラグをクリアして表面ビューをdrawColor(Color.TRANSPARENT)に設定する必要があり、すべて問題ありませんでした。

1
aescript