ListView是否可以包含碎片
在中,ListView的ELEMENTS可以是Fragments。 我知道你可以将一个TextView XML分配给一个ListView来改变它的外观,但是你可以将Fragments添加到一个ListView中。
例如:我有一个片段。 所述片段的XML包含一个ImageView,几个大样式的TextView和一个小型的TextView。 Fragment类代码接收一个Bundle,然后根据内容填充TextViews和ImageView。 片段XML和片段代码工作没有问题(我可以显示一个单独的片段就好了)。 我有一个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);
这是我的思维模式。 我做了一个碎片ArrayList来保存我所有的实例化视图。 然后我创build一个Fragment,创build一个Bundle,向Bundle添加数据(这样Fragment可以正确地将数据封装到Views中),将Bundle添加到Fragment中,最后将这个Fragment添加到ArrayList中。 之后,我制作了一个ArrayAdapter,添加了我想要使用的元素布局以及我制作的碎片列表。 然后设置ListView从我的适配器读取。
任何运行这个代码的人都可能得到NPE @实例化ArrayAdapter。 是什么赋予了? 这甚至有可能吗? 在我不停地喋喋不休之前,有人可以告诉我是不是在浪费我的时间? 有没有更好的办法? 我一直在考虑使用ScrollView,但是ListView的很多function都需要重新实现,而当我不需要的时候,我讨厌 – 讨厌 – 讨厌重新发明轮子。
感谢任何人的阅读,特别是感谢你的想法,如果你决定离开他们。 我试着寻找一个既定的答案,但我似乎find的所有问题/网页有关使用一个片段的ListView INSIDE; 不使用片段作为ListView的元素
编辑:我采取了下面的build议,并开始调查更多。 从事情出现的方式,我应该能够使用自定义适配器,膨胀片段,而不是从XML平面build设(缺乏一个更好的方式来描述过程)。但是,我当前的实现是抛出一个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);
所以已经过了几天了,我很确定这个post已经被埋没了。 不过,我想我会添加一个最新的更新,以防万一有人想尝试这个,谷歌search带来了他们在这里。 所以在我的实现中,当ListView被赋予适配器时,我得到了一个NPE。 这并不需要火箭外科医生弄清楚它确实是适配器,而不是ListView抛出错误。 对于我的生活,我无法弄清楚为什么虽然…
无论如何,我想我有一些想法。 首先是一个小故事:一段时间后,我试图在FragmentDialog中创buildFragmentTransactions。 每当我试图这样做,我会得到一个NPE。 最后,通过大量的研究,我发现原因与碎片被实例化有关。 当一个片段被调用时,它需要来自父项的上下文。 由于对话框的父母是启动它的活动,所以对话框本身不符合必要的标准。 我相信,当试图添加片段到ListView时,情况也是如此。 由于ListView没有通过实例化一个片段达成协议,所以抛出了NPE,从而让我挂了,回到了惯例。 D @ mn …我真的希望我能够做到这一点。 使用Fragments而不是简单的XML将使组织/search整个列表变得容易很多。 噢,好吧,猜猜这是不可能的,以防万一有人在想。
我会说这是不可能的,因为把一个片段放在ListView中意味着片段可以在多个容器中相乘。 当您使用FragmentManager创build一个片段时,它将被标记一个标识符,使得重新加载和重新排列方向和其他configuration更改变得很简单。 它也鼓励在多个设备configuration中使用。
片段实际上是活动的一个子集。 你会有一个活动作为一个列表的一部分? 绝对不是(应该是答案!)!!!
而且,当它们移入和移出视图时(细胞被回收利用)连续()和分离()片段并不是很有用。 这些都是ListView不应该处理的昂贵操作。 列表应该快速滚动。
从评论的谈话中,我可以看到你想要在活动中将视图设置代码和适配器分开,以达到很好的代码。 这样做可以:
- 覆盖
View
类并在那里进行自定义绘图和设置。 - 创build一个新的类,在这个类中提供一个上下文和数据集,让它回到列表需要显示的视图 – 这就是我通常所做的。
- 有一个Utils类来build立你的video在其他地方(愚蠢的)。
只是不要在列表中使用片段。 不是他们所瞄准的用例。 HTH。
事实certificate,你可以创build一个ListView
中的每个项目是一个Fragment
。 诀窍是将片段包装在一个FrameLayout
。
更新9/16/2014
尽pipe可以创build一个包含Fragments
的ListView
,但看起来并不是一个好主意。 这似乎绝对是在Android世界的一个angular落的情况下,有龙。 对于下面例子中的一个简单的片段,一切都很好,但如果你有一个复杂的项目,那么这可能不是一个好的方法。 我的新方法是将所有与GUI相关的代码放入一个扩展了FrameLayout
的View
中,并将其插入到ListView
– 这样做更好,更符合Android的期望。 如果你需要在代码的其他部分使用Fragment
的function,那么你也可以简单地使用这个新的View
。
回到原来的答案…
我已经添加了一个新的ManyFragments
示例到我的AnDevCon 14 Fragments示例应用程序,如果你想尝试一下。 本质上,它来自BaseAdapter
,在我的例子中是这样的:
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; } };
如果你对这里的好奇的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);
你不需要使用片段。
编写一个自定义的ViewAdapter,让它膨胀一个更复杂的布局(或者如果你需要真的看上去更复杂的布局),然后根据需要填充布局的字段。
[除此之外:对于在评论中回答的人 – 如果你真的回答这个问题,请用回答而不是评论! 如果只是因为你获得了更多的声望点!]