Android ListView 每行具有不同的布局
我试图确定拥有一个包含每行不同布局的 ListView 的最佳方法。我知道如何创建自定义行+自定义数组适配器来支持整个列表视图的自定义行,但是如何在ListView中实现许多不同的行样式?
I am trying to determine the best way to have a single ListView that contains different layouts for each row. I know how to create a custom row + custom array adapter to support a custom row for the entire list view, but how can I implement many different row styles in the ListView?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
由于您知道您将拥有多少种布局类型,因此可以使用这些方法。
getViewTypeCount()
- 此方法返回您的列表中有多少类型的行的信息getItemViewType(intposition)
- 返回您应根据位置使用哪种布局类型的信息然后,仅当布局为 null 时才膨胀布局,并使用 getItemViewType 确定类型。
请参阅本教程了解更多信息。
为了实现您在评论中描述的结构的一些优化,我建议:
ViewHolder
的对象中。它会提高速度,因为您不必每次在getView
方法中调用findViewById()
。请参阅 API 演示中的 List14。我希望这会对你有所帮助。如果您可以提供一些 XML 存根,其中包含您的数据结构以及您想要如何将其映射到行中的信息,我将能够为您提供更准确的建议。按像素。
Since you know how many types of layout you would have - it's possible to use those methods.
getViewTypeCount()
- this methods returns information how many types of rows do you have in your listgetItemViewType(int position)
- returns information which layout type you should use based on positionThen you inflate layout only if it's null and determine type using
getItemViewType
.Look at this tutorial for further information.
To achieve some optimizations in structure that you've described in comment I would suggest:
ViewHolder
. It would increase speed because you won't have to callfindViewById()
every time ingetView
method. See List14 in API demos.I hope that will help you. If you could provide some XML stub with your data structure and information how exactly you want to map it into row, I would be able to give you more precise advise. By pixel.
您已经了解了基础知识。您只需要让自定义适配器根据提供的行/光标信息返回不同的布局/视图。
ListView
可以支持多种行样式,因为它派生自 AdapterView :如果您查看 适配器,您将看到使用特定于行的视图的方法:
后两种方法提供位置 因此您可以使用它确定您应该该行使用的视图类型。
当然,您通常不会直接使用 AdapterView 和 Adapter,而是使用或派生它们的子类之一。 Adapter 的子类可能会添加额外的功能来更改如何获取不同行的自定义布局。 由于用于给定行的视图是由适配器驱动的,因此技巧是让适配器返回给定行所需的视图。如何做到这一点有所不同取决于具体的适配器。
例如,使用 ArrayAdapter,
getView()
来膨胀、填充并返回给定位置所需的视图。getView()
方法包括通过convertView
参数重用视图的机会。但要使用 CursorAdapter 的派生类,
newView()
以膨胀、填充并返回当前光标状态(即当前“行”)所需的视图[您还需要重写bindView
以便小部件可以重用视图]但是,要使用SimpleCursorAdapter,
setViewValue()
方法定义一个SimpleCursorAdapter.ViewBinder
来膨胀、填充并返回所需的值给定行(当前游标状态)和数据“列”的视图。该方法可以仅定义“特殊”视图,并遵循 SimpleCursorAdapter 的“正常”绑定的标准行为。查找您最终使用的适配器类型的具体示例/教程。
You already know the basics. You just need to get your custom adapter to return a different layout/view based on the row/cursor information being provided.
A
ListView
can support multiple row styles because it derives from AdapterView:If you look at the Adapter, you'll see methods that account for using row-specific views:
The latter two methods provide the position so you can use that to determine the type of view you should use for that row.
Of course, you generally don't use AdapterView and Adapter directly, but rather use or derive from one of their subclasses. The subclasses of Adapter may add additional functionality that change how to get custom layouts for different rows. Since the view used for a given row is driven by the adapter, the trick is to get the adapter to return the desired view for a given row. How to do this differs depending on the specific adapter.
For example, to use ArrayAdapter,
getView()
to inflate, populate, and return the desired view for the given position. ThegetView()
method includes an opportunity reuse views via theconvertView
parameter.But to use derivatives of CursorAdapter,
newView()
to inflate, populate, and return the desired view for the current cursor state (i.e. the current "row") [you also need to overridebindView
so that widget can reuse views]However, to use SimpleCursorAdapter,
SimpleCursorAdapter.ViewBinder
with asetViewValue()
method to inflate, populate, and return the desired view for a given row (current cursor state) and data "column". The method can define just the "special" views and defer to SimpleCursorAdapter's standard behavior for the "normal" bindings.Look up the specific examples/tutorials for the kind of adapter you end up using.
看看下面的代码。
首先,我们创建自定义布局。在这种情况下,有四种类型。
Even.xml
odd.xmlwhite.xmlblack.xml
然后
,我们创建列表
视图项。在我们的例子中,有一个字符串和一个类型。
之后,我们创建一个视图持有者。强烈建议这样做,因为 Android 操作系统会保留布局引用,以便在项目消失并重新出现在屏幕上时重复使用该项目。如果您不使用这种方法,每次您的项目出现在屏幕上时,Android 操作系统都会创建一个新项目,并导致您的应用程序泄漏内存。
最后,我们创建覆盖 getViewTypeCount() 和 getItemViewType(intposition) 的自定义适配器。
我们的活动是这样的:
现在在 mainactivity.xml 中创建一个列表视图
像这样
Take a look in the code below.
First, we create custom layouts. In this case, four types.
even.xml
odd.xml
white.xml
black.xml
Then, we create the listview item. In our case, with a string and a type.
After that, we create a view holder. It's strongly recommended because Android OS keeps the layout reference to reuse your item when it disappears and appears back on the screen. If you don't use this approach, every single time that your item appears on the screen Android OS will create a new one and causing your app to leak memory.
Finally, we create our custom adapter overriding getViewTypeCount() and getItemViewType(int position).
And our activity is something like this:
now create a listview inside mainactivity.xml
like this
在您的自定义数组适配器中,您可以重写 getView() 方法,正如您可能熟悉的那样。然后您所要做的就是使用 switch 语句或 if 语句根据传递给 getView 方法的位置参数返回某个自定义视图。 Android 很聪明,它只会给你一个适合你的位置/行类型的convertView;您不需要检查它的类型是否正确。您可以通过适当地重写 getItemViewType() 和 getViewTypeCount() 方法来帮助 Android 解决此问题。
In your custom array adapter, you override the getView() method, as you presumably familiar with. Then all you have to do is use a switch statement or an if statement to return a certain custom View depending on the position argument passed to the getView method. Android is clever in that it will only give you a convertView of the appropriate type for your position/row; you do not need to check it is of the correct type. You can help Android with this by overriding the getItemViewType() and getViewTypeCount() methods appropriately.
如果我们需要在列表视图中显示不同类型的视图,那么最好在适配器中使用 getViewTypeCount() 和 getItemViewType() 而不是在 getView() 中切换视图 VIEW.GONE 和 VIEW.VISIBLE 可能是非常昂贵的任务,这将影响列表滚动。
请检查这一点以了解 Adapter 中 getViewTypeCount() 和 getItemViewType() 的使用。
链接:the-use-of-getviewtypecount
If we need to show different type of view in list-view then its good to use getViewTypeCount() and getItemViewType() in adapter instead of toggling a view VIEW.GONE and VIEW.VISIBLE can be very expensive task inside getView() which will affect the list scroll.
Please check this one for use of getViewTypeCount() and getItemViewType() in Adapter.
Link : the-use-of-getviewtypecount
ListView 旨在用于简单的用例,例如所有行项目的相同静态视图。
由于您必须创建 ViewHolder 并充分利用
getItemViewType()
,并动态显示不同的行项目布局 xml,因此您应该尝试使用 RecyclerView,在 Android API 22 中可用。它为多种视图类型提供了更好的支持和结构。查看此教程,了解如何使用 RecyclerView 完成您的任务寻找。
ListView was intended for simple use cases like the same static view for all row items.
Since you have to create ViewHolders and make significant use of
getItemViewType()
, and dynamically show different row item layout xml's, you should try doing that using the RecyclerView, which is available in Android API 22. It offers better support and structure for multiple view types.Check out this tutorial on how to use the RecyclerView to do what you are looking for.