Android CameraX 预览不是圆形的

问题描述 投票:0回答:1

我有这个dialogFragment 布局,其中包含圆形布局。 我只需要在显示对话框时显示圆形布局,我创建了自定义视图或 CardView,但没有任何效果 我尝试的所有内容都以矩形视图显示,而卡片视图或自定义类的圆形最多显示圆形卡片视图的阴影 我的意思是,我只需要显示一个圆形对话框片段,并且相机显示在其中。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.cardview.widget.CardView
            android:id="@+id/cameraWrapper"
            android:layout_width="300dp"
            android:layout_height="300dp"
            android:foreground="@drawable/background_camera_overlay_circle"
            android:padding="-20dp"
            app:cardCornerRadius="360dp"
            app:cardElevation="0dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

            <androidx.camera.view.PreviewView
                android:id="@+id/preview"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />

        </androidx.cardview.widget.CardView>
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

这是我的用于显示相机对话框的对话框片段

class CameraDialog : DialogFragment(R.layout.dialog_camera) {
    companion object {
        private const val TAG = "CameraXApp"
    }

    private lateinit var binding: DialogCameraBinding
    private var videoCapture: VideoCapture<Recorder>? = null
    private var recording: Recording? = null
    private lateinit var cameraExecutor: ExecutorService

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        binding = DialogCameraBinding.inflate(inflater, container, false)
        dialog?.window?.setBackgroundDrawable(ColorDrawable(0x00ffffff))
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        startCamera()
        cameraExecutor = Executors.newSingleThreadExecutor()
        /**
         * this handler makes this recording camera with delay after that saving
         */
        view.postDelayed({
            captureVideo()
        }, 1000)
    }

    private fun captureVideo() {
        val videoCapture = this.videoCapture ?: return
        val curRecording = recording
        if (curRecording != null) {
            curRecording.stop()
            recording = null
            return
        }

        recording = videoCapture.output
            .prepareRecording(
                requireContext(),
                requireActivity().contentResolver.createVideoStoreOutputOptions(
                    ContentValues().createVideoContentValues()
                )
            )
            .apply {
                // Enable Audio for recording
                if (
                    PermissionChecker.checkSelfPermission(
                        requireContext(),
                        Manifest.permission.RECORD_AUDIO
                    ) ==
                    PermissionChecker.PERMISSION_GRANTED
                ) {
                    withAudioEnabled()
                }
            }
            .start(ContextCompat.getMainExecutor(requireContext())) { recordEvent ->
                when (recordEvent) {
                    is VideoRecordEvent.Finalize -> {
                        if (!recordEvent.hasError())
                            Toast.makeText(requireContext(), "captureVideo", Toast.LENGTH_SHORT).show()
                        else {
                            recording?.close()
                            recording = null
                            Timber.tag(TAG).e("captureVideo: got error")
                        }
                        dialog?.dismiss()
                    }
                }
            }
    }

    private fun startCamera() {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext())
        cameraProviderFuture.addListener({
            val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()

            // Preview
            val preview = Preview.Builder()
                .build()
                .also {
                    it.setSurfaceProvider(binding.preview.surfaceProvider)
                }

            // Video
            val recorder = Recorder.Builder()
                .setQualitySelector(
                    QualitySelector.from(
                        Quality.HIGHEST,
                        FallbackStrategy.higherQualityOrLowerThan(Quality.SD)
                    )
                )
                .build()
            videoCapture = VideoCapture.withOutput(recorder)

            // Select back camera as a default
            val cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA
            try {
                // Unbind use cases before rebinding
                cameraProvider.unbindAll()

                // Bind use cases to camera
                cameraProvider.bindToLifecycle(this, cameraSelector, preview, videoCapture)
            } catch (exc: Exception) {
                Timber.e(TAG, "Use case binding failed", exc)
            }
        }, ContextCompat.getMainExecutor(requireContext()))
    }

    override fun onDestroy() {
        super.onDestroy()
        cameraExecutor.shutdown()
    }
}

enter image description here 我需要将相机显示在红圈内 enter image description here

相机的圆形对话框片段,但显示在矩形视图中

android xml kotlin camera cardview
1个回答
0
投票

你不能直接把它弄圆。为此,需要为其创建一个自定义视图,如下所示。

您可以在 XML 中使用此类来显示相机周围。不要忘记将所需的参数传递给它。

RoundedCameraPreview.java

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.camera.view.PreviewView;
import future.quantumpaper.sci10gx302.papergenerator.R;


public class RoundedCameraPreview extends PreviewView {


    Path clipPath;
    boolean isRound;
    Context mContext;
    int padding;

    public RoundedCameraPreview(@NonNull Context context) {
        super(context);
        mContext = context;
    }

    public RoundedCameraPreview(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
    }

    public RoundedCameraPreview(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.cm_PreviewView,
                0, 0);
        try {
            isRound = a.getBoolean(R.styleable.cm_PreviewView_isRound, true);
            padding = a.getInt(R.styleable.cm_PreviewView_image_padding, 0);
        } finally {
            a.recycle();
        }
    }

    public boolean isRound() {
        return isRound;
    }

    public void setIsRound(boolean isRound) {
        this.isRound = isRound;
        invalidate();
        requestLayout();
    }


    public int getImagePadding() {
        return padding;
    }

    public void setImagePadding(int padding) {
        this.padding = padding;
        invalidate();
        requestLayout();
    }

    public RoundedCameraPreview(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        mContext = context;
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        if (isRound) {
            clipPath = new Path();
            clipPath.addCircle(canvas.getWidth() / 2, canvas.getWidth() / 2, (canvas.getWidth() / 2) - padding, Path.Direction.CW);
            Paint paint = new Paint();
            paint.setAntiAlias(true);
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
            canvas.clipPath(clipPath);
            canvas.drawPath(clipPath, paint);
        } else {
            clipPath = new Path();
            clipPath.addRect(padding, padding, (canvas.getWidth()) - padding, (canvas.getHeight()) - padding, Path.Direction.CCW);
            Paint paint = new Paint();
            paint.setAntiAlias(true);
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
            canvas.clipPath(clipPath);
            canvas.drawPath(clipPath, paint);
        }
        super.dispatchDraw(canvas);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.