Thẻ 'bao gồm' của Android XML Layout có thực sự hoạt động không?


84

Tôi không thể ghi đè các thuộc tính khi sử dụng <include> trong các tệp bố cục Android của mình. Khi tôi tìm kiếm lỗi, tôi tìm thấy Vấn đề bị Từ chối 2863 :

"thẻ include bị hỏng (ghi đè các thông số bố cục không bao giờ hoạt động)"

Vì Romain chỉ ra rằng điều này hoạt động trong các dãy phòng thử nghiệm và các ví dụ của anh ấy, nên tôi phải làm sai điều gì đó.

Dự án của tôi được tổ chức như thế này:

res/layout
  buttons.xml

res/layout-land
  receipt.xml

res/layout-port
  receipt.xml

Các button.xml chứa một cái gì đó như sau:

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

  <Button .../>

  <Button .../>
</LinearLayout>

Và các tệp biên lai .xml dọc và ngang trông giống như sau:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">

  ...

  <!-- Overridden attributes never work. Nor do attributes like
       the red background, which is specified here. -->
  <include
      android:id="@+id/buttons_override"
      android:background="#ff0000"
      android:layout_width="fill_parent"
      layout="@layout/buttons"/>

</LinearLayout>

Tôi đang thiếu gì?


Câu hỏi này được đề cập đến bởi các công cụ dành cho nhà phát triển Android khi bạn cố gắng sử dụng bao gồm theo cách không được hỗ trợ.
ThomasW

Câu trả lời:


132

Tôi chỉ tìm thấy vấn đề. Đầu tiên, bạn chỉ có thể ghi đè các thuộc tính layout_ *, vì vậy nền sẽ không hoạt động. Đó là hành vi được ghi lại và chỉ đơn giản là sự giám sát của tôi.

Vấn đề thực sự được tìm thấy trong LayoutInflater.java:

// We try to load the layout params set in the <include /> tag. If
// they don't exist, we will rely on the layout params set in the
// included XML file.
// During a layoutparams generation, a runtime exception is thrown
// if either layout_width or layout_height is missing. We catch
// this exception and set localParams accordingly: true means we
// successfully loaded layout params from the <include /> tag,
// false means we need to rely on the included layout params.
ViewGroup.LayoutParams params = null;
try {
   params = group.generateLayoutParams(attrs);
} catch (RuntimeException e) {
   params = group.generateLayoutParams(childAttrs);
} finally {
   if (params != null) {
     view.setLayoutParams(params);
   }
}

Nếu thẻ <include> không bao gồm cả layout_width và layout_height, thì RuntimeException sẽ xảy ra và được xử lý âm thầm, thậm chí không có bất kỳ câu lệnh nhật ký nào.

Giải pháp là luôn bao gồm cả layout_width và layout_height khi sử dụng thẻ <include>, nếu bạn muốn ghi đè bất kỳ thuộc tính layout_ * nào.

Ví dụ của tôi sẽ thay đổi thành:

<include
      android:id="@+id/buttons_override"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      layout="@layout/buttons"/>

33
Chuyện này thật vớ vẩn. Tôi chưa bao giờ có thể làm cho điều này hoạt động và thậm chí tôi đã thấy tài liệu đề cập đến việc cần cả chiều cao và chiều rộng nếu cố gắng ghi đè các kích thước, mà tôi đã giả định là chiều cao và chiều rộng. Tuy nhiên, tất cả những gì tôi đang cố gắng ghi đè là lợi nhuận, không thực sự là một thứ nguyên. Tại sao tôi cần phải chỉ định cả hai hoặc thậm chí bất kỳ cái nào trong số đó khi tất cả những gì tôi muốn thay đổi là layout_marginRight? Grrr, Android, đôi khi bạn làm tôi thất vọng quá.
Artem Russakovskii

1
FYI Android Lint sẽ cung cấp cho bạn một lỗi (thông số Layout layout_height bỏ qua trừ khi layout_width cũng được xác định trên <include> tag) nếu bạn không trọng cả chiều cao và chiều rộng thuộc tính
nhị phân

10

Tôi đã gửi một yêu cầu nâng cao để cho phép ghi đè tất cả các thuộc tính đã bao gồm:

Giả sử tôi có hai bố cục giống nhau khác với giá trị của một TextViewtrường. Hiện tại, tôi đã sửa đổi bố cục trong thời gian chạy hoặc sao chép XML.

Ví dụ để truyền hai tham số có giá trị "hello" và "world" vào layout1:

<include layout="@layout/layout1a" params="textView=hello|editText=world" />

layout1a.xml:

<merge><TextView text="@param/textView"><EditText hint="@param/editText"></merge>

Việc triển khai thay thế sẽ phá vỡ tính đóng gói và sẽ cho phép câu lệnh include ghi đè các giá trị như:

<include layout="@layout/layout1b" overrides="@id/textView.text=hello|@id/editText.hint=world" />

layout1b.xml:

<merge><TextView id="@+id/textView"><EditText hint="@+id/editText"></merge>


1
Cân nhắc những thứ databinding mới, <include>được sử dụng thậm chí thường xuyên hơn bây giờ, attr trọng là một tính năng thực sự phải có
Dmitry Gryazin

1

Tôi thấy rằng đôi khi tôi bỏ lỡ việc bao gồm thẻ android: id khi sử dụng trình tạo GUI trong Eclipse. Đảm bảo (khi tôi nhận thấy) rằng tôi thêm vào TextView từ trình tạo, id tôi đang sử dụng trong bố cục ListView.

<TextView android:text="@+id/textView1"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" />
...

trở thành

<TextView android:id="@+id/textView1"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" />
...

Thay vì nhận được 'false' 'false', tôi nhận được :) và bao gồm hoạt động ok.

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.