Xây dựng ứng dụng chụp ảnh và filter camera trên Android (p2)

Hello, mình là Dương Vũ. Đây là bài viết thứ 2 trong loạt bài hướng dẫn xây dựng ứng dụng chụp ảnh và filter camera trên Android. Ở bài viết trước mình đã hướng dẫn xây dựng màn hình Splash có chức năng hiện ra dòng giới thiệu về ứng dụng, đồng thời xin cấp các permission sử dụng trong ứng dụng. Bài này, ta sẽ cùng nhau xây dựng module chính của ứng dụng: module camera và chụp ảnh. Sau khi hoàn thành bài viết này, ứng dụng của ta sẽ có thêm các chức năng:

  • Camera kèm theo hiệu ứng (filter)
  • Hiển thị danh sách filter để lựa chọn khi chụp ảnh
  • Lưu trữ ảnh trên bộ nhớ thiết bị
  • Các chức năng cơ bản của camera: quay trước, quay sau, on/off chế độ chụp flash.

Nào, bắt đầu nhé!

Màn hình Main

Ok, mình sẽ sử dụng luôn lớp MainActivity mà IDE tạo ra cho  lúc khởi tạo dự án để viết chức năng camera. Màn hình này bao gồm 1 camera view có kích thước chiều rộng full màn hình, chiều cao bằng chiều rộng (tỉ lệ 1:1). Có 1 button để chụp ảnh, 1 recyclerView để hiển thị danh sách hiệu ứng, các button chức năng của camera (on/off flash, đổi camera). Ngoài ra màn hình còn có thêm 1 button cho phép chọn ảnh từ gallery. Ok, ta hãy bắt tay vào xây dựng layout cho nó.

Xây dựng layout

Ta chỉnh sửa lại file activity_main.xml như sau:

Bạn đừng lo lắng khi nhìn sang preview thấy layout của ta như 1 mớ shit. Ta sẽ chỉnh sửa lại kích thước cho chúng ở phần code Java. Ở đây, ta chỉ cần lưu ý tới 1 view đặc biệt, đó là org.wysaid.view.CameraRecordGLSurfaceView. Đây chính là view thuôc thư viện xử lý ảnh mà mình đã trình bày ở bài đầu tiên. Nó sẽ có nhiệm vụ hiển thị camera preview cho chúng ta.

MainActivity.java

Khai báo layout đã xong, giờ ta sẽ chuyển tới phần Java code. Việc đầu tiên là ta sẽ bắt MainActivity kế thừa BaseActivity ta đã tạo ra (chứ không phải kế thừa AppCompatActivity như mặc định), sau đó sẽ là bindView cho nó:

Setup camera

Tiếp theo, mình sẽ viết 1 phương thức setUpCameraView, phương thức này sẽ chỉnh sửa lại kích thước của cameraView, do ở phần layout xml, kích thước của cameraView chưa đúng tỉ lệ 1:1. Ngoài ra, ta cũng sẽ bắt các sự kiện cho các button on/off flash và config 1 số thuộc tính của cameraview:

Ok, việc setup cho cameraview đến đây gần như đã xong. Tuy nhiên còn 1 bước nữa. Như đã giới thiệu ở bài trước, mình có sử dụng những file LUT chứa trong thư mục assets để tạo ra hiệu ứng cho camera. Vì vậy, ta cần khai báo (load) các file LUT này cho đối tượng cameraView của chúng ta. Trước hết, hãy tạo 1 callback theo dõi việc load các file LUT success hay failed:

Sau khi tạo callback xong, ta thêm câu lệnh sau vào phương thức setUpCameraView để load các file LUT:

Ok, vậy là các bước config cho cameraView đã hoàn thành. Ta sẽ gọi hàm setUpCameraView vừa viết ở trong hàm createView:

và không quên tắt camera khi rời khỏi activity hiện tại:

 

Xây dựng list filter

Bây giờ việc tiếp theo của ta là hiển thị list các filter để cho người dùng chọn trong lúc chụp ảnh. Ta sẽ dùng recyclerView để hiển thị các filter này. Việc đầu tiên chúng ta cần làm để xây dựng list filter là định nghĩa 1 đối tượng chứa các thông tin về filter đó.

Đối tượng FilterData.

Mình sẽ tạo 1 package model. Bên trong chứa lớp FilterData có nội dung như sau:

Như các bạn thấy lớp này chỉ là 1 lớp Java thuần túy, không có gì đặc biệt cả. Nó chứa 3 trường:

  • name: Tên hiển thị trên app của filter.
  • rule: config của filter để thư viện xử lý ảnh thực hiện theo. Thực chất đây là tên các file LUT. Nếu các bạn tìm hiểu sâu thêm về thư viện xử lý ảnh này, các bạn sẽ thấy rằng có thể viết các config để thực hiện bất kỳ hiệu ứng nào ta mong muốn (chỉ cần có giá trị tham số). Tuy nhiên mình sẽ viết ở 1 bài khác. Ở bài này ta chỉ cần quan tâm đến tên config chứa file LUT mà thôi.
  • imageId: Id ảnh preview của filter. Mình sẽ đặt sẵn các ảnh preview ứng với từng filter trong thư mục drawable. Và trường imageId này sẽ có giá trị là id của các ảnh đó để hiện thị lên trên app.

Như vậy là ta đã xây dựng xong đối tượng chứa các thông tin về 1 filter. Giờ ta sẽ xây dựng adapter hiển thị list filter.

Xây dựng List Filter Adapter

Đầu tiên ta sẽ tạo layout cho các item của adapter, đặt tên là item_list_filter.xml:

Hãy để ý tới dòng:

Khi 1 filter được chọn, nó sẽ có 1 background riêng, để dễ phân biệt với các filter còn lại. Ta sẽ viết 2 file xml để thể hiện 2 trạng thái (được chọn và không được chọn) của filter. Trong thư mục drawable, tạo file bg_item_filter_selected.xml tương ứng với trạng thái filter đang được chọn:

Tạo thêm 1 file bg_item_filter_unselected.xml

Như các bạn thấy, ở trạng thái không được chọn, ta sẽ set cho filter đó có 1 background trống trơn.

Ok, mọi thứ liên quan đến layout đã xong, giờ ta sẽ viết adapter cho list filter. Ta tạo package adapter và định nghĩa lớp ListFilterAdapter như sau:

Adapter này cực kỳ đơn giản, nó chỉ chứa 1 interface xử lý sự kiện chọn filter, các bạn hãy tìm hiểu nhé. Ok, như vậy ta đã xây dựng xong adapter, giờ sẽ hiển thị nó lên app.

Hiển thị list filter

Quay trở lại MainActivity, mình sẽ tạo ra 1 mảng các String, mảng này chứa tên các file LUT mà mình sẽ truyền vào các đối tượng FilterData:

Và bây giờ sẽ tạo 1 phương thức setUpListFilterEffect để hiển thị list các filter lên recyclerview:

Như các bạn thấy, phương thức trên khởi tạo ra 1 list các đối tượng FilterData và truyền list đó vào adapter để hiển thị lên recyclerView. Đồng thời ta cũng implement các câu lệnh khi có 1 filter được chọn:

Ok, hy vọng code mình viết đủ rõ ràng để các bạn có thể hiểu. Giờ ta sẽ gọi phương thức setUpListFilterEffect này trong hàm createView:

Chức năng chụp ảnh

Ta sử dụng ButterKnife để bắt sự kiện click vào button chụp ảnh:

Như bạn thấy, khi click vào nút chụp ảnh, ta sẽ lưu lại 1 file jpg trong thư mục FilterImageDemo và nhảy sang màn hình chỉnh sửa ảnh (CameraResultActivity). Ta cũng truyền dữ liệu về filter đang được chọn và đường dẫn ảnh đã lưu sang màn hình chỉnh sửa. Tuy nhiên giờ ta chưa cần quan tâm đến màn hình chỉnh sửa ảnh này. Đơn giản hãy tạo 1 activity có tên CameraResultActivity và khai báo nó trong file AndroidManifest:

Chức năng tùy chọn camera trước (sau)

Ta sử dụng ButterKnife để bắt sự kiện click cho button đảo camera:

Chức năng đóng màn hình camera

Ta sử dụng ButterKnife để bắt sự kiện click cho button thoát khỏi màn hình camera:

Chức năng chọn ảnh trong gallery

Ta viết thêm 1 chức năng cho phép người dùng chọn ảnh trong gallery để chỉnh sửa thay vì chụp ảnh trực tiếp.

Như các bạn thấy khi ấn vào button pick image, ta đơn giản hiển thị màn hình CameraResultActivity. Khác với khi chụp ảnh, ta không truyền thêm dữ liệu nào khi chuyển qua màn hình CameraResultActivity này. Như vậy ở trong lớp CameraResultActivity, ta sẽ cần xử lý 2 trường hợp:

  • Không có data truyền sang (chọn ảnh trong gallery)
  • Có data truyền sang, hiển thị ảnh với các dữ liệu truyền từ màn hình chụp ảnh.

Tổng kết

Như vậy ở bài này mình đã hướng dẫn xong tính năng chụp ảnh. Ở bài tiếp theo (và cũng là bài cuối cùng) mình sẽ hướng dẫn nốt về chức năng chỉnh sửa cũng như chia sẻ ảnh được chọn. Hãy theo dõi nhé.

Source code.

 

 

Hãy chia sẻ

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *