Android:在方向更改时保留相机预览,而其他视图可以旋转

Android: retaining camera preview on orientation change while other views can rotate

我正在尝试构建自定义相机应用。我有一个 class 扩展 SurfaceView 用于相机预览。当设备改变方向时,该表面会被破坏并重新创建,从而导致明显的 "glitch",这会降低用户体验。

我想做的是防止必须在方向更改时重新创建此相机预览。此外,我希望有一些按钮覆盖此预览(例如闪光灯、选择 front/back 相机等),这些按钮会在方向改变时旋转。这类似于股票相机应用程序的作用:

Stock camera in landscape mode.

Stock camera in portrait mode. Note that buttons rotate on orientation change.

我发现的最佳方法(例如 here 中描述的)是使用清单文件将 activity 方向强制为横向,并在拍摄照片后根据需要旋转生成的照片在真实的设备方向上。据我了解,这种方法的缺点是,这也会阻止覆盖按钮的旋转。或者,当我读到一些关于使用片段和保留片段实例的内容时,我想知道我是否可以通过保留包含相机预览的片段来实现我的目标(是的,我是一个菜鸟)。

执行此操作的正确方法是什么?

如果您的清单未声明 [​​=21=] 处理方向更改,并且未锁定到单个方向,则设备的旋转将导致整个 activity 卸载并重新加载再次。这不就是你现在所经历的吗?

如果您为 activity 指定 android:configChanges="orientation|screenSize",那么用户体验会更加流畅。但是,在这样的旋转之后,你仍然不能保持相机预览 "intact";将重建布局。

最后,stock camera 应用程序的方法是设置固定(通常是横向)activity 方向,并通过更改按钮和其他 UI 元素来伪造纵向方向。但是如果你在底部寻找系统通知或导航(软)按钮,你会明白实际上设备被锁定在横向,只有控件被重绘。您还会注意到相机应用会避免使用标准文本小部件,因为此类小部件无法轻松旋转。

对了,你的问题还有一个误区。如果您想将图片存储为纵向,则无论您的 activity 方向如何,都需要(或不需要)手动旋转 JPEG。在大多数设备上,相机只能生成风景 JPEG 文件。相机 API 包括 setRotation() 方法,但通常,这只会在 JPEG header 中设置一个 EXIF 标志。并非所有图像查看器都尊重此标志。如果您不想妥协,可能需要手动旋转图像。