Làm cách nào tôi có thể gán ID cho chế độ xem theo chương trình?


202

Trong tệp XML, chúng ta có thể gán ID cho chế độ xem như android:id="@+id/something"sau đó gọi findViewById(), nhưng khi tạo chế độ xem theo chương trình, làm cách nào để tôi gán ID?

Tôi nghĩ rằng setId()không giống như phân công mặc định. setId()là thêm

Ai có thể sửa cho tôi?


1
Tập hợp con: cách tạo ID duy nhất: stackoverflow.com/questions/1714297/
triệt

Câu trả lời:


521

idTổng quan về Android

Android idlà một số nguyên thường được sử dụng để xác định chế độ xem; điều này idcó thể được chỉ định thông qua XML (khi có thể) và thông qua mã (theo chương trình.) Điều idnày hữu ích nhất để có được các tham chiếu cho các định nghĩa XML được Viewtạo bởi một Inflater(chẳng hạn như bằng cách sử dụng setContentView.)

Chỉ định idquaXML

  • Thêm một thuộc tính của android:id="@+id/somename "vào quan điểm của bạn.
  • Khi ứng dụng của bạn được xây dựng, android:idsẽ được chỉ định một mã duy nhất int để sử dụng trong mã.
  • Tham khảo của bạn android:id's intgiá trị trong mã sử dụng ' R.id.somename'(một cách hiệu quả là một hằng số.)
  • điều này intcó thể thay đổi từ bản dựng sang bản dựng để không bao giờ sao chép id từ gen/gói.name / R.java, chỉ cần sử dụng " R.id.somename".
  • (Ngoài ra, một idgán cho một Preferencetrong XML không được sử dụng khi Preferencetạo nó View.)

Gán idqua mã (lập trình)

  • Đặt thủ công ids bằng cách sử dụng someView.setId(int);
  • Điều này intphải là tích cực, nhưng nếu không thì tùy ý - nó có thể là bất cứ điều gì bạn muốn (tiếp tục đọc nếu điều này là đáng sợ.)
  • Ví dụ: nếu tạo và đánh số một số lượt xem đại diện cho các mục, bạn có thể sử dụng số mục của chúng.

Tính độc đáo của ids

  • XMLids được gán sẽ là duy nhất.
  • Mã giao ids làm không phải là duy nhất
  • Mã giao ids lon (theo lý thuyết) mâu thuẫn với XML-assigned ids.
  • Những mâu thuẫn idnày sẽ không thành vấn đề nếu được truy vấn chính xác (tiếp tục đọc) .

Khi nào (và tại sao) xung đột idkhông quan trọng

  • findViewById(int)sẽ lặp lại theo chiều sâu đệ quy đầu tiên thông qua hệ thống phân cấp chế độ xem từ Chế độ xem bạn chỉ định và trả về kết quả đầu tiên Viewtìm thấy với kết quả khớp id.
  • Miễn là không có mã được gán mã nào được idgán trước một định nghĩa XML idtrong cấu trúc phân cấp, findViewById(R.id.somename)sẽ luôn trả về Chế độ xem do XML xác định id.

Tự động tạo chế độ xem và chỉ định IDs

  • Trong bố cục XML, định nghĩa một khoảng trống ViewGroupvới id.
  • Chẳng hạn như LinearLayoutvới một android:id="@+id/placeholder".
  • Sử dụng mã để điền vào chỗ dành sẵn ViewGroupvới Views.
  • Nếu bạn cần hoặc muốn, chỉ định bất kỳ ids nào thuận tiện cho mỗi chế độ xem.
  • Truy vấn các khung nhìn con này bằng cách sử dụng placeholder.findViewById (thuận tiện);

  • API 17 được giới thiệu View.generateViewId()cho phép bạn tạo một ID duy nhất.

Nếu bạn chọn giữ các tham chiếu cho các quan điểm của mình xung quanh , hãy chắc chắn khởi tạo chúng với getApplicationContext()và đảm bảo đặt từng tham chiếu thành null onDestroy. Rõ ràng rò rỉ các Activity(treo vào nó sau khi được bị phá hủy) là lãng phí .. :)

Dự trữ một XML android:idđể sử dụng trong mã

API 17 được giới thiệu View.generateViewId() tạo ra một ID duy nhất. (Cảm ơn các cơ hội thay đổi đã chỉ ra điều này.) *

Nếu bạn ViewGroupkhông thể xác định thông qua XML (hoặc bạn không muốn nó), bạn có thể bảo lưu id qua XML để đảm bảo nó vẫn duy nhất:

Ở đây, giá trị / ids.xml định nghĩa một tùy chỉnh id:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="reservedNamedId" type="id"/>
</resources>

Sau đó, khi Viewgroup hoặc View đã được tạo, bạn có thể đính kèm id tùy chỉnh

myViewGroup.setId(R.id.reservedNamedId);

idVí dụ mâu thuẫn

Để rõ ràng bằng cách ví dụ che giấu, hãy xem xét điều gì xảy ra khi có idxung đột đằng sau hậu trường.

layout / mylayout.xml

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

Để mô phỏng một cuộc xung đột, giả sử bản dựng mới nhất của chúng ta được gán R.id.placeholder( @+id/placeholder) một intgiá trị là 12 ..

Tiếp theo, MyActivity.java xác định một số lượt xem theo chương trình (thông qua mã):

int placeholderId = R.id.placeholder; // placeholderId==12
// returns *placeholder* which has id==12:
ViewGroup placeholder = (ViewGroup)this.findViewById(placeholderId);
for (int i=0; i<20; i++){
    TextView tv = new TextView(this.getApplicationContext());
    // One new TextView will also be assigned an id==12:
    tv.setId(i);
    placeholder.addView(tv);
}

Vì vậy placeholder, một trong TextViewhai người mới của chúng tôi có id12 người! Nhưng đây không thực sự là vấn đề nếu chúng tôi truy vấn các quan điểm con của trình giữ chỗ:

// Will return a generated TextView:
 placeholder.findViewById(12);

// Whereas this will return the ViewGroup *placeholder*;
// as long as its R.id remains 12: 
Activity.this.findViewById(12);

*Không tệ lắm


9
Ngoài ra, điều này có thể hữu ích cho ai đó trong việc mã hóa các giải pháp tương tự để biết về View.generateViewId () trong API> 17 cho các ID không xung đột
AllDayAmazed

Lưu ý rằng việc findViewByIdkhám phá theo chiều sâu, vì vậy "Miễn là không có id được gán mã nào được gán ở trên id được xác định XML trong cấu trúc phân cấp" không đúng về mặt kỹ thuật; đó là "trước" chứ không phải "ở trên".
Karu

Trong các phiên bản gần đây hơn của các công cụ dành cho nhà phát triển Android, lập trình đặt ID thành giá trị tùy ý sẽ được gắn cờ là lỗi trình biên dịch. Giá trị được dự kiến ​​là một ID tài nguyên thực tế.
ThomasW

Tôi tin rằng đây thậm chí là trường hợp khi tôi trả lời điều này năm năm trước - đó là lý do tại sao id tùy chỉnh phải được xác định ids.xml. Đối với ID thực sự độc đoán, hãy sử dụng View.generateViewId()(API 17). (Vui lòng làm rõ quan điểm của bạn nếu tôi bỏ lỡ nó.)
CodeShane

> (Ngoài ra, một id được gán cho Tùy chọn trong XML không được sử dụng khi Tùy chọn tạo Chế độ xem của nó.) Rất quan tâm đến điều đó. Mã của tôi thừa hưởng từ PreferenceDialogFragmentCompatnó có vẻ như id từ R.idkhông khớp với phân cấp xem. Bằng cách này, tôi không thể tìm thấy chế độ xem bằng ID.
UrK

6

Bạn chỉ có thể sử dụng View.setId(integer)cho việc này. Trong XML, mặc dù bạn đang đặt id chuỗi, điều này được chuyển đổi thành số nguyên. Do đó, bạn có thể sử dụng bất kỳ Số nguyên (dương) nào cho việc Views bạn thêm lập trình.

Theo Viewtài liệu

Mã định danh không phải là duy nhất trong hệ thống phân cấp của chế độ xem này. Mã định danh phải là một số dương.

Vì vậy, bạn có thể sử dụng bất kỳ số nguyên dương nào bạn thích, nhưng trong trường hợp này có thể có một số lượt xem với id tương đương. Nếu bạn muốn tìm kiếm một số khung nhìn trong phân cấp gọi tới setTag với một số đối tượng chính có thể có ích.

Tín dụng cho câu trả lời này .


5

Có, bạn có thể gọi setId(value)trong bất kỳ chế độ xem nào với bất kỳ giá trị số nguyên (dương) nào bạn muốn và sau đó tìm thấy nó trong vùng chứa cha bằng cách sử dụng findViewById(value). Lưu ý rằng việc gọi setId()với cùng một giá trị cho các chế độ xem anh chị em khác nhau là hợp lệ , nhưng findViewById()sẽ chỉ trả về lần đầu tiên.


1
Lưu ý rằng bạn phải sử dụng một số nguyên lớn hơn 0.
Peter Ajtai

mặc dù findViewById (int) sẽ lặp lại theo cách đệ quy thông qua hệ thống phân cấp chế độ xem từ Chế độ xem bạn chỉ định và trả về Chế độ xem đầu tiên mà nó tìm thấy với id phù hợp được chỉ định trong câu trả lời đầu tiên là chính xác nhất.
Aniket Thakur

Vâng, kêu gọi findViewByIdmột tổ tiên đã biết là một ý tưởng tốt cho lý do hiệu suất, nhưng nó không đảm bảo nó sẽ tìm thấy một đứa trẻ ngay lập tức nếu có một ID có ID chính xác.
Karu
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.