我有这个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()
}
}
相机的圆形对话框片段,但显示在矩形视图中
你不能直接把它弄圆。为此,需要为其创建一个自定义视图,如下所示。
您可以在 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);
}
}