Android: Truy cập các chế độ xem con từ ListView


108

Tôi cần tìm ra vị trí pixel của một phần tử trong danh sách được hiển thị bằng cách sử dụng a ListView. Có vẻ như tôi nên lấy một trong các TextView và sau đó sử dụng getTop(), nhưng tôi không thể tìm ra cách để có được chế độ xem con của a ListView.

Cập nhật: Các con của ViewGroupkhông tương ứng 1-1 với các mục trong danh sách, vì a ListView. Thay vào đó, con ViewGroupcủa chúng chỉ tương ứng với những chế độ xem có thể nhìn thấy ngay bây giờ. Vì vậy, getChildAt()hoạt động trên một chỉ mục nội bộ ViewGroupvà không nhất thiết phải liên quan đến vị trí trong danh sách ListViewsử dụng.

Câu trả lời:


215

Xem: Android ListView: lấy chỉ mục dữ liệu của mục hiển thị và kết hợp với một phần câu trả lời của Feet ở trên, có thể cung cấp cho bạn một cái gì đó như:

int wantedPosition = 10; // Whatever position you're looking for
int firstPosition = listView.getFirstVisiblePosition() - listView.getHeaderViewsCount(); // This is the same as child #0
int wantedChild = wantedPosition - firstPosition;
// Say, first visible position is 8, you want position 10, wantedChild will now be 2
// So that means your view is child #2 in the ViewGroup:
if (wantedChild < 0 || wantedChild >= listView.getChildCount()) {
  Log.w(TAG, "Unable to get view for desired position, because it's not being displayed on screen.");
  return;
}
// Could also check if wantedPosition is between listView.getFirstVisiblePosition() and listView.getLastVisiblePosition() instead.
View wantedView = listView.getChildAt(wantedChild);

Lợi ích là bạn không lặp lại các phần tử con của ListView, điều này có thể ảnh hưởng đến hiệu suất.


10
Câu trả lời tuyệt vời, nhưng không hoàn toàn hoạt động khi bạn có các chế độ xem tiêu đề trong danh sách của mình. Nhiệm vụ firstPositionphải là int firstPosition = listView.getFirstVisiblePosition() - listView.getHeaderViewsCount();để khắc phục điều này.
pospi

@pospi: cảm ơn, điểm tốt! Tôi đã cập nhật câu trả lời của mình để giải thích cho điều đó.
Joe

Câu trả lời hay và hiệu quả trong hầu hết các trường hợp, nhưng tôi không hiểu tại sao bạn lại tin rằng các chế độ xem con xuất hiện theo thứ tự của chúng trong mảng các chế độ xem con. Vì các chế độ xem có thể được sử dụng lại, làm thế nào chúng ta có thể chắc chắn rằng chế độ xem đầu tiên không đại diện cho chế độ xem hiển thị cuối cùng?
Victor Denisov

2
@VictorDenisov: điều này chỉ có thể xảy ra trên chuỗi giao diện người dùng; do đó luồng giao diện người dùng sẽ bị chặn trong khi mã này đang thực thi, do đó các chế độ xem con là cố định và sẽ không được sửa đổi. ListViewđã được xử lý "di chuyển" các quan điểm con xung quanh sau khi tái chế cũ convertViews, vv, vì vậy bạn có thể được đảm bảo rằng ListView.getChildAt(0) trên thực tế quan điểm đầu tiên đính kèm từ adapter. Nó có thể không hoàn toàn có thể nhìn thấy (và có thể thậm chí không được hiển thị ở tất cả, tùy thuộc vào ListView's ngưỡng 'tầm nhìn' trước khi tái chế một cái nhìn mà nó coi là 'cuộn ngoài tầm nhìn')
Joe

1
@Matheus đó không phải là cách Android ListView hoạt động. Nếu mục danh sách là tắt màn hình, xem nó đã được tái chế và tái sử dụng cho một trong các mục danh sách khác mà trên màn hình. Bạn nên nghĩ lại cách bạn đang sử dụng ListView nếu đó là một yêu cầu.
Joe

17

Mã này dễ sử dụng hơn:

 View rowView = listView.getChildAt(viewIndex);//The item number in the List View
    if(rowView != null)
        {
           // Your code here
        }

9
không hoạt động luôn luôn. getChildAt được tính từ hàng hiển thị đầu tiên, không tính từ đầu dữ liệu.
SteelBytes 13/10/12

13
Đối số ViewID là khó hiểu. Đó là một chỉ số (hoặc vị trí). ID chế độ xem là một số nguyên hoàn toàn tùy ý do công cụ aapt tạo ra.
Johan Pelgrim,

6

Tìm kiếm nhanh các tài liệu cho lớp ListView đã hiển thị các phương thức getChildCount () và getChildAt () được kế thừa từ ViewGroup. Bạn có thể lặp lại chúng bằng cách sử dụng chúng không? Tôi không chắc nhưng nó đáng để thử.

Tìm thấy nó ở đây


1
Tôi đã thử điều này, để thực hiện các lựa chọn. Nó thường hoạt động nhưng đôi khi có những lỗi riêng lẻ và nó không đáng tin cậy. Tôi sẽ không giới thiệu nó.
Timmmm

Cảm ơn Timmmm, tôi đã không thực sự thử nó chỉ tìm thấy nó trong tài liệu.
Feet

5
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, final View view, int position, long id) {
        View v;
        int count = parent.getChildCount();
        v = parent.getChildAt(position);
        parent.requestChildFocus(v, view);
        v.setBackground(res.getDrawable(R.drawable.transparent_button));
        for (int i = 0; i < count; i++) {
            if (i != position) {
                v = parent.getChildAt(i);
                v.setBackground(res.getDrawable(R.drawable.not_clicked));
            }
        }
    }
});

Về cơ bản, tạo hai Bản vẽ - một trong suốt và một có màu mong muốn. Yêu cầu tiêu điểm tại vị trí được nhấp ( int positionnhư đã xác định) và thay đổi màu của hàng đã nói. Sau đó, đi qua cha mẹ ListViewvà thay đổi tất cả các hàng khác cho phù hợp. Điều này giải thích khi người dùng nhấp vào listviewnhiều lần. Điều này được thực hiện với bố cục tùy chỉnh cho mỗi hàng trong ListView. (Rất đơn giản, chỉ cần tạo một tệp bố cục mới với TextView- không đặt có thể lấy tiêu điểm hoặc có thể nhấp!).

Không cần bộ điều hợp tùy chỉnh - sử dụng ArrayAdapter


getChildAt có liên quan đến các mục được cuộn hiện tại. Điều này sẽ ngừng hoạt động nếu bạn cuộn danh sách của mình một chút.
nurettin

4
int position = 0;
listview.setItemChecked(position, true);
View wantedView = adapter.getView(position, null, listview);

1
Xây dựng một chút
innoSPG

-9

Điều này giả sử bạn biết vị trí của phần tử trong ListView:

  View element = listView.getListAdapter().getView(position, null, null);

Sau đó, bạn sẽ có thể gọi getLeft () và getTop () để xác định các phần tử trên vị trí màn hình.


43
getView()được gọi nội bộ bởi ListView, khi điền danh sách. Bạn không nên sử dụng nó để lấy chế độ xem ở vị trí đó trong danh sách, vì việc gọi getView()với null vì convertViewnguyên nhân khiến bộ điều hợp thổi phồng một chế độ xem mới từ tài nguyên bố cục của bộ điều hợp (không nhận được chế độ xem đã được hiển thị).
Joe

1
Vị trí chẵn sẽ là một vị trí trong màn hình trực quan, không phải vị trí nguồn dữ liệu của bộ điều hợp.
Vikas

@jasonhudgins Đây là phương pháp tôi đang sử dụng vì tôi nghĩ nó là tốt nhất nhưng khi tôi cố gắng làm cho thanh tiến trình trong chế độ xem con trở nên vô hình, nhưng thay vào đó, nó làm cho tất cả các thanh tiến trình trong listvew trở nên vô hình ........ tất cả đều ở trong tất cả các câu trả lời được chấp nhận đã làm các trick
Edijae Crusar
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.