美文网首页Litho
Litho学习--列表的实现-2

Litho学习--列表的实现-2

作者: 言者无知_n4c | 来源:发表于2018-05-21 00:23 被阅读67次

    接着上篇 简单的列表-1,这一篇主要讲解如何在列表的顶部添加一个水平滚动的列表,充分利用 Litho 和 Section API 的可组合性。

    简单的列表-1 中 ListSectionSpec 描述了一个包含有 32 个子 SingleComponentSection 的 GroupSection ,每个 SingleComponentSection 负责渲染一个 ListItem Component,每个 Component 的内容只有显示的数字发生了变化。

    这篇中将利用 Litho 中的另外一个核心 Section :DataDiffSection 来渲染列表, 我们把 ListSectionSpec 中的 SingleComponentSection 替换成 DataDiffSection 。

    本篇中的例子把上篇例子中的 ListItemSpec 变成了 ListItem2Spec , ListSectionSpec 变成了 ListSection2Spec, ListSectionSpec 与 ListItemSpec 对应,ListSection2Spec 与 ListItem2Spec 对应。

    1. 重构列表

    首先,把 ListItemSpec 中的三个属性抽取为一个数据模型:

    public class DataModel {
        public String title;
        public String subtitle;
        public int color;
    }
    

    把 ListItemSpec 按照如下修改:

    @LayoutSpec
    public class ListItem2Spec {
    
        @OnCreateLayout
        static Component onCreateLayout(
                ComponentContext c,
                @Prop DataModel dataModel) {
    
            return Column.create(c)
                    .paddingDip(ALL, 16)
                    .backgroundColor(dataModel.color)
                    .child(
                            Text.create(c)
                                    .text(dataModel.title)
                                    .textSizeSp(40))
                    .child(
                            Text.create(c)
                                    .text(dataModel.subtitle)
                                    .textSizeSp(20))
                    .build();
        }
    }
    

    在 ListSection2Spec 中添加生成列表的方法,这里使用静态方法模拟,实际场景应该是拉取数据:

     private static List<DataModel> generateData(int count) {
            final List<DataModel> data = new ArrayList<>(count);
            for (int i = 0; i < count; i++) {
                DataModel model = new DataModel();
                model.color = (i % 2 == 0 ? Color.WHITE : Color.LTGRAY);
                model.title = i + ". Hello, world!";
                model.subtitle = "Litho tutorial";
                data.add(model);
             }
            return data;
        }
    

    再写一个方法,接收 DataModel 参数,创建一个 ListItem2 。

    @OnEvent(RenderEvent.class)
        static RenderInfo onRender(final SectionContext c, @FromEvent DataModel model,@FromEvent int index) {
            return ComponentRenderInfo.create()
                    .component(
                            ListItem2.create(c)
                                    .dataModel(model)
                                    .build())
                    .build();
        }
    

    接下来把两个方法结合在一起,修改 onCreateChildren 方法:

    @OnCreateChildren
        static Children onCreateChildren(final SectionContext c) {
            return Children.create()
                    .child(
                            DataDiffSection.<DataModel>create(c)
                                    .data(generateData(32))
                                    .renderEventHandler(ListSection2.onRender(c)))
                    .build();
        }
    

    那么 @OnEvent 是什么东西?ListSection2.onRender(c) 又是怎么来的?
    下面简单解释一下:

    • 当一个列表条目需要被渲染的时候,DataDiffSection 会产生一个 RenderEvent。
    • 创建 DataDiffSection 的时候,我们传入自定义的 RenderEventHandler ,ListSection2.onRender(c)。
    • 这个自定义的 EventHandler 在接收到 RenderEvent 的时候,会调用在 ListSection2Spec 中定义的 onRender 方法。
    • 所有的 EventHandler 是由 @OnEvent 注解标注的代码生成的。

    运行APP,效果如下:


    简单列表实现-2

    2. 添加水平滚动列表

    还记得我们是如何用RecyclerCollectionComponent来创建列表的么?应为RecyclerCollectionComponent自身也是一个Component,所以我们可以在Section里再创建一个列表,轻松实现嵌套列表。在一个垂直的列表中再嵌套一个垂直的列表是没有意义的,比较常见的是在垂直列表中嵌入一个水平列表。接下来我们就要这么做。

    更新 onCreateChildren()中的代码,在DataDiffSection前面加一个SingleComponentSection:

        @OnCreateChildren
        static Children onCreateChildren(final SectionContext c) {
            return Children.create()
                .child(
                    SingleComponentSection.create(c)
                    .component(
                        RecyclerCollectionComponent.create(c)
                            .disablePTR(true)
                            .recyclerConfiguration(new ListRecyclerConfiguration(LinearLayoutManager.HORIZONTAL, /*reverse layout*/ false, SNAP_TO_CENTER))
                            .section(
                                DataDiffSection.<DataModel>create(c)
                                    .data(generateData(32))
                                    .renderEventHandler(ListSection2.onRender(c))
                            )
                            .canMeasureRecycler(true)
                    )
                    .build()
                )
                .child(
                    DataDiffSection.<DataModel>create(c)
                        .data(generateData(32))
                        .renderEventHandler(ListSection2.onRender(c))
                )
                .build();
        }
    

    这里我们看到 RecyclerCollectionComponent 的几个新 props:

    • recyclerConfiguration 接收一个配置对象用于设置组件的布局以及RecyclerCollectionComponent的对齐方式。
    • canMeasureRecycler对于没有固定高度的水平 RecyclerCollectionComponent 来说须设置成true。RecyclerCollectionComponent会测量第一个孩子的高度并将此高度作为整个水平列表的高度。

    运行APP,应该会看到如下画面:

    简单列表-2-带水平列表

    相关文章

      网友评论

        本文标题:Litho学习--列表的实现-2

        本文链接:https://www.haomeiwen.com/subject/yvdxjftx.html