在應用程式中新增預覽時,請使用 PreviewView
。這種 View
可供裁剪、縮放及旋轉,以便正確顯示圖片。
當相機啟動時,圖片預覽會串流至 PreviewView
內部途徑。
使用 PreviewView
使用 PreviewView
對 CameraX 導入預覽的過程包含下列步驟,詳情請見後續章節:
- (選用) 設定
CameraXConfig.Provider
。 - 在版面配置中加入
PreviewView
。 - 要求
ProcessCameraProvider
。 - 建立
View
時確認ProcessCameraProvider
。 - 選取相機並繫結至生命週期和用途。
使用 PreviewView
有些許限制。使用 PreviewView
時,您將無法執行下列任一操作:
- 建立
SurfaceTexture
,並在TextureView
和Preview.SurfaceProvider
上進行設定。 - 從
TextureView
擷取SurfaceTexture
,並設定在Preview.SurfaceProvider
上。 - 從
SurfaceView
取得Surface
,並設定在Preview.SurfaceProvider
上。
如果發生上述任一情況,Preview
就會停止將影格串流至 PreviewView
。
在版面配置中加入 PreviewView
下列範例顯示版面配置中的 PreviewView
:
<FrameLayout android:id="@+id/container"> <androidx.camera.view.PreviewView android:id="@+id/previewView" /> </FrameLayout>
要求 CameraProvider
下列程式碼顯示 CameraProvider
的要求方式:
Kotlin
import androidx.camera.lifecycle.ProcessCameraProvider import com.google.common.util.concurrent.ListenableFuture class MainActivity : AppCompatActivity() { private lateinit var cameraProviderFuture : ListenableFuture<ProcessCameraProvider> override fun onCreate(savedInstanceState: Bundle?) { cameraProviderFuture = ProcessCameraProvider.getInstance(this) } }
Java
import androidx.camera.lifecycle.ProcessCameraProvider import com.google.common.util.concurrent.ListenableFuture public class MainActivity extends AppCompatActivity { private ListenableFuture<ProcessCameraProvider> cameraProviderFuture; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { cameraProviderFuture = ProcessCameraProvider.getInstance(this); } }
檢查 CameraProvider 適用性
要求 CameraProvider
後,請在建立檢視畫面時確認初始化成功。以下程式碼說明如何執行這項作業:
Kotlin
cameraProviderFuture.addListener(Runnable { val cameraProvider = cameraProviderFuture.get() bindPreview(cameraProvider) }, ContextCompat.getMainExecutor(this))
Java
cameraProviderFuture.addListener(() -> { try { ProcessCameraProvider cameraProvider = cameraProviderFuture.get(); bindPreview(cameraProvider); } catch (ExecutionException | InterruptedException e) { // No errors need to be handled for this Future. // This should never be reached. } }, ContextCompat.getMainExecutor(this));
如需此範例中使用的 bindPreview
函式範例,請參閱下一節提供的程式碼。
選取相機並繫結生命週期和用途
建立並確認 CameraProvider
後,請執行以下操作:
- 建立
Preview
。 - 指定想要的相機
LensFacing
選項。 - 將所選相機和任何用途繫結至生命週期。
- 將
Preview
連結至PreviewView
。
請見以下程式碼範例:
Kotlin
fun bindPreview(cameraProvider : ProcessCameraProvider) { var preview : Preview = Preview.Builder() .build() var cameraSelector : CameraSelector = CameraSelector.Builder() .requireLensFacing(CameraSelector.LENS_FACING_BACK) .build() preview.setSurfaceProvider(previewView.getSurfaceProvider()) var camera = cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, preview) }
Java
void bindPreview(@NonNull ProcessCameraProvider cameraProvider) { Preview preview = new Preview.Builder() .build(); CameraSelector cameraSelector = new CameraSelector.Builder() .requireLensFacing(CameraSelector.LENS_FACING_BACK) .build(); preview.setSurfaceProvider(previewView.getSurfaceProvider()); Camera camera = cameraProvider.bindToLifecycle((LifecycleOwner)this, cameraSelector, preview); }
請注意,bindToLifecycle()
會傳回 Camera
物件。如要進一步瞭解如何控管相機輸出內容 (例如縮放和曝光),請參閱相機輸出內容相關說明。
您已完成相機預覽實作內容。建構應用程式,並確認應用程式和功能中顯示的預覽可以正常運作。
PreviewView 的其他控制項
CameraX PreviewView
提供一些用來設定屬性的其他 API,例如:
實作模式
PreviewView
可以使用下列其中一種模式,將預覽串流轉譯至目標 View
:
PERFORMANCE
為預設模式。PreviewView
會使用SurfaceView
顯示影片串流,但在某些情況下會改回使用TextureView
。SurfaceView
具有專屬繪圖介面,較有可能透過內部硬體合成器實作硬體疊加,特別是預覽影片上方沒有其他 UI 元素 (例如按鈕) 的情況。只要使用硬體疊加進行轉譯,影片影格就會避免使用 GPU 路徑,進而減少平台耗電量和延遲時間。COMPATIBLE
模式。在此模式下,PreviewView
會使用沒有專屬繪圖介面 (與SurfaceView
不同) 的TextureView
。因此,必須以混合的方式轉譯才能顯示影片。在這個額外步驟中,應用程式可以執行其他處理程序,例如不受限制地縮放及旋轉影片。
使用 PreviewView.setImplementationMode()
選取應用程式適用的實作模式。如果預設的 PERFORMANCE
模式不適用於應用程式,可以參考以下程式碼範例,瞭解如何設定 COMPATIBLE
模式:
Kotlin
// viewFinder is a PreviewView instance viewFinder.implementationMode = PreviewView.ImplementationMode.COMPATIBLE
縮放類型
如果預覽影片的解析度與目標 PreviewView
的尺寸不同,就需要配合檢視畫面裁剪影片內容或添加上下黑邊 (維持原始顯示比例)。為此,PreviewView
提供下列 ScaleTypes
:
FIT_CENTER
、FIT_START
和FIT_END
可用於添加上下黑邊。完整的影片內容會盡可能縮放 (放大或縮小) 至目標PreviewView
可顯示的最大尺寸。不過,雖然這種做法可以顯示完整的影片影格,畫面中的某部分可能會呈現空白。根據您在三種縮放類型之中選擇的類型,影片影格會與目標 View 的中心點、起點或結尾對齊。FILL_CENTER
、FILL_START
、FILL_END
可用於裁剪。如果影片不符合PreviewView
的顯示比例,則只會顯示部分內容,但影片會填滿整個PreviewView
。
CameraX 採用的預設縮放類型為 FILL_CENTER
。使用 PreviewView.setScaleType()
即可設定應用程式最適用的縮放類型。下列程式碼範例可設定 FIT_CENTER
縮放類型:
Kotlin
// viewFinder is a PreviewView instance viewFinder.scaleType = PreviewView.ScaleType.FIT_CENTER
顯示影片的程序包括下列步驟:
- 縮放影片:
- 如果是
FIT_*
縮放類型,請使用min(dst.width/src.width, dst.height/src.height)
縮放影片。 - 如果是
FILL_*
縮放類型,請使用max(dst.width/src.width, dst.height/src.height)
縮放影片。
- 如果是
- 將縮放後的影片與目的地
PreviewView
對齊:- 如果是
FIT_CENTER/FILL_CENTER
,縮放後的影片與目的地PreviewView
會依據中心點對齊。 - 如果是
FIT_START/FILL_START
,縮放後的影片與目的地PreviewView
會依據各自的左上角對齊。 - 如果是
FIT_END/FILL_END
,縮放後的影片與目的地PreviewView
會依據各自的右下角對齊。
- 如果是
舉例來說,以下是 640x480 的來源影片和 1920x1080 的目的地 PreviewView
:
下圖顯示 FIT_START
/FIT_CENTER
/FIT_END
的縮放程序:
整體程序的運作方式如下:
- 使用
min(1920/640, 1080/480) = 2.25
縮放影片影格 (保留原始顯示比例),取得 1440x1080 的中繼影片影格。 - 將 1440x1080 影片影格與 1920x1080
PreviewView
對齊。- 如果是
FIT_CENTER
,將影片影格與PreviewView
視窗的中心對齊。PreviewView
起始和結束的 240 像素欄為空白。 - 如果是
FIT_START
,將影片影格與PreviewView
視窗的起點 (左上角) 對齊。PreviewView
結束的 480 像素欄為空白。 - 如果是
FIT_END
,將影片影格與PreviewView
視窗的結尾 (右下角) 對齊。PreviewView
起始的 480 像素欄為空白。
- 如果是
下圖顯示 FILL_START
/FILL_CENTER
/FILL_END
的縮放程序:
程序的運作方式如下:
- 使用
max(1920/640, 1080/480) = 3
縮放影片影格,取得 1920x1440 的影片影格 (大於PreviewView
的尺寸)。 - 配合 1920x1080
PreviewView
視窗裁剪 1920x1440 影片影格。- 如果是
FILL_CENTER
,以 1920x1440 縮放後影片的中心為準,裁剪出 1920x1080 的大小。這時無法顯示影片上方和底部的 180 行內容。 - 如果是
FILL_START
,以 1920x1440 縮放後影片的起點為準,裁剪出 1920x1080 的大小。這時無法顯示影片底部的 360 行內容。 - 如果是
FILL_END
,以 1920x1440 縮放後影片的結尾為準,裁剪出 1920x1080 的大小。這時無法顯示影片上方的 360 行內容。
- 如果是
其他資源
如要進一步瞭解 CameraX,請參閱下列其他資源。
程式碼研究室
程式碼範例