2012-07-02 31 views

Trả lời

31

Như Romain Guy (Google Engineer hoạt động trên bộ công cụ giao diện người dùng) Đã nói trong bài đăng của mình

Bằng cách đặt độ rộng thành wrap_content, bạn đang yêu cầu ListView rộng bằng con rộng nhất. Do đó ListView phải đo các mục của nó và nhận được các mục mà nó phải gọi là getView() trên Adapter. Điều này có thể xảy ra nhiều lần tùy thuộc vào số lượng bố cục, hành vi của bố cục gốc, v.v.

Vì vậy, nếu bạn đặt chiều rộng bố cục hoặc chiều cao bố cục của ListView thành wrap_content thì ListView sẽ thử đo từng chế độ xem gắn liền với nó - chắc chắn không phải thứ bạn muốn.

Lưu ý: tránh thiết wrap_content cho ListViews hoặc GridViews tại mọi thời điểm, để biết thêm chi tiết xem Google I/O video này nói về thế giới của listview

+8

Lời khuyên này không chính xác có vẻ như là phổ biến.Sự kết hợp ListView/Adapater là chung chung hơn và có thể mở rộng hơn so với những người có thể nhận ra lúc đầu, có nghĩa là mọi người cũng có thể không nhận ra hậu quả của việc sử dụng wrap_content với các tập dữ liệu tùy ý. Nhưng điều đó không có nghĩa là không có nhiều trường hợp tập dữ liệu có kích thước cố định hoặc giới hạn. Trong những trường hợp đó, việc sử dụng wrap_content sẽ là một cuộc gọi phán xét nhiều hơn. – spaaarky21

+3

Điều này có vẻ như một cái gì đó lint nên cảnh báo về - nhưng nó hiện không. –

+1

Tôi không biết tại sao câu trả lời này được chấp nhận: nó không trả lời câu hỏi nào cả. Nó cũng vẹt lại bài đăng của Romain's Guy - đó là một câu hỏi hoàn toàn khác: số lần bố cục được đo - và trỏ đến video thực sự giải thích tại sao wrap_content hoạt động, ít nhất là 3 mục danh sách và "loại làm việc "cho các danh sách phức tạp hơn (với chi phí hiệu suất đáng kể). – Rick77

3
I want my list view to wrap its content horizontally and not to fill all the width. 

Trong trường hợp của Danh sách Xem bạn không thể cung cấp cho wrap_content, bởi vì nếu bạn cho wrap_content cho Danh sách Chỉ xem ba mục đầu tiên (hàng) sẽ được hiển thị còn lại sẽ bị bỏ qua .. Vì vậy, don' t sử dụng wrap_content .. Luôn luôn sử dụng fill_parent hoặc match_parent cho Danh sách Xem

đối với thiết kế hiệu quả trên Danh sách Xem bạn có thể thấy điều này World of ListView

+2

Không sử dụng fill_parent. Nó không được chấp nhận trong Android 2.2: http://developer.android.com/reference/android/view/ViewGroup.LayoutParams.html#FILL_PARENT – spaaarky21

29

Để đạt được wrap_content chiều cao trong ListView, chúng ta cần phải sử dụng CustomListView rằng extends bản địa của chúng tôi ListView.

MyListView.java

public class MyListView extends ListView { 

    private android.view.ViewGroup.LayoutParams params; 
    private int oldCount = 0; 

    public MyListView(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) 
    { 
     if (getCount() != oldCount) 
     { 
      int height = getChildAt(0).getHeight() + 1 ; 
      oldCount = getCount(); 
      params = getLayoutParams(); 
      params.height = getCount() * height; 
      setLayoutParams(params); 
     } 

     super.onDraw(canvas); 
    } 

} 

theo quan điểm tùy chỉnh layout sử dụng của bạn như thế này,

Layout.xml

<com.yourpackagename.MyListView 
     ...  
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     ... /> 
+0

Hoạt động hoàn hảo! – beetree

+1

Tuyệt vời! Làm việc cho tôi khi tôi muốn sử dụng một ListView bên trong RecyclerView. – VSG24

+3

Câu trả lời này rất hữu ích, nhưng khi ListView nằm trong RecyclerView, việc cuộn lên dường như bị lỗi. Vì vậy, giải pháp thực sự là ghi đè lên phương pháp onMeasure. Xem câu trả lời này: http://stackoverflow.com/a/24186596/1901561 – RIscRIpt

3

Nó có thể được thực hiện bằng cách sử dụng LinearLayout Tạo như ví dụ này

public class LinearLayoutAdapter { 
LinearLayout linearLayout; 
ArrayList<String> arrayList 
private View rootView; 
private static LayoutInflater inflater; 
public ChoicesAdapter_(ArrayList<String> arrayList ,LinearLayout linearLayout) 
{ 
    this.index =index; 
    this.arrayList=arrayList; 
    this.linearLayout=linearLayout; 
    notifyDataSetChanged(); 
} 
private void notifyDataSetChanged() { 
    linearLayout.removeAllViews(); 
    for (int i =0;i<getCount();i++){ 
     linearLayout.addView(getView(i,null,null)); 
    } 
} 
public int getCount() { 
    return arrayList.size(); 
} 
public Object getItem(int position) { 
    return null; 
} 
public long getItemId(int position) { 
    return 0; 
} 
public View getView(final int position, View convertView, ViewGroup parent) { 
    rootView = inflater.inflate(R.layout.row_list, null); 
    TextView textView = (TextView)rootView.findViewById(R.id.text);  
    textView.setText(arrayList.get(position)); 
    return rootView; 
} 

MainActivity dụ

public class MainActivity extends Activity { 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    ArrayList<String> arrayList = new ArrayList<String>(); 
    arrayList.add("Accent"); 
    arrayList.add("Acclaim"); 
    arrayList.add("Accord"); 
    arrayList.add("Achieva"); 
    arrayList.add("Aerio"); 
    arrayList.add("Aerostar"); 
    LinearLayout linearLayout = (LinearLayout)findViewById(R.id.linearLayout); 
    linearLayoutAdapter= LinearLayoutAdapter(arrayList,linearLayout); 
} 

}

XML ví dụ

<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@android:id/text" 
android:layout_width="match_parent" 
android:layout_height="50dp" 
android:gravity="center" 
android:textColor="@color/dark_gray" 
android:background="@color/white" 
android:textSize="20dp" 
android:text="" /> 
+0

Có, bạn có thể làm điều này, nhưng bạn mất (hoặc có rất nhiều để thực hiện) hệ thống tái chế cho chế độ xem danh sách. Nó hoạt động tốt cho vài mục nhưng, với vài mục bạn có thể xem xét không sử dụng một listview không phải là một adapter. –

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