屏幕的尺寸总是有限的,当内容已经超出屏幕的范围时,需要特殊的处理方式。EUI 利用滚动条实现此功能。通过拉动滚动条,可以在有限的屏幕中浏览全部内容。在其他引擎中我们可以使用TableView或者ScrollView来实现这些效果,在Egret中怎么使用呢,有两个办法实现。
一、使用滚动控制容器(Scroller)
二、使用滚动控制容器(Scroller) + 列表组合的方式(List)

还对Egret的Scroller不太了解的 点这里
对Egret的List不太了解的 点这里

不过你看完了官网中的示例和介绍,如果想了解更深的话,请继续往下看。

上面的第一种方式,是直接将视图添加到Scroller的ViewPort中,这种方式非常不建议这么做,原因是太浪费性能了,当你的数据量比较大的时候,在微信小程序上面肯定会卡的。(我已经尝试过了,所以我只将第二种做法和其中遇到的问题记录下来,供大家参考交流)

先看一下效果:

这里写图片描述

显示示例中有几个比较重要的部分

一、顶部显示下面cell的分类属性
二、右部滑动条
三、list中cell刷新时数据更新

下面,我们一个一个的解决上面的问题

问题一:
先看我们的布局
这里写图片描述
上面空的部分是做的一个导航器,必须要为空,Scroller大小就是演示图中所有滑动部分,在上面添加一个Group覆盖到Scroller顶部
这里写图片描述
好的,其实你也可以想到这样做,这很简单,关键的是这样做了会引起第二个问题,右部滑动条在顶部的时候会被group遮挡,哈哈,我们直接进入到第二个问题吧。

问题二:
其实要解决问题二很简单的,直接添加一个VScrollerBar组件不就可以了嘛。当然可以这样就可以了,不过这样之后又怎么办呢,Scroller滑动时怎么在滑动条上面表现出来呢。这里写图片描述

将一下代码添加到初始化的地方,新建GameLobbyView.ts

private init() {
    this.game_list_scroller.verticalScrollBar = this.verticalScrollBar;
    this.game_list_scroller.scrollPolicyH = eui.ScrollPolicy.OFF;
    this.game_list_scroller.addEventListener(egret.Event.CHANGE, this.onScrollerChange, this);
}

/**
 * 滚动位置改变的时候
 */
private onScrollerChange() {
    let scrollV = this.game_list_scroller.viewport.scrollV;
    let thumbY = Math.abs(scrollV) / (this.game_list_scroller.viewport.measuredHeight - this.game_list_scroller.height);
    this.verticalScrollBar.thumb.y = thumbY * (this.verticalScrollBar.height - this.verticalScrollBar.thumb.height);
}

在onScrollerChange中监听Scroller的滑动,并自己计算滑动条的位置。

问题三:
数据刷新问题,这才是重点,我们一步一步来吧。

1、新建ts文件对应Scroller中的单个cell视图GameCellView类,并建立对应皮肤GameCellViewSkin.exml,同时新建数据结构GameCellData类,保存cell中需要使用到的数据

class GameCellData {
    ***
}

class GameCellView extends eui.Component implements eui.IItemRenderer {

    // ------------- 接口必须实现数据 ----------------
    private _data: GameCellData;
    public set data(data: GameCellData) {
        this._data = data;
        this.updateView(this._data);
    }
    public get data(): GameCellData {
        return this._data;
    }

    public selected: boolean;
    public itemIndex: number;
    // ------------- 接口必须实现数据 ----------------
}

上面GameCellView必须实现eui.IItemRenderer接口,

    /**
     * 列表类组件的项呈示器接口。
     */
    interface IItemRenderer extends UIComponent {
        /**
         * 要呈示或编辑的数据。
         */
        data: any;
        /**
         * 如果项呈示器可以将其自身显示为已选中,则为 true。
         */
        selected: boolean;
        /**
         * 项呈示器的数据提供程序中的项目索引。
         */
        itemIndex: number;
    }

2、在主类GameLobbyView.ts中初始化list数据

private initList() {
    this.game_list.itemRenderer = GameCellView;
    let listData = new eui.ArrayCollection(this.gameCellDatas);
    this.game_list.dataProvider = listData;
    this.game_list_scroller.viewport = this.game_list;
    // 以上代码在官网中你应该有看见过
    // 重要的下面的代码
    this.game_list.updateRenderer = this.gameCell.bind(this);
}

/**
 * List更新数据是调用
 */
private gameCell(renderer: eui.IItemRenderer, itemIndex: number, data: any) : eui.IItemRenderer{
    renderer.data = data;
    renderer.itemIndex = itemIndex;
    return renderer;
}

先看一下updateRenderer接口说明,所以我们需要实现一个更深数据的接口,上面实现在gameCell中。

        /**
         * 更新项呈示器,以备使用或重用
         */
        updateRenderer(renderer: IItemRenderer, itemIndex: number, data: any): IItemRenderer;

当刷新视图的时候,会回调gameCell函数,我们在gameCell中给视图设置数据。

3、在GameCellView中实现视图刷新数据设置功能

/**
 * 更新视图
 */
private updateView(data: GameCellData) {
    // your code
}

public myOperate() {
    console.log("外界操作视图");
}

这里就是你的代码逻辑了,自己更新视图逻辑。

4、假如我想在GameLobbyView.ts对GameCellView操作怎么办呢。
这里有两个办法,
a、重新刷新list的Data的数据,但是这样相当于重置了数据,不建议使用
b、更改传给list的原数据,并对gameCellView对象操作。

/**
 * 折叠所有同类的游戏
 */
private foldAllGamesByAbilityId(abilityId) {
    let games = gameAbility[abilityId];
    // 更新数据
    for(let gameId of games) {
        let gameData = this.gameInfoDatas[gameId] as GameCellData;
        // gameData更改
    }

    // 更新视图
    for(let i = 0; i < this.game_list.numChildren; i++) {
        let gameCellView = this.game_list.getChildAt(i) as GameCellView;
        gameCellView.myOperate();
    }
}

上面只是想说我们可以拿到List中的视图对象,虽然我们并没有用代码创建视图对象,但是List自动帮我们创建了。

上面只是说了思路,已经很完整了,详细你看完后就知道怎么做了。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐