Header ads

Header ads
» » Tại sao lại sử dụng thuộc tính fitsSystemWindow trong lập trình Android?

Hôm nay nhân dịp đang làm task về "immersive fullscreen mode" trong công ty, mình xin viết một bài chia sẻ về một thuộc tính khá liên quan. Đó là fitsSystemWindow.




Tại sao chúng ta lại sử dụng fitsSystemWindow?

System windows (system bars) là một phần của màn hình, nơi hệ thống Android vẽ ra những View không-thể-tương-tác (trong trường hợp của StatusBar) hay là những View có-thể-tương-tác-được (như là ToolbarNavigationBar).

Trong Android Developers Docs ghi rằng:
 - android:fitsSystemWindow là một thuộc tính nội bộ kiểu boolean để điều chỉnh view layout dựa theo System windows (như là StatusBar,..). Nếu nó được set là true, Android sẽ tự động điều chỉnh lại paddding của View đó sao cho nó chừa đủ khoảng trống dành cho các System windows. Tuy nhiên nó chỉ có tác dụng đối với các view không phải là embeded-Activity. (Là các Activity đươc host ngay trong một Activity khác, ví dụ như TabHost/TabActivity. Trong thực tế các embeded-Activity tồn tại ở LocalActivityManager của Activity mẹ, giống như FragmentManager cho phép bạn hiển thị một Activity này trong một Activity khác.). Bởi vì chúng bị giới hạn bởi diện tích được cấp bởi Activity mẹ).
Toolbar bị vẽ dưới StatusBar

Đa phần thời gian, ứng dụng của bạn sẽ không cần phải được vẽ ở dưới StatusBar hay NavigationBar, tuy nhiên nếu bạn muốn: bạn cần phải chắc chắn rằng những thành phần giao diện mà có-thể-tương-tác-được (như Button, EditText,..) không bị "ẩn" bên dưới các System windows. Đó cũng là hành vi (behaviour) mặc định mà thuộc tính android:fitsSystemWindows=“true” cung cấp cho bạn: và như mình đã trích dẫn ở trên, nó set lại padding của View để đảm bảo nội dung không bị che bởi các System windows.

Một số thứ cần lưu ý:
  • fitsSystemWindows được áp dụng theo chiều sâu dạng "deep first" - có quan trọng thứ tự: View đầu tiên nhận được insets sẽ thay đổi.
  • Insets (viền) luôn quan hệ và tỉ lệ với toàn cửa sổ trên màn hình: insets có thể được áp dụng ngay cả trước quá trình parse và tạo layout được diễn ra. Vậy nên đừng nghĩ rằng hệ thống Android có chút ít thông tin gì về vị trí của View khi dựa vào thuộc tính fitsSystemWindows để thiết lập padding cho View đó.
  • Và dĩ nhiên, vì nó không có chút thông tin gì nên mọi padding khác mà bạn set cho View đó đều bị ghi đè (overwritten): bạn hãy chú ý rằng mọi thuộc tính như paddingLeft/padding/paddingBottom đều bị ghi đè và không còn hiệu lực khi bạn áp dụng android:fitsSystemWindow = "true".
Và, trong nhiều trường hợp, như là một trình phát video full screen, bạn cần một View full màn hình, không có thuộc tính, và một ViewGroup mang thuộc tính android:fitsSystemWindow = "true" để chứa View full màn hình mà bạn cần thiết lập insets.

Hoặc có thể bạn muốn RecyclerView của mình scroll xuống và vẽ ẩn bên dưới thanh NavigationBar, đồng thời biến màu nền của NavigationBar thành trong suốt - bằng cách sử dụng thuộc tính android:fitsSystemWindow = "true" kết hợp vớiandroid:clipToPadding = "false". Các nội dung bên trong RecyclerView của bạn sẽ nằm bên dưới NavigationBar, tuy nhiên nếu bạn scroll xuống đến cuối cùng thì thấy item cuối của RecyclerView vẫn được thiết lập padding bottom và nằm phía trên NavigationBar (còn tốt hơn là nó bị che khuất và ẩn bên dưới nhiều nhỉ :D)


Tùy biến fitsSystemWindows

Ở phiên bản Android KitKat hoặc thấp hơn, một custom View của bạn có thể override lại hàm fitsSystemWindows(Rect insets) và thay vào đó bất kì phương thức nào bạn muốn, chỉ việc return true; nếu bạn muốn "nuốt" (consume) những viền insets hoặc false nếu bạn muốn cho những View khác một cơ hội "chạm tay vào điều ước" :D

Tuy nhiên, kể từ phiên bản Android LollipopGoogle cung cấp thêm một số APIs mới để cho việc tùy biến tính năng này dễ dàng hơn và phù hợp hơn với các hành vi, tính năng hiện có khác của View. Thay vì như ở trên, bạn sẽ overrideonApplyWindowInsets() thứ sẽ cho phép View có thể tùy biến giữ lấy bao nhiêu phần viền insets tùy ý, ngoài ra bạn còn có thể gọi hàm dispatchWindowInsets() lên các View con khi cần thiết.

Và tốt hơn cả là bạn sẽ không phải đau đầu hay hack não khi phải subclass những Views của mình để custom các hành vi cho Views như trên ở các phiên bản Android Lollipop hoặc cao hơn. Bạn có thể dùngViewCompat.setOnApplyWindowInsetsListener(), thứ có thể cho tham chiếu đến onApplyWindowInsets() của View.ViewCompat còn cung cấp các hàm helper để gọi onApplyWindowInsets() và dispatchWindowInsets() mà không cần kiểm tra version.


Các ví dụ về tùy biến fitsSystemWindows

Trong khi các layouts cơ bản (FrameLayout, RelativeLayout, LinearLayout,..) đang sử dụng hành vi mặc định của mình, thì có rất nhiều layouts khác đã tùy biến sẵn những hành vi mà nó thực hiện khi gặp fitsSystemWindows(), nhờ đó có thể đáp ứng được một số trường hợp usecase cụ thể.

Một ví dụ điển hình ở đây là navigation drawer, thứ cần phải phủ ra cả màn hình, và được vẽ dưới một StatusBar có màu nền trong suốt. 


Ở đây DrawerLayout sử dụng thuộc tính fitsSystemWindows() như là một dấu hiệu rằng nó muốn dịch chuyển viền của những View con (như là main content view), nhưng vẫn vẽ StatusBar bình thường với màu nền được định sẵn trongcolorPrimaryDark của theme, nhằm tuân theo qui tắc của Material design.

Nếu bạn chú ý một chút có thể thấy rằng trên các thiết bị chạy Android Lollipop trở lên,  DrawerLayout luôn gọi hàmdispatchApplyWindowsInsets() cho từng View con mà nó chứa, qua đó cho phép những View con đó cũng có thể nhậnfitsSystemWindows, khác với hành vi mặc định của nó trên các phiển bản trước (là đơn giản "nuốt" những viền insets đó, và những View con của nó không bao giờ có thể chạm tới fitsSystemWindows).

CoordinatorLayout cũng được cải tiến và có thể override cái cách mà nó "xử lý" những viền window insets - cho phép những hành vi được thiết lập ở những View con có thể đánh chặn (intercept) và thay đổi cách thức mà chúng hành động khi gặp window insets - trước khi gọi hàm dispatchApplyWindowInsets() lên mỗi View con. Nó cũng sử dụng thuộc tínhfitsSystemWindows như là một biến cờ (flag) để xác định cách thức mà nó sẽ vẽ màu nền của StatusBar.

Tương tự, CollapsingToolbarLayout tìm fitsSystemWindows trong các thuộc tính của nó để quyết định vẽ content scrim - là những gì được vẽ chồng lên khoảng trống của StatusBar và Toolbar khi CollapsingToolbarLayout được scroll dài ra phủ xuống màn hình.

Nếu bạn vẫn hứng xem những trường hợp phổ biến liên quan đến Design Library, hãy thử nhìn qua ứng dụng mẫucheesesquare sau.


Sử dụng hệ thống Android, đừng chống lại nó!

Một thứ cần phải luôn nhớ trong đầu rằng thuộc tính này không phải được gọi là fitsStatusBar hay fitsNavigationBar. Bất cứ thứ gì cấu thành System Windows, thì kích thước (dimensions) và vị trí của nó có thể thay đổi khi chạy trên các nền tảng, phiên bản khác nhau. Ví dụ rõ ràng nhất, bạn hãy nhìn vào những điểm khác nhau khi chạy ứng dụng trên Android Honeycomb và Ice Cream Sandwich.

Cuối cùng các bạn hãy yên tâm rằng, phần viền insets mà bạn lấy đi từ fitsSystemWindow sẽ đúng với mọi phiên bản platform để chắc chắn rằng những nội dung trong layout của bạn không bị xếp chồng với những thành phần giao diện UI cung cấp bởi hệ thống - hay chắc chắn rằng bạn sẽ tránh đưa ra bất kì giả định nào về tính khả dụng hoặc kích cỡ nếu bạn tùy biến hành vi mặc định của nó.

Chào các bạn! Chúc các bạn học tốt!
Học viện Đào tạo Trực Tuyến
Public group · 10280 members
Chia sẻ kiến thức, kinh nghiệm giúp bạn có nhiều trải nghiệm và kiến thức hơn


Khóa học Phân tích dữ liệu sử dụng Microsoft Power BI

Khóa học Phân tích dữ liệu sử dụng Power Query trong Excel
HƯỚNG DẪN THIẾT KẾ QUẢNG CÁO VÀ ĐỒ HỌA CHUYÊN NGHIỆP VỚI CANVA
Hãy tham gia khóa học để trở thành người chuyên nghiệp. Tuyệt HAY!😲👍
 Khoa hoc hay
http://hoc.elearninghaiphong.com/main/noidungkhoahoc/15

GOOGLE SPREADSHEETS phê không tưởng
 Khoa hoc hay


Khóa hoc lập trình bằng Python tại đây



Nếu bạn muốn tạo video chuyên nghiệp và sáng tạo hãy tham gia khóa học HƯỚNG DẪN TỰ TẠO VIDEO CLIP CHUYÊN NGHIỆP SÁNG TẠO

 Xây dựng website​​​​

Hacker mũ trắng




Hãy tham gia khóa học để biết mọi thứ

Để tham gia tất cả các bài học, Bạn nhấn vào đây 
Khóa học sử dụng Adobe Presenter-Tạo bài giảng điện tử
 Khoa hoc hay
http://hoc.elearninghaiphong.com/main/noidungkhoahoc/71

Cập nhật công nghệ từ Youtube tại link: https://www.youtube.com/channel/UCOxeYcvZPGf-mGLYSl_1LuA/videos
Để tham gia khóa học công nghệ truy cập link: http://thuvien.hocviendaotao.com
Mọi hỗ trợ về công nghệ email: dinhanhtuan68@gmail.com

About Học viện đào tạo trực tuyến

Xinh chào bạn. Tôi là Đinh Anh Tuấn - Thạc sĩ CNTT. Email: dinhanhtuan68@gmail.com .
- Nhận đào tạo trực tuyến lập trình dành cho nhà quản lý, kế toán bằng Foxpro, Access 2010, Excel, Macro Excel, Macro Word, chứng chỉ MOS cao cấp, IC3, tiếng anh, phần mềm, phần cứng .
- Nhận thiết kế phần mềm quản lý, Web, Web ứng dụng, quản lý, bán hàng,... Nhận Thiết kế bài giảng điện tử, số hóa tài liệu...
HỌC VIỆN ĐÀO TẠO TRỰC TUYẾN:TẬN TÂM-CHẤT LƯỢNG.
«
Next
Bài đăng Mới hơn
»
Previous
Bài đăng Cũ hơn