2010-11-02 26 views
39

Có thể vẽ lại một hàng trong một ListView không? Tôi có một ListView với các hàng là LinearLayout s. Tôi nghe một sự thay đổi ưu tiên và đôi khi tôi chỉ cần thay đổi một số View bên trong LinearLayout của một hàng. Có cách nào để làm cho nó vẽ lại hàng mà không gọi listview.notifyDatasetChanged()?Vẽ lại một hàng trong một chế độ xem danh sách

Tôi đã thử gọi view.invalidate() trên chế độ xem (bên trong LinearLayout) nhưng không vẽ lại hàng.

+1

"Có cách nào để làm cho nó vẽ lại hàng đó mà không cần gọi listview.notifydatasetchanged()?" - Chỉ cần tìm nó như là một phần tử con của 'ViewGroup' (trong trường hợp này là' ListView') và sửa đổi nó. "Tôi đã thử gọi view.invalidate() trên khung nhìn (bên trong linearlayout) nhưng nó không vẽ lại hàng." - bạn có chắc là bạn có hàng thích hợp không? Bạn thậm chí không cần phải gọi 'invalidate()', AFAIK. – CommonsWare

+1

Tôi chắc chắn có hàng phù hợp và chế độ xem phù hợp. Tôi nghĩ rằng vấn đề của tôi là người nghe ưu tiên của tôi đang bị thu gom rác. Tôi đã thay đổi nó vì vậy tôi gọi notifyDataSetChanged() trong onResume() của hoạt động của tôi, để giải quyết vấn đề mà tôi đang cố sửa chữa. – Falmarri

Trả lời

105

Như Romain Guy explained a while lại trong Google I/O session, cách hiệu quả nhất để chỉ cập nhật một cái nhìn trong một danh sách xem là một cái gì đó như sau (cái này cập nhật toàn bộ View dữ liệu):

ListView list = getListView(); 
int start = list.getFirstVisiblePosition(); 
for(int i=start, j=list.getLastVisiblePosition();i<=j;i++) 
    if(target==list.getItemAtPosition(i)){ 
     View view = list.getChildAt(i-start); 
     list.getAdapter().getView(i, view, list); 
     break; 
    } 

Giả sử target là một mục của bộ điều hợp.

Mã này truy xuất ListView, sau đó duyệt các chế độ xem hiện tại, so sánh mục target bạn đang tìm với từng mục được hiển thị và nếu mục tiêu của bạn nằm trong số đó, hãy xem chế độ xem và thực hiện bộ điều hợp getView() xem để làm mới màn hình.

Như một mặt lưu ý invalidate() không hoạt động giống như một số người mong đợi và sẽ không làm mới xem như getView() không, notifyDataSetChanged() sẽ xây dựng lại toàn bộ danh sách và kết thúc gọi getview() cho mỗi mặt hàng trưng bày và invalidateViews() cũng sẽ ảnh hưởng đến một bó.

Một điều cuối cùng, bạn cũng có thể nhận được hiệu suất bổ sung nếu chỉ cần thay đổi con của chế độ xem hàng và không phải toàn bộ hàng như getView.Trong trường hợp đó, các mã sau đây có thể thay thế list.getAdapter().getView(i, view, list); (ví dụ để thay đổi một văn bản TextView):

((TextView)view.findViewById(R.id.myid)).setText("some new text"); 

trong mã chúng tôi tin tưởng.

+0

Bạn có thể thêm liên kết vào phiên Google I/O chính nó không? Tôi muốn kiểm tra toàn bộ phiên. – uthark

+0

+1 thx cho điều này, thú vị của nó - im giả sử nó hoạt động như của bạn đi qua xem hiện tại trong như convertView arg và nó sẽ có các yếu tố xem thiết lập lại - rất đẹp – Dori

+0

Không nên ở đây là i

0

Đặt một số thẻ trên hàng bạn muốn cập nhật. Khi bạn muốn vẽ lại mà xem hoặc hàng cụ thể sau đó làm

ListView lv = (ListView)findViewById(....) 

và sau đó

View v = lv.findViewWithTag(tagobject); 

và sau đó bạn làm bất cứ điều gì bạn muốn với quan điểm.

6

view.invalidate() không hoạt động đối với tôi. Nhưng điều này hoạt động như một nét duyên dáng:

giả sử bạn đang cập nhật vị trí "position" trong hàng. if tránh các công cụ vẽ lại kỳ lạ, như nhắn tin văn bản khi bạn đang cập nhật một hàng không có trong màn hình.

  if (position >= listView.getFirstVisiblePosition() 
       && position <= listView.getLastVisiblePosition()) { 

        runOnUiThread(new Runnable() { 
         @Override 
         public void run() { 
          listView.invalidateViews(); 
         } 
        }); 
      } 
+1

Nó đang làm việc dude :) nhưng có vẻ như để tạo lại tất cả các hàng ... bất kỳ cách nào để tạo lại hàng duy nhất ?? –

3

Romain Guy đã trả lời cho câu hỏi này tại "Google IO 2010 Thế giới của ListView" video tại thời điểm chính xác nơi câu hỏi này đã được hỏi: http://www.youtube.com/watch?feature=player_detailpage&v=wDBM6wVEO70#t=3149s

Vì vậy, theo Romain Guy, nên hoạt động, và tôi nghĩ chúng ta có thể tin tưởng anh ta.

Lý do khiến chế độ xem của bạn không được vẽ lại là một chút bí ẩn. Có thể thử vô hiệu hóa tất cả các tùy chọn bộ nhớ cache có sẵn trong ListView

setAnimationCacheEnabled(false); 
setScrollingCacheEnabled(false); 
setChildrenDrawingCacheEnabled(false); 
setChildrenDrawnWithCacheEnabled(false); 
+1

Đây không phải là những gì anh ta nói. Anh ta nói rằng phương thức getView vẫn sẽ được gọi nhưng khi tạo ra ui, công cụ có thể thấy rằng các dữ liệu của các mục đã không thay đổi và sau đó sử dụng lại chúng. –

Các vấn đề liên quan