android - 如何渲染裁剪成圆形的 SurfaceView?

标签 android surfaceview geometry android-windowmanager

我想在圆圈内渲染相机预览,如下所示:

我让它在添加到 Activity 的 fragment 中工作。但我想通过将 View 添加到 WindowManager 来显示其他应用程序之上的 View 。

所以我所做的工作是在其他应用程序之上显示 View ,但 SurfaceView 根本不剪辑。另外,我将 SurfaceView 剪裁成圆形,但在一个 fragment 中。

我在这里阅读了很多关于这个主题的答案和文章。关于裁剪 SurfaceView 的信息很少,也没有库可以满足我的要求。我找到的大部分信息只解释了如何将其裁剪为正方形或其他矩形。

添加到 WindowManager 后的样子

我在努力画画

如何剪辑显示在所有 View 上方的 SurfaceView?

SurfaceView 子类

public class CircleSurface extends SurfaceView {

    private Path clipPath;

    public CircleSurface(Context context) {
        super(context);
        init();
    }

    public CircleSurface(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CircleSurface(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        setZOrderMediaOverlay(true);
        setWillNotDraw(false);

        SurfaceHolder sfhTrackHolder = getHolder();
        sfhTrackHolder.setFormat(PixelFormat.TRANSPARENT);


        clipPath = new Path();
        //TODO: define the circle you actually want
        clipPath.addCircle(710, 330, 250, Path.Direction.CW);
    }

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

向窗口管理器添加 View 的服务

public class LiveStreamingService extends Service implements SurfaceHolder.Callback {
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForeground(startId, getNotification());
        }
        sharedInstance = this;

        // android shouldn't auto restart this service
        return START_NOT_STICKY;
    }

    @Override
    public void onCreate() {
        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);

        // camera view
        CircleSurface cameraSurfaceView = new CircleSurface(this);
        cameraSurfaceView.getHolder().addCallback(this);

        wm.addView(cameraSurfaceView, getLayoutParams(360, 270));
    }

    private WindowManager.LayoutParams getLayoutParams(int width, int height) {
        int overlayType = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O 
                ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY 
                : WindowManager.LayoutParams.TYPE_PHONE;

        WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
                width,
                height,
                overlayType,
                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
                PixelFormat.TRANSLUCENT
        );

        return layoutParams;
    }

    // ...
}

更新

似乎相机渲染在某种程度上与 dispatchDraw 方法分开。我可以在 dispatchDraw 中做任何事情,并且相机一直显示为矩形。

最佳答案

为使用 OnPreviewFrame 监听相机预览回调的表面 View 创建了一个绘图线程。

在线程的绘图循环中:

c.drawColor(0, PorterDuff.Mode.CLEAR);
c.drawColor(0x1000000); // magical color that removes everything (like transparency)

if (currentFrame == null) return;

c.clipPath(circleSurfaceView.path);
c.drawBitmap(currentFrame, 0, 0, paint);

我不知道神奇的颜色是什么。我遇到它是幸运的。我尝试过的所有其他方法只会画出黑色或模糊的噪音。

关于android - 如何渲染裁剪成圆形的 SurfaceView?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54281206/

相关文章:

安卓 PID 问题

android - 渐变在 SurfaceView 中显示为带状,但在普通 View 中看起来非常平滑

google-maps - 如何根据纬度/经度计算三点之间的角度

android - 在 Android 中按下 Button 时连续触发事件

android - 安卓文件选择器

android - Marshmallow 指纹扫描仪硬件存在

java - 在没有布局的情况下以编程方式创建 ImageView

android - getSupportedPictureSize() 返回一个 Nexus4 实际上不支持的值

android - 圈选并选择文本

python - Pyplot 双纽线