【发布时间】: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 中做任何事情,并且相机一直显示为矩形。
【问题讨论】:
-
我尝试了 Region.Op.DIFFERENCE 和其他标志,但没有任何变化。这就像 clipPath 什么都不做。我什至注释掉了
super.dispatchDraw(canvas)并且摄像头仍在显示。
标签: android surfaceview geometry android-windowmanager