Triển khai bản xem trước

Khi thêm một bản xem trước vào ứng dụng của bạn, hãy dùng PreviewView. Đây là View có thể cắt, điều chỉnh theo tỷ lệ và xoay để hiển thị phù hợp.

Bản xem trước hình ảnh sẽ truyền đến một khu vực bên trong PreviewView khi máy ảnh hoạt động.

Sử dụng PreviewView

Quy trình triển khai bản xem trước cho CameraX bằng PreviewView bao gồm các bước dưới đây. Các bước này được đề cập ở những phần sau:

  1. Định cấu hình CameraXConfig.Provider (không bắt buộc).
  2. Thêm PreviewView vào bố cục.
  3. Yêu cầu ProcessCameraProvider.
  4. Khi tạo View, hãy kiểm tra xem có ProcessCameraProvider hay không.
  5. Chọn một máy ảnh rồi liên kết vòng đời và trường hợp sử dụng.

Việc sử dụng PreviewView có một số hạn chế. Khi dùng PreviewView, bạn không thể thực hiện bất cứ điều nào sau đây:

  • Tạo một SurfaceTexture để đặt trên TextureViewPreview.SurfaceProvider.
  • Truy xuất SurfaceTexture từ TextureView và đặt trên Preview.SurfaceProvider.
  • Lấy giá trị Surface từ SurfaceView và đặt cho Preview.SurfaceProvider.

Nếu bất kỳ điều nào ở trên xảy ra, thì Preview sẽ ngừng truyền khung hình đến PreviewView.

Thêm PreviewView vào bố cục

Mẫu sau đây minh hoạ PreviewView trong bố cục:

<FrameLayout
    android:id="@+id/container">
        <androidx.camera.view.PreviewView
            android:id="@+id/previewView" />
</FrameLayout>

Yêu cầu CameraProvider

Mã sau đây minh hoạ cách yêu cầu một 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);
    }
}

Kiểm tra xem CameraProvider có dùng được hay không

Sau khi yêu cầu CameraProvider, hãy xác minh rằng quá trình khởi động đã thành công khi thành phần hiển thị được tạo. Mã sau đây minh hoạ cách thực hiện việc này:

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

Để biết ví dụ về hàm bindPreview dùng trong mẫu này, hãy xem mã được cung cấp trong phần tiếp theo.

Chọn một máy ảnh rồi liên kết vòng đời và trường hợp sử dụng

Sau khi bạn tạo và xác nhận CameraProvider, hãy làm như sau:

  1. Tạo Preview.
  2. Chỉ định tuỳ chọn LensFacing cho máy ảnh mà bạn muốn dùng.
  3. Liên kết máy ảnh đã chọn và mọi trường hợp sử dụng với vòng đời.
  4. Kết nối Preview với PreviewView.

Mã sau đây cho thấy một ví dụ:

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

Xin lưu ý rằng bindToLifecycle() trả về đối tượng Camera. Để biết thêm thông tin về cách kiểm soát đầu ra của máy ảnh, chẳng hạn như thu phóng và phơi sáng, hãy xem phần Đầu ra của máy ảnh.

Giờ thì bạn đã triển khai xong bản xem trước cho máy ảnh. Hãy tạo ứng dụng và xác nhận rằng bản xem trước xuất hiện trong ứng dụng của bạn và hoạt động như dự kiến.

Chế độ kiểm soát bổ sung cho PreviewView

PreviewView của CameraX cung cấp một số API bổ sung để định cấu hình các thuộc tính như:

Chế độ triển khai

PreviewView có thể dùng một trong các chế độ sau để kết xuất luồng xem trước trên View đích:

  • PERFORMANCE là chế độ mặc định. PreviewView dùng SurfaceView để hiển thị luồng video, nhưng sẽ quay lại dùng TextureView trong một số trường hợp nhất định. SurfaceView có khu vực vẽ chuyên dụng, giúp tăng cơ hội được trình tổng hợp phần cứng nội bộ triển khai thông qua lớp phủ phần cứng, đặc biệt khi không có thành phần khác trên giao diện người dùng (như nút) phía trên video xem trước. Bằng cách hiển thị qua lớp phủ phần cứng, khung hình video sẽ tránh được lộ trình GPU, nhờ đó giảm mức tiêu thụ điện năng và độ trễ của nền tảng.

  • Chế độ COMPATIBLE. Ở chế độ này, PreviewView dùng TextureView (khác với SurfaceView) không có khu vực vẽ chuyên dụng. Do đó, video sẽ được kết xuất bằng tính năng kết hợp để có thể hiển thị. Tại bước bổ sung này, ứng dụng có thể xử lý thêm các bước mà không bị hạn chế, ví dụ: điều chỉnh tỷ lệ và xoay video.

Hãy dùng PreviewView.setImplementationMode() để chọn chế độ triển khai phù hợp với ứng dụng của bạn. Nếu chế độ PERFORMANCE mặc định không phù hợp với ứng dụng của bạn, thì đoạn mã mẫu sau đây sẽ hướng dẫn bạn cách đặt chế độ COMPATIBLE:

Kotlin

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

Loại tỷ lệ

Nếu độ phân giải của video xem trước khác với kích thước của PreviewView đích, thì nội dung video phải vừa với thành phần hiển thị bằng cách cắt hoặc dùng hiệu ứng hòm thư (giữ nguyên tỷ lệ khung hình). Để phục vụ cho việc này, PreviewView cung cấp ScaleTypes sau:

  • FIT_CENTER, FIT_STARTFIT_END dùng cho hiệu ứng hòm thư. Toàn bộ nội dung video được điều chỉnh theo tỷ lệ (lên hoặc xuống) ở kích thước tối đa có thể hiển thị trong PreviewView đích. Tuy nhiên, mặc dù toàn bộ khung hình video vẫn hiển thị, một số phần màn hình có thể bị trống. Tuỳ thuộc vào loại tỷ lệ mà bạn chọn trong 3 loại này, khung hình video sẽ được căn chỉnh với phần giữa, đầu hoặc cuối của View đích.

  • FILL_CENTER, FILL_START, FILL_END dùng khi cắt. Nếu video không khớp với tỷ lệ khung hình PreviewView, thì dù chỉ một phần nội dung được hiển thị, video vẫn sẽ lấp đầy toàn bộ PreviewView.

Loại tỷ lệ mặc định mà CameraX sử dụng là FILL_CENTER. Hãy dùng PreviewView.setScaleType() để đặt loại tỷ lệ phù hợp nhất với ứng dụng của bạn. Đoạn mã mẫu sau đây đặt loại tỷ lệ FIT_CENTER:

Kotlin

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

Quy trình hiển thị video bao gồm các bước sau:

  1. Điều chỉnh video theo tỷ lệ:
    • Đối với các loại tỷ lệ FIT_*, hãy điều chỉnh video theo tỷ lệ bằng min(dst.width/src.width, dst.height/src.height).
    • Đối với các loại tỷ lệ FILL_*, hãy điều chỉnh video theo tỷ lệ bằng max(dst.width/src.width, dst.height/src.height).
  2. Căn chỉnh video được điều chỉnh theo tỷ lệ với PreviewView đích:
    • FIT_CENTER/FILL_CENTER: video được điều chỉnh theo tỷ lệ sẽ được căn giữa PreviewView đích.
    • FIT_START/FILL_START: video được điều chỉnh theo tỷ lệ sẽ được căn chỉnh về phía góc trên cùng bên trái của PreviewView đích.
    • FIT_END/FILL_END: video được điều chỉnh theo tỷ lệ sẽ được căn chỉnh về phía góc dưới cùng bên phải của PreviewView đích.

Ví dụ: dưới đây là video gốc có kích thước 640x480 với PreviewView đích có kích thước 1920x1080:

Hình ảnh minh hoạ video có kích thước 640x480 so với bản xem trước có kích thước 1920x1080

Hình ảnh sau đây minh hoạ cách FIT_START/FIT_CENTER/FIT_END điều chỉnh theo tỷ lệ:

Hình ảnh minh hoạ cách FIT_START, FIT_CENTER và FIT_END điều chỉnh theo tỷ lệ

Quy trình này diễn ra như sau:

  1. Điều chỉnh khung hình video theo tỷ lệ (duy trì tỷ lệ khung hình gốc) bằng min(1920/640, 1080/480) = 2.25 để có được khung hình video trung gian 1440x1080.
  2. Căn chỉnh khung hình video có kích thước 1440x1080 với PreviewView có kích thước 1920x1080.
    • FIT_CENTER: khung hình video sẽ được căn giữa cửa sổ PreviewView. Cột 240 điểm ảnh đầu và cuối của PreviewView được để trống.
    • FIT_START: khung hình video sẽ được căn tại phần đầu (góc trên cùng bên trái) của cửa sổ PreviewView. Cột 480 điểm ảnh ở phần cuối của PreviewView được để trống.
    • FIT_END: khung hình video sẽ được căn tại phần cuối (góc dưới cùng bên phải) của cửa sổ PreviewView. Cột 480 điểm ảnh ở phần đầu của PreviewView bị trống.

Hình ảnh sau đây minh hoạ cách FILL_START/FILL_CENTER/FILL_END điều chỉnh theo tỷ lệ:

Hình ảnh minh hoạ cách FILL_START, FILL_CENTER và FILL_END điều chỉnh theo tỷ lệ

Quy trình này diễn ra như sau:

  1. Điều chỉnh khung hình video theo tỷ lệ với max(1920/640, 1080/480) = 3 để có được khung hình video trung gian có kích thước 1920x1440 (lớn hơn kích thước của PreviewView).
  2. Cắt khung hình video có kích thước 1920x1440 cho vừa với cửa sổ PreviewView có kích thước 1920x1080.
    • FILL_CENTER: khung hình video có kích thước 1920x1080 sẽ cắt từ phần giữa của video được điều chỉnh theo tỷ lệ 1920x1440. 180 dòng trên cùng và dưới cùng của video không hiển thị.
    • FILL_START: khung hình video có kích thước 1920x1080 sẽ cắt từ phần đầu của video được điều chỉnh theo tỷ lệ 1920x1440. 360 dòng dưới cùng của video không hiển thị.
    • FILL_END: khung hình video có kích thước 1920x1080 sẽ cắt từ phần cuối của video được điều chỉnh theo tỷ lệ 1920x1440. 360 dòng trên cùng của video không hiển thị.

Tài nguyên khác

Để tìm hiểu thêm về CameraX, hãy xem các tài nguyên bổ sung sau đây.

Lớp học lập trình

  • Bắt đầu sử dụng CameraX
  • Đoạn mã mẫu

  • Ứng dụng mẫu CameraX