【问题标题】:How to render SurfaceView cropped to a circle?如何将 SurfaceView 裁剪为圆形?
【发布时间】:2019-06-14 07:49:18
【问题描述】:

我想在一个圆圈内渲染一个相机预览,像这样:

我让它在添加到活动的片段中工作。但我想通过将其添加到 WindowManager 来显示其他应用程序上方的视图。

所以我的工作是在其他应用程序上方显示视图,但 SurfaceView 根本没有剪辑。另外,我将 SurfaceView 裁剪为圆形,但在一个片段中。

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

添加到 WindowManager 后的外观

我正在尝试绘制

如何剪辑显示在所有视图上方的 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);
    }
}

将视图添加到窗口管理器的服务

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 中做任何事情,并且相机一直显示为矩形。

【问题讨论】:

标签: android surfaceview geometry android-windowmanager


【解决方案1】:

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

在线程的绘图循环内:

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);

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-01
    • 2021-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多