ListView可以包含片段

时间:2012-07-06 13:38:53

标签: android listview android-arrayadapter fragment

如同,ListView的ELEMENTS可以是片段。我知道您可以将TextView XML分配给ListView以改变它的外观,但是您可以将片段添加到ListView中。

例如:我有一个片段。所述片段的XML包含一个ImageView,一些大型TextView和一个小型TextView。 Fragment类代码接收Bundle,然后根据内容相应地填充TextViews和ImageView。 Fragment XML和Fragment代码都可以正常工作 (我可以很好地显示一个单独的片段)。我有一个FragmentActivity,我想在其中显示上面提到的碎片列表。这是我用来尝试填充FragmentActivity视图中的ListView的代码:

    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);

这是我对此的思考方式。我创建了一个Fragments的ArrayList来保存我所有实例化的视图。然后我创建一个Fragment,创建一个Bundle,将数据添加到Bundle(以便Fragment可以正确地将数据封送到它的Views中),将Bundle添加到Fragment,然后最后将Fragment添加到ArrayList。之后,我创建一个ArrayAdapter,添加我想要使用的元素布局,以及我制作的片段列表;然后将ListView设置为从我的适配器读取。

任何运行此代码的人都可能会获得NPE @实例化ArrayAdapter。是什么赋予了?这甚至可能吗?在我继续绞尽脑汁之前,有人可以告诉我,如果我只是在浪费时间吗?有没有更好的办法?我一直在考虑使用ScrollView,但是ListView的大部分功能都需要重新实现,我讨厌 - 讨厌 - 讨厌在不必要的时候重新发明轮子。

感谢所有人的阅读,特别感谢您的决定,如果您决定离开他们。我试图寻找一个既定的答案,但我似乎找到的是关于使用片段的Lis​​tView INSIDE的问题/网页;不使用碎片作为ListView的元素

编辑:我接受了以下建议并开始调查更多内容。从事物出现的方式我应该能够使用一个自定义适配器来膨胀片段,而不是仅仅从XML构建扁平(由于缺乏更好的方式来描述该过程)但是,我当前的实现是在尝试设置时抛出NPE适配器。

这是我的自定义适配器代码(为简洁起见缩短):

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);
}

}

以下是我实施它的方式:

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);

所以这已经过了几天,我很确定这个帖子已被埋葬了。但是,我想我会添加一个最后更新,以防万一有人想尝试这个,谷歌搜索将他们带到这里。所以在我的实现中,当ListView被赋予适配器时,我得到一个NPE。它不需要火箭外科医生弄清楚它肯定是适配器而不是ListView抛出错误。对于我的生活,我无法弄清楚为什么......

无论如何,我想我有一些想法。首先,一个小故事:前一阵子我试图在FragmentDialog中制作FragmentTransactions。每次我试图这样做,我都会得到一份NPE。最后,通过大量研究,我发现原因与片段实例的方式有关。当调用Fragment时,它需要来自它父级的上下文。由于Dialog的父级是启动它的Activity,因此Dialog本身不符合必要的标准。我相信,当尝试将片段添加到ListView时,情况也是如此。由于ListView不符合与片段实例化的协议,因此它会抛出NPE,从而让我停下来并回到惯例。 D @ mn ......我真的希望能够做到这一点。使用片段而不是简单的XML会使组织/搜索列表变得更加容易。哦,好吧......如果有人想知道它就无法做到。

3 个答案:

答案 0 :(得分:8)

我认为这是不可能的,因为在ListView中放置片段意味着片段可以在多个容器中相乘。当您使用FragmentManager创建片段时,它会使用标识符进行标记,从而可以轻松地重新加载和重新排列方向和其他配置更改。它还鼓励跨多个设备配置使用。

片段实际上是活动的子集。你有没有活动作为列表的一部分?绝对不是(应该是答案!)!!!

此外,当它们移入和移出视图(单元格被回收)时,连续地附加()和分离()片段并不是非常有用。这些都是ListView不应该处理的昂贵操作。列表应该快速滚动。

从评论的对话中,我可以看到你希望通过在Activity中很好地分离视图设置代码和适配器来实现漂亮的代码。这样做可以:

  1. 覆盖View课程并在那里进行自定义绘图和设置。
  2. 创建一个新类,在其中提供所需的上下文和数据集,以使您返回列表需要显示的视图 - 这就是我通常所做的。
  3. 有一个Utils课程可以在其他地方制作你的视频(愚蠢)。
  4. 不要在列表中使用碎片。不是他们的目标用例。 HTH。

答案 1 :(得分:7)

事实证明,您可以创建ListView,其中listView中的每个项目都是Fragment。诀窍是将片段包装在FrameLayout

更新2014年9月16日

尽管可能创建包含ListView的{​​{1}},但它看起来并不是一个好主意。这似乎绝对是Android世界的一个极端情况,并且有龙。对于像下面示例中的一个简单片段,一切都运行得很漂亮,但如果你有一个复杂的项目,其中有很多进展,那么这可能不是你要走的路。我的新方法是将所有与GUI相关的代码拉入Fragments扩展View,然后将其插入到FrameLayout中 - 这样做效果更好,更符合Android如何使用。如果您需要在代码的其他部分使用ListView的功能,那么您也可以在其中使用这个新的Fragment

回到原来的答案......

如果你想尝试一下,我已经为我的AnDevCon 14 Fragments example app添加了一个新的View示例。基本上它来自ManyFragments,在我的例子中看起来像这样:

BaseAdapter

如果您对此感兴趣,请生成ViewId():

    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;
        }
    };

答案 2 :(得分:4)

您不需要使用碎片。

编写一个自定义的ViewAdapter,让它膨胀一个更复杂的布局(如果你需要真正想要的话,可能会有几个更复杂的布局),然后根据需要填充布局的字段。

[旁白:对于在评论中回答的人 - 如果你真的在回答这个问题,请使用答案而不是评论!如果只是因为你获得了更多的声望点!]