So sánh Frame và Bounds trong iOS
Để hiểu về frame và bounds, ta có thể định nghĩa nó như sau: Frame của view là vị trí và kích thước của nó, sử dụng hệ thống toạ độ của view cha (view này nằm trong một view cha) Trong khi đó, bounds là vị trí và kích thước của view đó sử dụng hệ thống toạ độ của chính nó. Frame vs Bounds ...
Để hiểu về frame và bounds, ta có thể định nghĩa nó như sau:
- Frame của view là vị trí và kích thước của nó, sử dụng hệ thống toạ độ của view cha (view này nằm trong một view cha)
- Trong khi đó, bounds là vị trí và kích thước của view đó sử dụng hệ thống toạ độ của chính nó.
Frame vs Bounds
Ở bức hình bên trái, view được đặt ở top left của parent view, hình chữ nhật màu vàng đại diện cho frame của view. Ở bức hình bên phải, ta cũng thấy lại view này nhưng lần này, parent view lại không được hiện ra. Đó là do bounds không biết gì về parent view cả, và hình chữ nhật màu đỏ đại diện cho view bounds. Và chấm xanh ở cả hai bức hình đại diện cho điểm gốc của frame và bounds.
Frame origin = (0, 0) awidth = 80 height = 130 Bounds origin = (0, 0) awidth = 80 height = 130
Thật là rối rắm phải không, xem ra thì frame và bounds chẳng khác gì nhau cả???
Bây giờ hãy cùng xem ví dụ tiếp theo, ta sẽ thay đổi origin của frame như sau:
Frame origin = (40, 60) awidth = 80 height = 130 Bounds origin = (0, 0) awidth = 80 height = 130
Bây giờ thì có chút khác biệt rồi nhỉ, sau khi thay đổi toạ độ x-y, frame đã di chuyển khỏi vị trí ban đầu, nhưng nội dung của nó thì vẫn y như vậy. Trong khi đó, bounds vẫn không hề biết gì về sự thay đổi. Đến thời điểm này thì cả awidth và height của cả frame lẫn bounds đều giống nhau. Tuy nhiên nó không phải lúc nào cũng như vậy. Nếu ta xoay view đi 20 độ, nó sẽ không còn giống nhau nữa.
Frame origin = (20, 52) awidth = 118 height = 187 Bounds origin = (0, 0) awidth = 80 height = 130
Ta có thể thấy bounds vẫn y như vậy, nó vẫn không hề biết chuyện gì đã xảy ra, trong khi frame thì thay đổi liên tục. Giờ thì rõ ràng frame và bounds khác nhau lắm rồi phải không?
Ta cần chú ý tới việc transform một view, khi đó frame của nó sẽ không định nghĩa được. Vì vậy, khung hình màu vàng được vẽ ở trên khi xoay hình thực ra không hề tồn tại. Điều đó có nghĩa là nếu cần xoay, scale hoặc làm bất cứ tác vụ transformation nào thì ta không nên sử dụng giá trị của frame. Nhưng vẫn có thể sử dụng được giá trị của bounds. Trong document của Apple có ghi:
Important: If a view’s transform property does not contain the identity transform, the frame of that view is undefined and so are the results of its autoresizing behaviors.
Từ đầu đến giờ, ta nhận thấy rằng origin của bounds luôn nằm ở vị trí (0, 0). Tuy nhiên, nó không bắt buộc phải như vậy. Sẽ như thế nào nếu view có một subview quá lớn để hiển thị? Ta sẽ dùng UIImageView với một ảnh lớn. Dưới đây ta có thể thấy được toàn bộ nội dung của subview:
Frame origin = (40, 60) awidth = 80 height = 130 Bounds origin = (0, 0) awidth = 80 height = 130
Chỉ có góc top left của khung hình được nằm trong bounds của view. Bây giờ nếu ta thay đổi toạ độ của bounds origin như bên dưới:
Frame origin = (40, 60) awidth = 80 height = 130 Bounds origin = (280, 70) awidth = 80 height = 130
Frame vẫn nằm yên một chỗ trong parent view nhưng nội dung bên trong frame đã bị thay đổi, bởi origin của bounds bây giờ đang nằm ở một vị trí khác của view. Đây cũng ý tưởng chính đằng sau UIScrollView và những subclass của nó (TableView, CollectionView...).
Khi nào nên sử dụng frame, khi nào nên sử dụng bounds
Bởi frame liên quan đến vị trí của view trên parent view, nên ta thường sử dụng nó khi cần những thay đổi bên ngoài, như thay đổi awidth hoặc tìm khoảng cách giữa view và top của parent view. Trong khi đó, bounds được sử dụng trong các trường hợp cần những thay đổi bên trong, ví dụ như vẽ hoặc sắp xếp các subview bên trong view. Ngoài ra, bounds còn được dùng để lấy kích thước của view nếu ta đã áp dụng transformation cho nó trước đó.