Hướng dẫn

Giới thiệu Cahier: Một mẫu mới trên GitHub dành cho Android để nâng cao năng suất và khả năng sáng tạo trên màn hình lớn

Đọc trong 11 phút
Chris Assigbe
Kỹ sư Quan hệ với nhà phát triển

Ink API hiện đang ở giai đoạn beta và đã sẵn sàng để tích hợp vào ứng dụng của bạn. Chúng tôi đạt được cột mốc này là nhờ ý kiến phản hồi có giá trị của nhà phát triển, giúp chúng tôi liên tục cải thiện hiệu suất, độ ổn định và chất lượng hình ảnh của API.

Các ứng dụng của Google, chẳng hạn như Google Tài liệu, Pixel Studio, Google Photos, Chrome PDF, Youtube Effect Maker và các tính năng độc đáo trên Android như Khoanh tròn để tìm kiếm đều sử dụng các API mới nhất. 

Để đánh dấu cột mốc này, chúng tôi rất vui mừng thông báo về việc ra mắt Cahier, một ứng dụng mẫu toàn diện để ghi chú, được tối ưu hoá cho các thiết bị Android ở mọi kích thước, đặc biệt là máy tính bảng và điện thoại có thể gập lại.

Cahier là gì?

Cahier ("sổ tay" trong tiếng Pháp) là một ứng dụng mẫu được thiết kế để minh hoạ cách bạn có thể tạo một ứng dụng cho phép người dùng ghi lại và sắp xếp suy nghĩ của họ bằng cách kết hợp văn bản, bản vẽ và hình ảnh. 

Mẫu này có thể đóng vai trò là tài liệu tham khảo hữu ích để nâng cao năng suất và khả năng sáng tạo của người dùng trên màn hình lớn. Lớp học này giới thiệu các phương pháp hay nhất để xây dựng những trải nghiệm như vậy, giúp nhà phát triển nhanh chóng hiểu và áp dụng các API cũng như kỹ thuật mạnh mẽ có liên quan. Bài đăng này sẽ hướng dẫn bạn tìm hiểu các tính năng cốt lõi của Cahier, các API chính và những quyết định về cấu trúc giúp mẫu này trở thành một tài liệu tham khảo hữu ích cho các ứng dụng của riêng bạn.

Các tính năng chính được minh hoạ trong mẫu bao gồm:

  • Tạo ghi chú linh hoạt: Cho biết cách triển khai một hệ thống tạo nội dung linh hoạt hỗ trợ nhiều định dạng trong một ghi chú duy nhất, bao gồm văn bản, bản vẽ tự do và tệp đính kèm hình ảnh.
  • Công cụ vẽ sáng tạo: Triển khai trải nghiệm vẽ có hiệu suất cao và độ trễ thấp bằng cách sử dụng Ink API. Mẫu này cung cấp một ví dụ thực tế về việc tích hợp nhiều cọ vẽ, bộ chọn màu, chức năng huỷ/làm lại và công cụ tẩy.
  • Tích hợp nội dung linh hoạt bằng tính năng kéo và thả: Minh hoạ cách xử lý cả nội dung đến và nội dung đi bằng tính năng kéo và thả. Điều này bao gồm việc chấp nhận hình ảnh được thả từ các ứng dụng khác và cho phép người dùng kéo nội dung ra khỏi ứng dụng của bạn để chia sẻ liền mạch.
  • Sắp xếp ghi chú: Đánh dấu ghi chú là mục yêu thích để truy cập nhanh. Lọc chế độ xem để luôn ngăn nắp.
  • Cấu trúc ưu tiên chế độ ngoại tuyến: Được xây dựng bằng cấu trúc ưu tiên chế độ ngoại tuyến bằng cách sử dụng Room, đảm bảo tất cả dữ liệu được lưu cục bộ và ứng dụng vẫn hoạt động đầy đủ mà không cần kết nối Internet.
  • Hỗ trợ mạnh mẽ nhiều cửa sổ và nhiều phiên bản: Thể hiện cách hỗ trợ nhiều phiên bản, cho phép ứng dụng của bạn chạy trong nhiều cửa sổ để người dùng có thể làm việc trên nhiều ghi chú song song, nâng cao năng suất và khả năng sáng tạo trên màn hình lớn.
  • Giao diện người dùng thích ứng cho mọi màn hình: Giao diện người dùng thích ứng liền mạch với nhiều kích thước và hướng màn hình bằng cách sử dụng ListDetailPaneScaffoldNavigationSuiteScaffold để mang đến trải nghiệm người dùng tối ưu trên điện thoại, máy tính bảng và thiết bị có thể gập lại.
  • Tích hợp sâu với hệ thống: Cung cấp hướng dẫn về cách đặt ứng dụng của bạn làm ứng dụng ghi chú mặc định trên Android 14 trở lên bằng cách phản hồi các ý định Ghi chú trên toàn hệ thống, cho phép nhanh chóng ghi lại nội dung từ nhiều điểm truy cập hệ thống.

Được thiết kế để tăng năng suất và sức sáng tạo trên màn hình lớn

Trong lần ra mắt ban đầu, chúng tôi sẽ tập trung thông báo về một số tính năng cốt lõi giúp Cahier trở thành một nguồn tài nguyên học tập quan trọng cho cả trường hợp sử dụng năng suất và sáng tạo.

Nền tảng của khả năng thích ứng

Cahier được thiết kế để có khả năng thích ứng ngay từ đầu. Mẫu này sử dụng thư viện material3-adaptive, cụ thể là ListDetailPaneScaffoldNavigationSuiteScaffold để điều chỉnh liền mạch bố cục ứng dụng cho phù hợp với nhiều kích thước màn hình và hướng. Đây là một thành phần quan trọng đối với ứng dụng Android hiện đại và Cahier cung cấp một ví dụ rõ ràng về cách triển khai thành phần này một cách hiệu quả.

Giao diện người dùng thích ứng Cahier được tạo bằng thư viện Thích ứng Material 3..gif

Giao diện người dùng thích ứng Cahier được tạo bằng Thư viện thích ứng Material 3

Giới thiệu các API và công cụ tích hợp chính

Mẫu này tập trung vào việc giới thiệu các API năng suất mạnh mẽ mà bạn có thể tận dụng trong các ứng dụng của riêng mình, bao gồm:

Tìm hiểu kỹ hơn về các API chính

Hãy tìm hiểu kỹ hơn về 2 API nền tảng mà Cahier tích hợp để mang đến trải nghiệm ghi chú hàng đầu.

Tạo trải nghiệm viết tự nhiên bằng Ink API

Thao tác nhập bằng bút cảm ứng biến các thiết bị màn hình lớn thành sổ tay và sổ phác thảo kỹ thuật số. Để giúp bạn tạo ra trải nghiệm viết mượt mà và tự nhiên, chúng tôi đã đưa Ink API vào làm nền tảng của mẫu này. Ink API giúp bạn dễ dàng tạo, kết xuất và thao tác với các nét mực đẹp mắt có độ trễ thấp nhất.

Ink API cung cấp một cấu trúc theo mô-đun, vì vậy bạn có thể điều chỉnh API này cho phù hợp với ngăn xếp và nhu cầu cụ thể của ứng dụng. Các mô-đun API bao gồm:

  • Các mô-đun tạo nội dung (Compose – khung hiển thị): Xử lý dữ liệu đầu vào là nét vẽ theo thời gian thực để tạo ra các nét vẽ mượt mà với độ trễ thấp nhất mà thiết bị có thể cung cấp.
    • Trong DrawingSurface, Cahier sử dụng thành phần kết hợp InProgressStrokes mới ra mắt để xử lý bút cảm ứng hoặc dữ liệu đầu vào bằng thao tác chạm theo thời gian thực. Mô-đun này chịu trách nhiệm ghi lại các sự kiện con trỏ và kết xuất nét mực ướt với độ trễ thấp nhất có thể.
  • Mô-đun Strokes (Nét vẽ): Biểu thị dữ liệu đầu vào bằng mực và hình ảnh đại diện của dữ liệu đó.  khi người dùng vẽ xong một đường, lệnh gọi lại onStrokesFinished sẽ cung cấp một đối tượng Stroke đã hoàn tất/khô cho ứng dụng. Đối tượng bất biến này, đại diện cho nét mực đã hoàn thành, sau đó được quản lý trong DrawingCanvasViewModel.
  • Mô-đun kết xuất: Hiển thị hiệu quả các nét mực, cho phép kết hợp các nét mực này với Jetpack Compose hoặc khung hiển thị Android.
  • Các mô-đun cọ (Compose – khung hiển thị): Cung cấp một cách thức khai báo để xác định kiểu hiển thị trực quan của nét vẽ. Các bản cập nhật gần đây (kể từ bản phát hành alpha03) bao gồm một cọ đường nét đứt mới, đặc biệt hữu ích cho các tính năng như chọn bằng công cụ lasso. DrawingCanvasViewModel giữ trạng thái cho currentBrush. Hộp công cụ trong DrawingCanvas cho phép người dùng chọn các họ cọ vẽ khác nhau (chẳng hạn như StockBrushes.pressurePen() hoặc StockBrushes.highlighter()) và thay đổi màu sắc. ViewModel cập nhật đối tượng Brush. Sau đó, đối tượng này được thành phần kết hợp InProgressStrokes dùng cho các nét mới.
  • Các mô-đun hình học (Compose – khung hiển thị): Hỗ trợ thao tác và phân tích nét vẽ cho các tính năng như xoá và chọn.
    • Công cụ tẩy trong hộp công cụ và chức năng trong DrawingCanvasViewModel dựa vào mô-đun hình học. Khi hoạt động, công cụ tẩy sẽ tạo một MutableParallelogram xung quanh đường dẫn cử chỉ của người dùng. Sau đó, công cụ tẩy sẽ kiểm tra các giao điểm giữa hình dạng và hộp giới hạn của các nét hiện có để xác định nét nào cần tẩy, giúp công cụ tẩy hoạt động trực quan và chính xác.
  • Mô-đun Storage: Cung cấp khả năng chuyển đổi tuần tự và chuyển đổi ngược tuần tự hiệu quả cho dữ liệu mực, giúp tiết kiệm đáng kể dung lượng đĩa và mạng. Để lưu bản vẽ, Cahier duy trì các đối tượng Stroke trong cơ sở dữ liệu Room. Trong Converters, mẫu này dùng hàm encode của mô-đun lưu trữ để chuyển đổi tuần tự StrokeInputBatch (dữ liệu thô về điểm) thành ByteArray. Mảng byte, cùng với các thuộc tính của cọ vẽ, được lưu dưới dạng chuỗi JSON. Hàm decode được dùng để tái tạo nét khi một ghi chú được tải.
orion.png

Ngoài các mô-đun cốt lõi này, các bản cập nhật gần đây đã mở rộng chức năng của Ink API:

  • Các API thử nghiệm mới cho các đối tượng BrushFamily tuỳ chỉnh cho phép nhà phát triển tạo ra các loại bút vẽ sáng tạo và độc đáo, mang đến khả năng cho các công cụ như bút vẽ Bút chìBút chỉ.

Cahier sử dụng các cọ tuỳ chỉnh (bao gồm cả cọ nhạc độc đáo được giới thiệu bên dưới) để minh hoạ những khả năng sáng tạo nâng cao.

Tia laser cầu vồng được tạo bằng cọ vẽ tuỳ chỉnh của Ink API..gif

Tia laser cầu vồng được tạo bằng các cọ vẽ tuỳ chỉnh của Ink API

notes.png

Cọ nhạc được tạo bằng cọ tuỳ chỉnh của Ink API

  • Các mô-đun khả năng tương tác Jetpack Compose gốc giúp đơn giản hoá việc tích hợp các chức năng viết tay ngay trong giao diện người dùng Compose để mang lại trải nghiệm phát triển hiệu quả và phù hợp hơn.

Ink API mang lại một số lợi thế khiến API này trở thành lựa chọn lý tưởng cho các ứng dụng cải thiện hiệu suất và sáng tạo so với một quy trình triển khai tuỳ chỉnh:

  • Dễ sử dụng: Ink API giúp bạn không phải xử lý các vấn đề phức tạp về đồ hoạ và hình học, cho phép bạn tập trung vào các tính năng cốt lõi của Cahier.
  • Hiệu suất: Hỗ trợ độ trễ thấp tích hợp và khả năng kết xuất được tối ưu hoá giúp đảm bảo trải nghiệm viết mượt mà và phản hồi nhanh.
  • Tính linh hoạt: Thiết kế theo mô-đun cho phép bạn chọn các thành phần cần thiết, giúp tích hợp liền mạch Ink API vào cấu trúc của Cahier.

Ink API đã được áp dụng trên nhiều ứng dụng của Google, bao gồm cả tính năng đánh dấu trong Tài liệu và tính năng Khoanh tròn để tìm kiếm, cũng như các ứng dụng của đối tác như Orion Notes và Trình quét PDF.

"Ink API là lựa chọn đầu tiên của chúng tôi cho tính năng Khoanh tròn để tìm kiếm (CtS). Nhờ tài liệu phong phú của họ, việc tích hợp Ink API diễn ra rất dễ dàng, cho phép chúng tôi đạt được nguyên mẫu hoạt động đầu tiên chỉ trong vòng một tuần. Nhờ kết cấu cọ tuỳ chỉnh và khả năng hỗ trợ ảnh động của Ink, chúng tôi có thể nhanh chóng lặp lại thiết kế nét vẽ." – Jordan Komoda, Kỹ sư phần mềm – Google

Trở thành ứng dụng ghi chú mặc định có vai trò ghi chú

Ghi chú là một chức năng cốt lõi giúp tăng năng suất của người dùng trên các thiết bị có màn hình lớn. Với tính năng vai trò ghi chú, người dùng có thể truy cập vào các ứng dụng tương thích của bạn từ màn hình khoá hoặc trong khi các ứng dụng khác đang chạy. Tính năng này xác định và đặt các ứng dụng ghi chú mặc định trên toàn hệ thống, đồng thời cấp cho các ứng dụng đó quyền khởi chạy để ghi lại nội dung. 

Triển khai trong Cahier

Việc triển khai vai trò ghi chú bao gồm một số bước chính, tất cả đều được minh hoạ trong mẫu:

  1. Khai báo trong tệp kê khai: Trước tiên, ứng dụng phải khai báo khả năng xử lý ý định ghi chú. Trong AndroidManifest.xml, Cahier có một <intent-filter> cho thao tác android.intent.action.CREATE_NOTE. Điều này báo hiệu cho hệ thống rằng ứng dụng là ứng dụng tiềm năng cho vai trò ghi chú.
  2. Kiểm tra trạng thái vai tròSettingsViewModel sử dụng RoleManager của Android để xác định trạng thái hiện tại. SettingsViewModel kiểm tra xem vai trò ghi chú có trên thiết bị hay không (isRoleAvailable) và Cahier hiện có giữ vai trò đó hay không (isRoleHeld). Trạng thái này được hiển thị cho giao diện người dùng bằng cách sử dụng các luồng Kotlin.
  3. Yêu cầu vai trò: Trong tệp Settings.kt, một Button sẽ xuất hiện với người dùng nếu vai trò có sẵn nhưng chưa được giữ. Khi được nhấp vào, nút này sẽ gọi hàm requestNotesRole trong ViewModel. Hàm này tạo một ý định mở màn hình cài đặt ứng dụng mặc định, nơi người dùng có thể chọn Cahier. Quy trình này được quản lý bằng API rememberLauncherForActivityResult, xử lý việc khởi chạy ý định và nhận kết quả.
  4. Cập nhật giao diện người dùng: Sau khi người dùng quay lại màn hình cài đặt, lệnh gọi lại ActivityResultLauncher sẽ kích hoạt một hàm trong ViewModel để cập nhật trạng thái vai trò, đảm bảo giao diện người dùng phản ánh chính xác việc ứng dụng hiện có phải là ứng dụng mặc định hay không.

Tìm hiểu cách tích hợp vai trò ghi chú vào ứng dụng của bạn trong hướng dẫn tạo ứng dụng ghi chú.

helloworld.png

Cahier ra mắt trong một cửa sổ nổi dưới dạng ứng dụng ghi chú mặc định trên máy tính bảng Lenovo

Một bước tiến lớn: Lenovo cho phép vai trò ghi chú

Chúng tôi rất vui mừng thông báo một bước tiến lớn trong việc nâng cao năng suất trên Android cho màn hình lớn: Lenovo đã hỗ trợ vai trò Ghi chú trên máy tính bảng chạy Android 15 trở lên! Với bản cập nhật này, giờ đây, bạn có thể cập nhật các ứng dụng ghi chú để cho phép người dùng có thiết bị Lenovo tương thích đặt các ứng dụng đó làm mặc định, cấp quyền truy cập liền mạch từ màn hình khoá và mở khoá các tính năng chụp nội dung ở cấp hệ thống.

Cam kết này của một OEM hàng đầu cho thấy vai trò ngày càng quan trọng của ghi chú trong việc mang lại trải nghiệm người dùng thực sự tích hợp và hiệu quả trên Android. 

Nhiều phiên bản, nhiều cửa sổ và cửa sổ kiểu máy tính

Năng suất trên màn hình lớn là khả năng quản lý thông tin và quy trình làm việc một cách hiệu quả. Đó là lý do Cahier được thiết kế để tận dụng tối đa các tính năng nâng cao về cửa sổ của Android, mang đến một không gian làm việc linh hoạt phù hợp với nhu cầu của người dùng. Ứng dụng này hỗ trợ:

  • Chế độ nhiều cửa sổ: Khả năng cơ bản để chạy cùng với một ứng dụng khác ở chế độ chia đôi màn hình hoặc chế độ cửa sổ tuỳ ý. Điều này rất cần thiết cho các tác vụ như tham chiếu một trang web trong khi ghi chú trong Cahier.
  • Nhiều phiên bản: Đây là nơi chế độ đa nhiệm thực sự phát huy tác dụng. Cahier cho phép người dùng mở nhiều cửa sổ độc lập của ứng dụng cùng lúc. Hãy tưởng tượng bạn so sánh hai ghi chú khác nhau cạnh nhau hoặc tham khảo một ghi chú văn bản trong một cửa sổ trong khi làm việc trên bản vẽ trong một cửa sổ khác. Cahier minh hoạ cách quản lý những thực thể riêng biệt này, mỗi thực thể có trạng thái riêng, biến ứng dụng của bạn thành một công cụ mạnh mẽ và đa năng.
  • Tính năng cửa sổ kiểu máy tính: Khi kết nối với màn hình ngoài, chế độ máy tính trên Android sẽ biến máy tính bảng hoặc thiết bị gập thành một máy trạm. Vì Cahier được xây dựng bằng giao diện người dùng thích ứng và hỗ trợ nhiều phiên bản, nên ứng dụng này hoạt động rất tốt trong môi trường này. Người dùng có thể mở, đổi kích thước và định vị nhiều cửa sổ Cahier giống như trên máy tính truyền thống, cho phép thực hiện các quy trình làm việc phức tạp mà trước đây không thể thực hiện trên thiết bị di động.
cahier-desktop-windowing.webp

Cahier chạy ở chế độ cửa sổ trên máy tính trên Pixel Tablet

Sau đây là cách chúng tôi triển khai các tính năng này trong Cahier:

Để bật tính năng nhiều phiên bản, trước tiên, chúng tôi cần báo hiệu cho hệ thống rằng ứng dụng hỗ trợ việc khởi chạy nhiều lần bằng cách thêm thuộc tính PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI vào khai báo MainActivity trong AndroidManifest:

  <activity

    android:name="com.example.cahier.MainActivity"

    android:exported="true"

    android:label="@string/app_name"

    android:theme="@style/Theme.MyApplication"

    android:showWhenLocked="true"

    android:turnScreenOn="true"

    android:resizeableActivity="true"

    android:launchMode="singleInstancePerTask">


    <property

        android:name="android.window.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI"

        android:value="true"/>

    ...

</activity>

Tiếp theo, chúng tôi triển khai logic để khởi chạy một phiên bản mới của ứng dụng. Trong CahierHomeScreen.kt, khi người dùng chọn mở một ghi chú trong cửa sổ mới, chúng tôi sẽ tạo một Intent mới có các cờ cụ thể hướng dẫn hệ thống cách xử lý việc khởi chạy hoạt động mới. Tổ hợp phím FLAG_ACTIVITY_NEW_TASKFLAG_ACTIVITY_MULTIPLE_TASK và FLAG_ACTIVITY_LAUNCH_ADJACENT đảm bảo ghi chú sẽ mở trong một cửa sổ mới, riêng biệt cùng với cửa sổ hiện có.

  fun openNewWindow(activity: Activity?, note: Note) {

    val intent = Intent(activity, MainActivity::class.java)

    intent.putExtra(AppArgs.NOTE_TYPE_KEY, note.type)

    intent.putExtra(AppArgs.NOTE_ID_KEY, note.id)

    intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK or

        Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT


    activity?.startActivity(intent)

}

Để hỗ trợ chế độ nhiều cửa sổ, chúng ta cần báo hiệu cho hệ thống rằng ứng dụng hỗ trợ khả năng đổi kích thước bằng cách đặt phần tử <activity> hoặc <application> của Tệp kê khai.

  <activity

    android:name="com.example.cahier.MainActivity"

    android:resizeableActivity="true"

    ...>

</activity>

Giao diện người dùng được tạo bằng thư viện thích ứng Material 3 cho phép giao diện này thích ứng liền mạch trong các trường hợp nhiều cửa sổ, chẳng hạn như chế độ chia đôi màn hình của Android. 

Để nâng cao trải nghiệm người dùng, chúng tôi đã thêm tính năng hỗ trợ kéo và thả. Hãy xem cách chúng tôi triển khai tính năng này trong Cahier ở bên dưới.

Kéo và thả

Một ứng dụng thực sự năng suất hoặc sáng tạo không hoạt động độc lập mà tương tác liền mạch với phần còn lại của hệ sinh thái thiết bị. Kéo và thả là nền tảng của hoạt động tương tác này, đặc biệt là trên màn hình lớn, nơi người dùng thường làm việc trên nhiều cửa sổ ứng dụng. Cahier hoàn toàn chấp nhận điều này bằng cách triển khai chức năng kéo và thả trực quan cho cả việc thêm và chia sẻ nội dung.

  • Nhập dễ dàng: Người dùng có thể kéo hình ảnh từ các ứng dụng khác (chẳng hạn như trình duyệt web, thư viện ảnh hoặc trình quản lý tệp) rồi thả trực tiếp vào canvas ghi chú. Để làm việc này, Cahier sử dụng đối tượng sửa đổi dragAndDropTarget để xác định vùng thả, kiểm tra nội dung tương thích (chẳng hạn như image/*) và xử lý URI đến.
  • Chia sẻ dễ dàng: Bạn có thể chia sẻ nội dung trong Cahier dễ dàng như chia sẻ nội dung từ các ứng dụng khác. Người dùng có thể nhấn và giữ một hình ảnh trong ghi chú văn bản hoặc nhấn và giữ toàn bộ canvas của ghi chú bản vẽ và hình ảnh kết hợp, rồi kéo hình ảnh đó ra một ứng dụng khác.

Nghiên cứu chuyên sâu về kỹ thuật: Kéo từ canvas vẽ

Việc triển khai cử chỉ kéo trên canvas vẽ đặt ra một thách thức riêng. Trong DrawingSurface, các thành phần kết hợp xử lý dữ liệu đầu vào vẽ trực tiếp (InProgressStrokes của Ink API) và Box phát hiện cử chỉ nhấn và giữ để bắt đầu thao tác kéo là các thành phần kết hợp cùng cấp.

Theo mặc định, hệ thống đầu vào con trỏ Jetpack Compose được thiết kế sao cho chỉ một thành phần kết hợp cùng cấp (thành phần đầu tiên theo thứ tự khai báo trùng với vị trí chạm) nhận được sự kiện. Trong trường hợp của Cahier, chúng ta muốn logic xử lý hoạt động đầu vào kéo và thả có cơ hội chạy và có thể sử dụng các hoạt động đầu vào trước khi thành phần kết hợp InProgressStrokes sử dụng tất cả hoạt động đầu vào chưa được sử dụng để vẽ rồi sử dụng hoạt động đầu vào đó. Nếu chúng ta không sắp xếp mọi thứ theo đúng thứ tự, Box sẽ không phát hiện được cử chỉ nhấn và giữ để bắt đầu thao tác kéo, hoặc InProgressStrokes sẽ không nhận được dữ liệu đầu vào để vẽ.

Để giải quyết vấn đề này, chúng tôi đã tạo một đối tượng sửa đổi pointerInputWithSiblingFallthrough tuỳ chỉnh và đặt Box bằng đối tượng sửa đổi đó trước InProgressStrokes trong mã thành phần kết hợp. Tiện ích này là một trình bao bọc mỏng xung quanh hệ thống pointerInput tiêu chuẩn nhưng có một thay đổi quan trọng: tiện ích này ghi đè hàm sharePointerInputWithSiblings() để trả về true. Điều này cho biết khung Compose cho phép các sự kiện con trỏ truyền đến các thành phần kết hợp anh chị em, ngay cả sau khi được sử dụng.

  internal fun Modifier.pointerInputWithSiblingFallthrough(

    pointerInputEventHandler: PointerInputEventHandler

) = this then PointerInputSiblingFallthroughElement(pointerInputEventHandler)


private class PointerInputSiblingFallthroughModifierNode(

    pointerInputEventHandler: PointerInputEventHandler

) : PointerInputModifierNode, DelegatingNode() {


    var pointerInputEventHandler: PointerInputEventHandler

        get() = delegateNode.pointerInputEventHandler

        set(value) {

            delegateNode.pointerInputEventHandler = value

        }


    val delegateNode = delegate(

        SuspendingPointerInputModifierNode(pointerInputEventHandler)

    )


    override fun onPointerEvent(

        pointerEvent: PointerEvent,

        pass: PointerEventPass,

        bounds: IntSize

    ) {

        delegateNode.onPointerEvent(pointerEvent, pass, bounds)

    }


    override fun onCancelPointerInput() {

        delegateNode.onCancelPointerInput()

    }


    override fun sharePointerInputWithSiblings() = true

}


private data class PointerInputSiblingFallthroughElement(

    val pointerInputEventHandler: PointerInputEventHandler

) : ModifierNodeElement<PointerInputSiblingFallthroughModifierNode>() {


    override fun create() = PointerInputSiblingFallthroughModifierNode(pointerInputEventHandler)


    override fun update(node: PointerInputSiblingFallthroughModifierNode) {

        node.pointerInputEventHandler = pointerInputEventHandler

    }


    override fun InspectorInfo.inspectableProperties() {

        name = "pointerInputWithSiblingFallthrough"

        properties["pointerInputEventHandler"] = pointerInputEventHandler

    }

}

Sau đây là cách sử dụng trong DrawingSurface:

  Box(

    modifier = Modifier

        .fillMaxSize()

        // Our custom modifier enables this gesture to coexist with the drawing input.

        .pointerInputWithSiblingFallthrough {

            detectDragGesturesAfterLongPress(

                onDragStart = { onStartDrag() },

                onDrag = { _, _ -> /* consume drag events */ },

                onDragEnd = { /* No action needed */ }

            )

        }

) 

// The Ink API's composable for live drawing sits here as a sibling.

InProgressStrokes(...)

Với chế độ này, hệ thống sẽ phát hiện chính xác cả nét vẽ và cử chỉ kéo nhấn và giữ cùng một lúc. Sau khi bắt đầu thao tác kéo, chúng ta sẽ tạo một URI content:// có thể chia sẻ bằng FileProvider và truyền URI đó đến khung kéo và thả của hệ thống bằng view.startDragAndDrop(). Giải pháp này đảm bảo trải nghiệm người dùng mạnh mẽ và trực quan, cho thấy cách khắc phục các xung đột cử chỉ phức tạp trong giao diện người dùng theo lớp.

Được xây dựng theo kiến trúc hiện đại

Ngoài các API cụ thể, Cahier còn minh hoạ các mẫu cấu trúc quan trọng để tạo các ứng dụng có chất lượng cao và thích ứng.

Tầng trình bày: Jetpack Compose và khả năng thích ứng

Lớp trình bày được xây dựng hoàn toàn bằng Jetpack Compose. Như đã đề cập, Cahier sử dụng thư viện material3-adaptive để có khả năng thích ứng với giao diện người dùng. Việc quản lý trạng thái tuân theo một mẫu Luồng dữ liệu một chiều (UDF) nghiêm ngặt, với các thực thể ViewModel được dùng làm vùng chứa dữ liệu chứa thông tin ghi chú và trạng thái giao diện người dùng.

Lớp dữ liệu: Kho lưu trữ và Room

Đối với lớp dữ liệu, Cahier sử dụng giao diện NoteRepository để trừu tượng hoá tất cả các thao tác dữ liệu. Lựa chọn thiết kế này cho phép ứng dụng dễ dàng chuyển đổi giữa nguồn dữ liệu cục bộ (Room) và một phần phụ trợ từ xa tiềm năng trong tương lai. Luồng dữ liệu cho một thao tác như chỉnh sửa ghi chú rất đơn giản:

  1. Giao diện người dùng Jetpack Compose sẽ kích hoạt một phương thức trong ViewModel.
  2. ViewModel tìm nạp ghi chú từ NoteRepository, xử lý logic và chuyển ghi chú đã cập nhật trở lại kho lưu trữ.
  3. NoteRepository lưu nội dung cập nhật vào cơ sở dữ liệu Room.

Hỗ trợ toàn diện cho phương thức nhập

Để thực sự là một ứng dụng năng suất mạnh mẽ, ứng dụng phải xử lý nhiều phương thức nhập một cách hoàn hảo. Cahier được xây dựng để tuân thủ nguyên tắc về dữ liệu đầu vào trên màn hình lớn và hỗ trợ:

  • Bút cảm ứng: Tích hợp với Ink API, tính năng chống tì tay, đăng ký vai trò ghi chú, nhập bằng bút cảm ứng trong các trường văn bản và chế độ sống động.
  • Bàn phím: Hỗ trợ hầu hết các phím tắt và tổ hợp phím thường dùng (chẳng hạn như ctrl+nhấp, meta+nhấp) và chỉ báo rõ ràng cho tiêu điểm bàn phím.
  • Chuột và bàn di chuột: Hỗ trợ trạng thái nhấp chuột phải và di chuột.

Hỗ trợ các hoạt động tương tác nâng cao bằng bàn phím, chuột và bàn di chuột là một trọng tâm chính để cải thiện hơn nữa. 

Hãy bắt đầu ngay hôm nay

Chúng tôi hy vọng Cahier sẽ là bệ phóng cho ứng dụng tuyệt vời tiếp theo của bạn. Chúng tôi đã xây dựng ứng dụng này để trở thành một tài nguyên toàn diện, có nguồn mở, minh hoạ cách kết hợp giao diện người dùng thích ứng, các API mạnh mẽ như Ink và vai trò ghi chú, cũng như một cấu trúc hiện đại, thích ứng.

Bạn đã sẵn sàng tìm hiểu sâu hơn?

  • Khám phá mã: Truy cập vào kho lưu trữ GitHub của chúng tôi để khám phá cơ sở mã Cahier và xem các nguyên tắc thiết kế đang hoạt động.
  • Xây dựng ứng dụng của riêng bạn: Sử dụng Cahier làm nền tảng cho ứng dụng ghi chú, đánh dấu tài liệu hoặc ứng dụng sáng tạo của riêng bạn.
  • Đóng góp: Chúng tôi hoan nghênh những nội dung bạn đóng góp! Giúp chúng tôi cải thiện Cahier để trở thành một nguồn tài nguyên hữu ích hơn nữa cho cộng đồng nhà phát triển Android.

Hãy xem hướng dẫn chính thức dành cho nhà phát triển và bắt đầu xây dựng ứng dụng năng suất và sáng tạo thế hệ tiếp theo ngay hôm nay. Chúng tôi rất mong được chiêm ngưỡng tác phẩm của bạn!

Tác giả:

Tiếp tục đọc