[Học Android] Tại sao nên sử dụng FragmentContainerView để chứa fragment thay vì FrameLayout?

[Học Android] Tại sao nên sử dụng FragmentContainerView để chứa fragment thay vì FrameLayout?

Hiện nay FragmentContainerView (FCV) luôn được khuyến nghị sử dụng để chứa fragment thay vì FrameLayout như trước đây. Cùng tìm hiểu lý do tại sao và cách sử dụng FCV trong bài viết hôm nay nhé.

I. Dẫn nhập

FragmentContainerView (FCV) hiện tại luôn được khuyến nghị sử dụng để chứa fragment thay vì sử dụng FrameLayout như trước đây. Bên cạnh việc xử lý quan hệ của các fragment, FCV còn bổ sung thêm nhiều tính năng phối hợp với trạng thái của Fragment. Trong bài viết này, chúng ta sẽ tìm hiểu FCV là gì? cách tương tác với FCV và một số vấn đề về animation của Fragment đã được khắc phục khi dùng với FCV.

II. Nội dung chính

1. FCV là gì?

FCV là một dạng custom-view được mở rộng từ FrameLayout, nhưng khác với các ViewGroups khác, FCV chỉ chấp nhân các fragment view. FCV không những hỗ trợ các thuộc tính của mà còn cung cấp thêm nhiều FragmentTransaction một cách linh hoạt.

2. Đưa view vào FCV

  • FragmentContainerView.addView(view) chỉ nên gọi với một view được gắn với Fragment, view này nhận được bởi Fragment.onCreateView(LayoutInflater, ViewGroup, boolean).
  • Khi view của Fragment được khởi tạo, một tag được gán cho nó để liên kết với instance của Fragment bằng cách gọi View.setTag(R.id.fragment_container_view_tag, fragment). Khi FragmentContainerView.addView(View) được gọi, tag của view sẽ được lấy khi gọi View.getTag(R.id.fragment_container_view_tag).
  • IllegalStateException sẽ xảy ra khi chúng ta thêm các loại view khác cho FCV.

3. Đưa fragment vào FCV

  • Bởi vì FCV là một subclass của FrameLayout nên fragment có thể được thêm vào giống như FrameLayout.
supportFragmentManager.beginTransaction()
    .add(R.id.fragmentContainerView, myFragment)
    .commit()
  • Một cách khác để đưa fragment vào FCV là sử dụng thuộc tính android:name trong file XML
  • Quá trình khởi tạo này diễn ra bên trong MyFragment bằng các sử dụng FragmentStore (điều này rất hữu ích nếu hàm khởi tạo của MyFragment cần các đối số) và sau đó thực hiện một FragmentTransaction để thêm nó vào container.
  • FCV cho phép linh hoạt thay thế các fragment (giống như khi chúng ta sử dụng FrameLayout) và điều này hoàn toàn khác với tag – không cho phép thay thế fragment đã định nghĩa cố định trong XML thông qua FragmentTransaction.
  • Một cách cuối cùng để thêm fragment vào FCV là sử dụng thuộc tính class trong XML

4. Các thuộc tính trong XML của FCV

  • FCV hỗ trợ các thuộc tính giống như tag.
  • id: thuộc tính bắt buộc nếu FCV khởi tạo một static fragment trong trường hợp thuộc tính android:name hoặc class được cung cấp. IllegalStateException sẽ được xuất ra nếu không tìm thấy id. Tuy nhiên, nếu thuộc tính  android:name hoặc class không được khai báo thì id sẽ trở thành tùy chọn.
  • tag: thuộc tính tùy chọn để liên kết tag với Fragment. Fragment có thể lấy ra bằng các gọi FragmentManager.findFragmentByTag(tag).
  • animateLayoutChanges: Khi được set là true thì UnsupportedOperationException sẽ được thông báo đối với Android API 18 trở lên vì layout animation phải bị vô hiệu hóa với FCV trên các phiên bản API này vì chúng có thể xung đột với các animationtransition được đặt trong các API của Fragment. Tuy nhiên, với API 17 trở xuống, ViewGroup.setLayoutTransition(LayoutTransition)  phải được gọi để các Fragment transition hoạt động chính xác.

5. FCV và các animation chuyển đổi.

  • Trước đây, việc cố gắng tùy chỉnh enterexit animation của các Fragment đã gây ra sự cố trong đó Fragment enter sẽ nằm bên dưới Fragment exit cho đến khi nó hoàn toàn thoát khỏi màn hình. Điều này dẫn đến những hiệu ứng khó chịu khi chuyển đổi giữa các Fragment.
  • FCV khắc phục vấn đề này bằng cách đảm bảo rằng các Fragmentexit animation sẽ được vẽ trước, điều này dẫn đến các Fragmententer animation sẽ được vẽ lên trên cùng.
  • Animation chuyển đổi vẫn có thể được thiết lập bằng cách gọi FragmentTransaction.setCustomAnimation().
supportFragmentManager.beginTransaction()
    .setCustomAnimations(R.anim.slide_in_from_right, R.anim.slide_out_to_left,
        R.anim.slide_in_from_left, R.anim.slide_out_to_right)
    .replace(R.id.fragmentContainerView, myFragment)
    .commit()

III. Tổng kết

Cảm ơn bạn đã đọc bài viết.

Chào thân ái và quyết thắng!

admin

Leave a Reply

Your email address will not be published. Required fields are marked *