Tại sao LayoutInflater bỏ qua các tham số layout_ference và layout_height mà tôi đã chỉ định?


167

Tôi đã gặp sự cố nghiêm trọng khi khiến LayoutInflater hoạt động như mong đợi và những người khác cũng vậy: Làm cách nào để sử dụng layoutinflator để thêm lượt xem khi chạy? .

Tại sao LayoutInflater bỏ qua các tham số bố trí tôi đã chỉ định? Ví dụ: tại sao layout_widthlayout_heightcác giá trị từ tài nguyên XML của tôi không được vinh danh?


Đúng- điều đó có làm tổn thương hay tôi đã chọn sai địa điểm? Chỉ cần nghĩ rằng tôi sẽ chia sẻ kết quả của tôi. Phải thừa nhận hướng dẫn không được đề cập cụ thể của trang faq ..
andig

3
xem đoạn cuối của câu hỏi đầu tiên trong faq. gửi nó như một câu hỏi và sau đó gửi hướng dẫn như một câu trả lời. Tất nhiên, bạn có thể chỉnh sửa câu hỏi này và dán hướng dẫn trong câu trả lời. Tôi sẽ nâng cấp nếu bạn sửa lỗi này.
bigstones

Câu trả lời:


380

Tôi đã điều tra vấn đề này, đề cập đến các tài liệu LayoutInflater và thiết lập một dự án trình diễn mẫu nhỏ. Các hướng dẫn sau đây cho thấy cách tự động điền bố cục bằng cách sử dụng LayoutInflater.

Trước khi chúng ta bắt đầu, hãy xem LayoutInflater.inflate()các tham số trông như thế nào:

  • tài nguyên : ID cho tài nguyên bố cục XML để tải (ví dụ R.layout.main_page:)
  • root : Chế độ xem tùy chọn là cha mẹ của hệ thống phân cấp được tạo (nếu attachToRoottrue) hoặc đơn giản là một đối tượng cung cấp một tập hợp các LayoutParamsgiá trị cho gốc của cấu trúc phân cấp được trả về (nếu attachToRootfalse.)
  • Đính kèm : Có nên gắn hệ thống phân cấp tăng cao vào tham số gốc không? Nếu sai, root chỉ được sử dụng để tạo lớp con chính xác LayoutParamscho chế độ xem gốc trong XML.

  • Trả về : Giao diện gốc của hệ thống phân cấp bị thổi phồng. Nếu root được cung cấp và attachToRoottrue, đây là root; mặt khác, nó là gốc của tệp XML bị thổi phồng.

Bây giờ cho bố trí mẫu và mã.

Bố cục chính ( main.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</LinearLayout>

Được thêm vào thùng chứa này là một TextView riêng biệt, hiển thị dưới dạng hình vuông nhỏ màu đỏ nếu các tham số bố cục được áp dụng thành công từ XML ( red.xml):

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="25dp"
    android:layout_height="25dp"
    android:background="#ff0000"
    android:text="red" />

Bây giờ LayoutInflaterđược sử dụng với một số biến thể của các tham số cuộc gọi

public class InflaterTest extends Activity {

    private View view;

    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

      setContentView(R.layout.main);
      ViewGroup parent = (ViewGroup) findViewById(R.id.container);

      // result: layout_height=wrap_content layout_width=match_parent
      view = LayoutInflater.from(this).inflate(R.layout.red, null);
      parent.addView(view);

      // result: layout_height=100 layout_width=100
      view = LayoutInflater.from(this).inflate(R.layout.red, null);
      parent.addView(view, 100, 100);

      // result: layout_height=25dp layout_width=25dp
      // view=textView due to attachRoot=false
      view = LayoutInflater.from(this).inflate(R.layout.red, parent, false);
      parent.addView(view);

      // result: layout_height=25dp layout_width=25dp 
      // parent.addView not necessary as this is already done by attachRoot=true
      // view=root due to parent supplied as hierarchy root and attachRoot=true
      view = LayoutInflater.from(this).inflate(R.layout.red, parent, true);
    }
}

Các kết quả thực tế của các biến thể tham số được ghi lại trong mã.

TRIỆU CHỨNG: Gọi LayoutInflatermà không chỉ định gốc dẫn đến lạm phát cuộc gọi bỏ qua các tham số bố cục từ XML. Gọi thổi phồng với root không bằng nullattachRoot=truekhông tải các tham số bố trí, nhưng trả lại đối tượng gốc, điều này ngăn các thay đổi bố cục tiếp theo đối tượng được tải (trừ khi bạn có thể tìm thấy nó bằng cách sử dụng findViewById()). Do đó, quy ước gọi mà bạn rất muốn sử dụng là quy ước này:

loadedView = LayoutInflater.from(context)
                .inflate(R.layout.layout_to_load, parent, false);

Để giúp giải quyết các vấn đề về bố cục, Trình kiểm tra Bố cục rất được khuyến khích.


20
Câu trả lời tuyệt vời. Đã làm việc trên Android được 3 năm và vẫn còn nhiều thứ để học hỏi.
Reuben Scratton

Xin chào, có bất kỳ cách nào để làm điều tương tự với mã java thay vì thổi phồng với R.layout. bởi vì tôi không có bố cục Tôi đã tạo chế độ xem bằng mã java và tôi muốn thêm cùng một chế độ xem trong 300 lần.
Raj

1
@andig: Activitylà lớp con của Contextvà các ví dụ của câu trả lời nằm trong phạm vi Activity, vì vậy để đơn giản hơn, tôi đã thay thế getBaseContext()bằng this, vì lợi ích của câu trả lời này, nó tương đương.
Marcin Orleansowski

5
container có layout_ thong và layout_height được đặt thành "match_parent"; sau đó bình luận nói "// result: layout_height = quấn_content layout_creen = match_parent". Tôi có bị mất sth không?
Mary Paździoch

1
Cảm ơn đã làm nghiên cứu và chia sẻ kết quả! Ngoài ra, tôi thứ hai câu hỏi của Marian.
LarsH

5

andig là chính xác rằng một lý do phổ biến cho LayoutInflater bỏ qua layout_params của bạn sẽ là do một gốc không được chỉ định. Nhiều người nghĩ rằng bạn có thể vượt qua trong null cho root. Điều này có thể chấp nhận được đối với một vài tình huống như hộp thoại, nơi bạn không có quyền truy cập vào root tại thời điểm tạo. Tuy nhiên, một nguyên tắc tốt để tuân theo là nếu bạn có root, hãy đưa nó cho LayoutInflater.

Tôi đã viết một bài viết chuyên sâu về blog này mà bạn có thể xem ở đây:

https://www.bignerdranch.com/blog/under Hiểu-androids-layoutinflater-inflate /


1
This is acceptable for a few scenarios such as a dialogđó là tất cả những gì tôi cần
tân binh Nhà phát triển

0

Tôi muốn thêm vào câu trả lời chính ở trên
Tôi đã cố gắng theo dõi nhưng recyclerView của tôi đã bắt đầu kéo dài mọi mục vào màn hình
mà tôi phải thêm dòng tiếp theo sau khi thổi phồng để đạt được mục tiêu

itemLayoutView.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT));

Tôi đã thêm các thông số này bằng xml nhưng nó không hoạt động chính xác
và với dòng này tất cả đều ổn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.