2012-07-06 33 views
36

Như trong, ELEMENTS của ListView có phải là Fragments hay không. Tôi biết rằng bạn có thể gán một TextView XML cho một ListView để thay đổi cách nó trông, nhưng bạn có thể thêm Fragments vào một ListView không.ListView có thể chứa Fragments

Ví dụ: Tôi có Phân đoạn. XML cho biết Fragment chứa một ImageView, một vài TextView kiểu lớn và một TextView kiểu nhỏ. Mã lớp Fragment nhận được một Bundle, sau đó dựa trên các nội dung populates TextViews và ImageView cho phù hợp. Cả hai đoạn mã XML và đoạn mã làm việc mà không có vấn đề (tôi có thể hiển thị một mảnh riêng lẻ tốt). Tôi có một FragmentActivity, trong đó tôi muốn hiển thị danh sách các mảnh vỡ nói trên. Đây là mã tôi đang sử dụng để cố gắng điền vào ListView bên trong Chế độ xem của FragmentActivity:

ArrayList<Fragment> fragList = new ArrayList<Fragment>(); 
    Fragment fragment = Fragment.instantiate(this, TileItem.class.getName()); 
    Bundle bundle = new Bundle(); 
    bundle.putInt("key", 0); 
    fragment.setArguments(bundle); 
    fragList.add(fragment); 

    ArrayAdapter<Fragment> adapter = new ArrayAdapter<Fragment>(this, R.layout.tile_item, fragList); 
    listItems.setAdapter(adapter); 

Đây là chế độ suy nghĩ của tôi về điều này. Tôi tạo một ArrayList of Fragments để giữ tất cả các khung nhìn được tạo ra của tôi. Sau đó tôi tạo một Fragment, tạo một Bundle, thêm dữ liệu vào Bundle (để Fragment có thể sắp xếp dữ liệu vào View của nó một cách chính xác), thêm Bundle vào Fragment, sau đó thêm Fragment vào ArrayList. Sau đó, tôi tạo một ArrayAdapter, thêm bố cục phần tử mà tôi muốn sử dụng và danh sách các Mảnh vỡ mà tôi đã tạo; sau đó đặt ListView để đọc từ bộ điều hợp của tôi.

Bất kỳ ai chạy mã này sẽ có khả năng nhận được NPE @ instantiating ArrayAdapter. Đưa cái gì? Điều này thậm chí có thể? Trước khi tôi tiếp tục làm hỏng bộ não của mình, ai đó có thể cho tôi biết nếu tôi chỉ lãng phí thời gian của mình? Có cách nào tốt hơn? Tôi đã nghĩ đến việc sử dụng một ScrollView, nhưng rất nhiều các chức năng của một ListView sẽ cần phải thực hiện lại và tôi ghét-ghét-ghét phát minh lại bánh xe khi nó không cần thiết.

Nhờ bất kỳ ai đọc và đặc biệt cảm ơn bạn đã suy nghĩ nếu bạn quyết định rời bỏ chúng. Tôi đã thử tìm kiếm xung quanh cho một câu trả lời thành lập này, nhưng tất cả tôi dường như tìm được những câu hỏi/trang web liên quan đến việc sử dụng một ListView INSIDE của một Fragment; không sử dụng Fragments AS ELEMENTS của ListView

Chỉnh sửa: Tôi đã lấy các đề xuất bên dưới và bắt đầu điều tra thêm. Từ cách mọi thứ xuất hiện, tôi sẽ có thể sử dụng một adapter tùy chỉnh làm phồng ra các mảnh thay vì chỉ đơn giản là xây dựng từ XML (vì thiếu một cách tốt hơn để mô tả quá trình) Tuy nhiên, thực hiện hiện tại của tôi là ném NPE khi cố gắng thiết lập bộ điều hợp.

Đây là mã bộ chuyển đổi tùy chỉnh của tôi (rút ngắn cho ngắn gọn):

public class AdapterItem extends ArrayAdapter<Fragment> { 

Context c; 
List<Fragment> f; 

public AdapterItem(Context c, List<Fragment> f) { 
    super(c, R.layout.tile_item, f); 
    this.c = c; 
    this.f = f; 
} 

@Override 
public View getView(int pos, View v, ViewGroup vg) { 
    LayoutInflater i = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    return i.inflate(R.layout.tile_item, vg, false); 
} 

}

và đây là cách tôi đang thực hiện điều đó:

ArrayList<Fragment> fragList = new ArrayList<Fragment>(); 
    Fragment fragment = Fragment.instantiate(this, TileItem.class.getName()); 
    Bundle bundle = new Bundle(); 
    bundle.putInt("key", 0); 
    fragment.setArguments(bundle); 
    fragList.add(fragment); 

    AdapterItem adapter = new AdapterItem(this, fragList); 
    adapter.add(fragment); 
    listItems.setAdapter(adapter); 

Vì vậy, nó được một vài ngày và tôi khá chắc chắn chủ đề này đã được chôn cất. Tuy nhiên, tôi nghĩ rằng tôi sẽ thêm một bản cập nhật cuối cùng chỉ trong trường hợp ai đó muốn thử này và tìm kiếm google mang lại cho họ ở đây. Vì vậy, trong việc thực hiện của tôi, tôi nhận được một NPE khi ListView được cung cấp bộ điều hợp. Nó không có một bác sĩ phẫu thuật tên lửa để tìm ra rằng nó chắc chắn là bộ chuyển đổi và không phải là ListView ném lỗi. Đối với cuộc sống của tôi, tôi không thể tìm ra lý do tại sao mặc dù ...

Dù sao đi nữa, tôi nghĩ tôi có một số ý tưởng. Đầu tiên, một câu chuyện nhỏ: Một thời gian trở lại tôi đã cố gắng để làm cho FragmentTransactions bên trong một FragmentDialog. Mỗi khi tôi cố gắng làm như vậy, tôi sẽ nhận được một NPE. Cuối cùng, thông qua nhiều nghiên cứu, tôi phát hiện ra rằng lý do liên quan đến cách mà các mảnh vỡ được thể hiện. Khi một Fragment được gọi là nó cần bối cảnh từ cha mẹ của nó. Vì cha mẹ của một Dialog là Activity đã khởi động nó, nên Dialog không đáp ứng được các tiêu chí cần thiết.Tôi tin rằng, khi cố gắng thêm phân đoạn vào một ListView, đây cũng là trường hợp. Kể từ khi ListView không đáp ứng thỏa thuận với instancing một Fragment nó ném NPE và do đó, để lại cho tôi treo và trở lại với các công ước. D @ mn ... Tôi đã thực sự hy vọng tôi sẽ có thể làm điều này. Việc sử dụng Fragments thay vì XML đơn giản sẽ giúp việc tổ chức/tìm kiếm dễ dàng hơn thông qua danh sách. Oh well ... đoán nó không thể được thực hiện trong trường hợp bất cứ ai đang tự hỏi.

+2

Tại sao bạn thậm chí * muốn * mảnh vỡ được "ELEMENTS của một ListView"? Các nhà phát triển đã tạo ra 'ListView' trong nhiều năm mà không có yếu tố của họ là những mảnh vỡ. Bạn đang mong đợi điều gì từ việc biến chúng trở thành những mảnh vỡ? – CommonsWare

+1

Vâng, đối với một trong những tôi mong đợi để có thể hiển thị nhiều hơn chỉ là một TextView đơn giản bên trong một danh sách (trên thực tế tôi sẽ có thể hiển thị một hình ảnh, và thêm một vài dòng văn bản). Ngoài ra, tôi sẽ có thể tái sử dụng mã phân đoạn hơn và hơn từ các hoạt động khác nhau mà không cần sao chép mã. Tôi cũng đã thấy danh sách cuộn các mục có nhiều động hơn là một TextView đơn giản (như các danh sách trong Google Play, chúng phức tạp hơn chỉ là một TextView). Làm thế nào là đạt được? Sẽ không có hiệu ứng tương tự có thể (một cách dễ dàng hơn) bằng cách sử dụng một Fragment? – user1449018

+3

Bạn có thể làm điều đó bằng cách sử dụng Bộ điều hợp và Chế độ xem tùy chỉnh được tăng từ XML cho các hàng của bạn. –

Trả lời

8

Tôi muốn nói rằng điều này không thể thực hiện khi đặt một đoạn trong ListView có nghĩa là đoạn có thể được nhân trên nhiều vùng chứa. Khi bạn sử dụng FragmentManager để tạo một đoạn, nó được gắn thẻ với một mã định danh, làm cho nó trở nên đơn giản để tải lại và sắp xếp lại về định hướng và các thay đổi cấu hình khác. Nó cũng khuyến khích sử dụng trên nhiều cấu hình thiết bị.

Phân đoạn thực sự là một tập hợp con của Hoạt động. Bạn có bao giờ có Hoạt động như một phần của danh sách không? Chắc chắn không (nên là câu trả lời!) !!!

Hơn nữa, nó không phải là rất hữu ích để đính kèm() và tách() một mảnh liên tục khi chúng di chuyển vào và ra khỏi tầm nhìn (các tế bào được tái chế). Đây là tất cả các hoạt động tốn kém mà một ListView không nên giải quyết. Danh sách sẽ cuộn nhanh.

Từ cuộc hội thoại trên các nhận xét, tôi có thể thấy bạn muốn đạt được mã tốt đẹp với sự tách biệt tốt về mã thiết lập chế độ xem và bộ điều hợp trong Hoạt động. Làm như vậy với một trong hai cách:

  1. Ghi đè lớp View và vẽ tùy chỉnh và thiết lập ở đó.
  2. Tạo một lớp mới, trong đó bạn cung cấp bối cảnh và tập dữ liệu cần thiết để giúp bạn quay lại chế độ xem danh sách cần hiển thị - đây là những gì tôi thường làm.
  3. Có lớp Utils để tạo video của bạn ở nơi khác (ngớ ngẩn).

Chỉ không sử dụng Phân đoạn trong Danh sách. Không phải trường hợp sử dụng mà họ đang nhắm đến. HTH.

3

Bạn không cần sử dụng Phân đoạn.

Viết ViewAdapter tùy chỉnh và làm cho nó có bố cục phức tạp hơn (hoặc có thể bố cục phức tạp hơn nếu bạn cần thực sự ưa thích) rồi điền vào các trường của bố cục nếu cần.

[Bên cạnh: đối với những người trả lời trong nhận xét - vui lòng sử dụng câu trả lời thay vì nhận xét nếu bạn thực sự trả lời câu hỏi! Nếu chỉ vì bạn nhận được nhiều điểm danh tiếng hơn theo cách đó!]

+0

PS: Nếu bạn đang cố gắng sử dụng lại các phần của bố cục này trong bố cục khác, hãy xem phần tử

7

Hóa ra bạn có thể tạo một ListView trong đó mỗi mục trong listView là Fragment. Bí quyết là gói Fragment trong một FrameLayout.

CẬP NHẬT 9/16/2014

Mặc dù nó là thể để tạo ra một ListView chứa Fragments, nó không giống như đó là một ý tưởng tốt. Điều này dường như chắc chắn là một trường hợp góc trong thế giới Android và có những con rồng. Đối với một đoạn đơn giản giống như một phần trong ví dụ dưới đây, mọi thứ hoạt động rất đẹp, nhưng nếu bạn có một dự án phức tạp với rất nhiều thứ đang diễn ra trong đó thì đây có lẽ không phải là cách để đi. Cách tiếp cận mới của tôi là kéo tất cả mã có liên quan đến GUI vào một mã số View kéo dài FrameLayout và chèn mã đó vào một ListView - điều này hoạt động tốt hơn và phù hợp hơn với cách Android dự kiến ​​sẽ được sử dụng.Nếu bạn cần chức năng của Fragment ở các phần khác của mã, bạn có thể chỉ cần sử dụng View mới ở đó.

Quay lại câu trả lời ban đầu ...

Tôi đã thêm một ManyFragments dụ mới để AnDevCon 14 Fragments example app của tôi nếu bạn muốn thử nó ra. Về cơ bản nó đi xuống các các BaseAdapter, mà trong ví dụ của tôi trông như thế này:

BaseAdapter adapter = new BaseAdapter() { 
     @Override public int getCount() { return 10000; } 
     @Override public Object getItem(int i) { return new Integer(i); } 
     @Override public long getItemId(int i) { return i; } 

     @Override 
     public View getView(int i, View view, ViewGroup viewGroup) { 

      if (view!=null){ 
       ManyListItemFragment fragment = (ManyListItemFragment) view.getTag(); 
       fragment.setCount(i); 
      } else { 
       FrameLayout layout = new FrameLayout(getActivity()); 
       layout.setLayoutParams(frameLayoutParams); 
       int id = generateViewId(); 
       layout.setId(id); 
       ManyListItemFragment fragment = new ManyListItemFragment(); 
       fragment.setCount(i); 
       getChildFragmentManager() 
         .beginTransaction() 
         .replace(id,fragment) 
         .commit(); 
       view = layout; 
       view.setTag(fragment); 
      } 

      return view; 
     } 
    }; 

Trong trường hợp bạn đang tò mò đây là generateViewId():

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) 
public static int generateViewId() { 
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { 
     for (;;) { 
      final int result = sNextGeneratedId.get(); 
      // aapt-generated IDs have the high byte nonzero; clamp to the range under that. 
      int newValue = result + 1; 
      if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0. 
      if (sNextGeneratedId.compareAndSet(result, newValue)) { 
       return result; 
      } 
     } 
    } else { 
     return View.generateViewId(); 
    } 
} 
private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1); 
+0

Bạn có thể hướng dẫn tôi cách tôi giả sử tạo bố cục khác cho từng danh sách mục – Shadow

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