Khi nhận được tiêu điểm, Activity
sẽ được yêu cầu
vẽ bố cục.
Khung Android sẽ xử lý quy trình vẽ, nhưng
Activity
phải cung cấp
nút gốc của hệ phân cấp bố cục.
Quá trình vẽ bắt đầu bằng nút gốc của bố cục. Nút này được yêu cầu để đo lường và
vẽ cây bố cục. Quá trình vẽ được xử lý bằng cách đi theo từng phần của cây và
kết xuất từng View
giao với khu vực không hợp lệ. Đổi lại, mỗi
ViewGroup
chịu trách nhiệm yêu cầu vẽ
từng phần tử con
(bằng phương thức draw()
)
và mỗi View
chịu trách nhiệm vẽ chính nó.
Vì cây đã được sắp xếp sẵn theo kiểu tuyến dẫn,
nghĩa là, phần tử mẹ sẽ được vẽ trước (tức là phía sau) phần tử con của mình, còn phần tử
đồng cấp được vẽ theo thứ tự xuất hiện trên cây của các phần tử đó.
Lưu ý: Khung này không vẽ các đối tượng View
không ở
trong khu vực hợp lệ, đồng thời
sẽ đảm nhiệm việc vẽ nền View
giúp bạn.
Bạn có thể buộc View
vẽ bằng cách gọi
invalidate()
.
Vẽ bố cục là một quá trình gồm hai lượt: lượt đo lường và lượt bố cục.
Lượt đo lường
Lượt đo lường được triển khai trong measure(int, int)
và được thực hiện từ trên xuống trên cây View
. Mỗi View
sẽ đẩy thông số kỹ thuật về kích thước xuống cây
trong quá trình đệ quy. Khi kết thúc lượt đo lường, mọi
View
đều đã lưu trữ
số đo của mình. Lượt thứ hai xảy ra trong
layout(int, int, int, int)
và cũng theo chiều từ trên xuống. Trong
lượt này, mỗi phần tử mẹ chịu trách nhiệm xác định vị trí của tất cả các phần tử con tương ứng
bằng cách sử dụng kích thước đã tính toán được trong lượt đo lường.
Khi phương thức
measure()
của đối tượng View
được trả về, bạn phải đặt các giá trị getMeasuredWidth()
và
getMeasuredHeight()
của đối tượng đó, cùng với
các giá trị này cho mọi phần tử con cháu của đối tượng View
đó.
Các giá trị chiều rộng đo được và
chiều cao đo được của đối tượng View
phải tuân theo quy tắc ràng buộc do
phần tử mẹ của đối tượng View
áp đặt. Điều này đảm bảo rằng,
khi kết thúc lượt đo lường, mọi phần tử mẹ sẽ chấp nhận
tất cả các số đo của phần tử con tương ứng. Phần tử mẹ View
có thể gọi
measure()
nhiều lần
ở phần tử con. Ví dụ: phần tử mẹ có thể đo lường mỗi phần tử con một lần bằng
kích thước chưa xác định để tìm ra xem phần tử con muốn lớn đến mức nào rồi gọi
lại measure()
trên các phần tử con đó bằng
con số thực tế nếu tổng kích thước không bị ràng buộc
của tất cả phần tử con quá lớn hoặc quá nhỏ (nghĩa là nếu phần tử con
không tự thống nhất với nhau
về mức dung lượng mà mỗi phần tử con nhận được thì phần tử mẹ
sẽ can thiệp và đặt ra quy tắc trong lượt thứ hai).
Lượt đo lường sử dụng hai lớp để truyền đạt các kích thước. Lớp
ViewGroup.LayoutParams
được đối tượng
View
sử dụng để cho phần tử mẹ biết
cách đo lường và vị trí mong muốn. Lớp
ViewGroup.LayoutParams
cơ sở chỉ
mô tả kích thước mong muốn của View
cho cả
chiều rộng và chiều cao. Đối với mỗi
kích thước, lượt đo lường có thể xác định một trong các mục sau:
- một số chính xác
MATCH_PARENT
, nghĩa làView
muốn lớn bằng phần tử mẹ (trừ đi khoảng đệm)WRAP_CONTENT
, nghĩa làView
muốn vừa đủ lớn để chứa trọn nội dung của mình (cộng với khoảng đệm).
ViewGroup.LayoutParams
có các lớp con tương ứng với
nhiều lớp con của ViewGroup
.
Ví dụ: RelativeLayout
có lớp con riêng là
ViewGroup.LayoutParams
có
khả năng căn giữa các đối tượng con View
theo chiều ngang và chiều dọc.
Các đối tượng MeasureSpec
dùng để đẩy
yêu cầu xuống cây theo chiều từ phần tử mẹ xuống
phần tử con. MeasureSpec
có thể ở một trong
ba chế độ sau:
UNSPECIFIED
: Được phần tử mẹ sử dụng để xác định kích thước mong muốn của phần tử conView
. Ví dụ:LinearLayout
có thể gọimeasure()
trên phần tử con với chiều cao được đặt làUNSPECIFIED
và chiều rộng củaEXACTLY
là 240 để tìm hiểu xem phần tử conView
muốn có chiều cao là bao nhiêu với chiều rộng là 240 pixel.EXACTLY
: Được phần tử mẹ sử dụng để áp đặt kích thước chính xác lên phần tử con. Phần tử con phải dùng kích thước này và đảm bảo rằng tất cả các phần tử con cháu của mình sẽ nằm vừa khít bên trong kích thước này.AT MOST
: Được phần tử mẹ sử dụng để áp đặt kích thước tối đa lên phần tử con. Phần tử con phải đảm bảo rằng bản thân và tất cả các phần tử con cháu của mình sẽ nằm vừa khít bên trong kích thước này.
Lượt bố cục
Để bắt đầu chạy bố cục, hãy gọi requestLayout()
.
Phương thức này thường được
View
gọi trên chính nó khi
cho rằng không còn vừa bên trong
các giới hạn hiện tại của nó nữa.