導入預覽

在應用程式中新增預覽時,請使用 PreviewView。這種 View 可供裁剪、縮放及旋轉,以便正確顯示圖片。

當相機啟動時,圖片預覽會串流至 PreviewView 內部途徑。

使用 PreviewView

使用 PreviewView 對 CameraX 導入預覽時,以下步驟會進行說明,詳情請見後續章節:

  1. 選用設定 CameraXConfig.Provider
  2. 在版面配置中新增 PreviewView
  3. 要求 ProcessCameraProvider
  4. View 建立時查看 ProcessCameraProvider
  5. 請選取相機並繫結至生命週期和用途。

使用 PreviewView 有些許限制。使用 PreviewView 時,您將無法執行下列任一操作:

  • TextureViewPreview.SurfaceProvider 中建立要設定的 SurfaceTexture
  • 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 後,請執行以下操作:

  1. 建立 Preview
  2. 指定想要的相機 LensFacing 選項。
  3. 將所選相機和任何用途繫結至生命週期。
  4. 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 顯示影片串流,但在某些情況下會改回 TextureViewSurfaceView 具有專屬的繪圖介面,較有可能透過內部硬體合成器實作硬體重疊圖層,當預覽影片頂層沒有其他 UI 元素 (例如按鈕) 時更是如此。只要透過硬體重疊圖層進行算繪,影片畫面就會避免使用 GPU 路徑,進而降低平台耗電量和延遲時間。

  • COMPATIBLE 模式。在此模式下,PreviewView 會採用無專屬繪圖途徑的 TextureView,與 SurfaceView 不同。因此,為了方便顯示,影片會以混合的方式算繪。在此額外步驟中,應用程式可以執行其他處理作業,例如不受限制地縮放及旋轉影片。

請使用 PreviewView.setImplementationMode() 選取適合您應用程式的實作模式。如果預設的 PERFORMANCE 模式不適合您的應用程式使用,請參考下列程式碼範例,瞭解如何設定 COMPATIBLE 模式:

Kotlin

// viewFinder is a PreviewView instance
viewFinder.implementationMode = PreviewView.ImplementationMode.COMPATIBLE

縮放類型

如果預覽影片的解析度與目標 PreviewView 的尺寸不同,影片內容就需要經過裁剪或新增上下黑邊 (保持原始顯示比例),才能與檢視畫面相符。為此,PreviewView 提供了下列 ScaleTypes

  • FIT_CENTERFIT_STARTFIT_END 可以用於上下黑邊。完整的影片內容將縮放 (向上或向下) 至目標 PreviewView 可顯示的最大可能尺寸。不過,在顯示完整影片畫面時,螢幕中的部分內容可能會呈現空白。根據選擇的三種縮放類型,影片畫面會與目標「檢視畫面」的中心點、起點或結尾對齊。

  • FILL_CENTERFILL_STARTFILL_END 可以用於裁剪。如果影片不符合 PreviewView 的顯示比例,則系統只會顯示部分內容,但影片會填滿整個 PreviewView

CameraX 採用的預設縮放類型為 FILL_CENTER。請使用 PreviewView.setScaleType() 設定最適合您應用程式的縮放類型。下列程式碼範例會設定 FIT_CENTER 縮放類型:

Kotlin

// viewFinder is a PreviewView instance
viewFinder.scaleType = PreviewView.ScaleType.FIT_CENTER

顯示影片的程序包括下列步驟:

  1. 縮放影片:
    • 如果是 FIT_* 縮放類型,請使用 min(dst.width/src.width, dst.height/src.height) 縮放影片。
    • 如果是 FILL_* 縮放類型,請使用 max(dst.width/src.width, dst.height/src.height) 縮放影片。
  2. 將縮放後的影片與目的地 PreviewView 對齊:
    • 如果是 FIT_CENTER/FILL_CENTER,縮放後的影片與目的地 PreviewView 置中對齊。
    • 如果是 FIT_START/FILL_START,縮放後的影片與目的地 PreviewView 相對於每個影片的左上角對齊。
    • 如果是 FIT_END/FILL_END,縮放後的影片與目的地 PreviewView 相對於每個影片的右下角對齊。

舉例來說,以下為 640x480 的來源影片和 1920x1080 的目的地 PreviewView

與 1920x1080 預覽相比,顯示 640x480 影片的圖片

下圖顯示了 FIT_START / FIT_CENTER / FIT_END 的縮放程序:

圖片顯示 FIT_START、FIT_CENTER 和 FIT_END 縮放程序

整體程序的運作方式如下:

  1. 使用 min(1920/640, 1080/480) = 2.25 縮放影片畫面 (保留原始長寬比),以取得 1440x1080 的中繼影片畫面。
  2. 將 1440x1080 影片畫面與 1920x1080 PreviewView 對齊。
    • 針對 FIT_CENTER,將影片畫面與 PreviewView 視窗的中心對齊。PreviewView 起始和結束位置的 240 像素欄為空白。
    • 針對 FIT_START,將影片畫面與 PreviewView 視窗的起始位置 (左上角) 對齊。PreviewView 結束位置的 480 像素欄為空白。
    • 針對 FIT_END,將影片畫面與 PreviewView 視窗的結束位置 (右下角) 對齊。PreviewView 起始位置的 480 像素欄為空白。

下圖顯示了 FILL_START / FILL_CENTER / FILL_END 的縮放程序:

顯示 FILL_START、FILL_CENTER 和 FILL_END 縮放程序的圖片

整體程序的運作方式如下:

  1. 使用 max(1920/640, 1080/480) = 3 縮放影片畫面,以取得 1920x1440 的中繼畫面 (大於 PreviewView 的尺寸)。
  2. 裁剪 1920x1440 影片畫面,以符合 1920x1080 PreviewView 的視窗。
    • 針對 FILL_CENTER,從縮放版 1920x1440 影片的中心裁剪出 1920x1080 的大小。影片的上方和底部 180 行不會顯示。
    • 針對 FILL_START,從縮放版 1920x1440 影片的開始位置裁剪出 1920x1080 的大小。影片的底部 360 行不會顯示。
    • 對於 FILL_END,從縮放版 1920x1440 影片的結束位置裁剪出 1920x1080 的大小。影片上方的 360 行不會顯示。

其他資源

如要進一步瞭解 CameraX,請參閱下列其他資源。

程式碼研究室

  • 開始使用 CameraX
  • 程式碼範例

  • CameraX 範例應用程式