Laya PageView组件简单实现

问题背景

Laya 1.x中没有PageView组件,就是一次滑动一整页的组件。

解决方法

替代方案是用List组件来实现一个。

方案要点

  1. 在触摸事件中处理翻页
  2. 利用List组件的成员scrollBar得到当前滑动的位置,然后计算出需要自动翻到第几页
  3. 利用List组件tweenTo方法来做翻页动画
  4. 翻页后发送翻页事件

代码

export class PageView extends Laya.List{
    constructor(){
        super();

        this.on(Laya.Event.MOUSE_UP, this, this.onMouseUp);
        this.on(Laya.Event.MOUSE_OUT, this, this.onMouseOut);

        this.renderHandler = Laya.Handler.create(this, this.renderItem);    
        
    }

    destroy(){
        this.off(Laya.Event.MOUSE_UP, this, this.onMouseUp);
        this.off(Laya.Event.MOUSE_OUT, this, this.onMouseOut);
    }

    onMouseUp(event){
        this._updatePage();
    }

    // onMouseMove(event){
    //     console.info("PageView: mouse move => ", event);
    // }

    onMouseOut(event){
        // console.info("PageView: mouse out => ", event);
        this._updatePage();
    }

    private _currentPage:number = 0;
    private _updatePage(){
        // 参考:https://gitee.com/hopher/layaair/blob/master/src/ui/src/laya/ui/List.as
        // this.tweenTo(0);
        // this.onScrollBarChange
        
        // 停止滚动
        this.scrollBar.stopScroll();
        // 滑行到下一页的位置
        // let length:number = this._array.length;
		// let totalPage = Math.ceil(length / (this.repeatX * this.repeatY));
        // let numX:number = this._isVertical ? this.repeatX : this.repeatY;
        // let numY:number = this._isVertical ? this.repeatY : this.repeatX; // 
        // let lineCount:number = Math.ceil(length / numX); // 总的行数
        let total = this._cellOffset > 0 ? this.totalPage + 1 : this.totalPage;

        let pageId = 0;
        if (total > 1) {
            pageId = Math.ceil((this.scrollBar.value - this._cellOffset - this._cellSize/2)/this._cellSize);
        } else {
            // this._scrollBar.setScroll(0, 0, 0);
            // this._scrollBar.target = this._content;
        }

        // console.info("Slider pos => ", this.scrollBar.slider.value);
        // console.info(`Neareast item id: ${pageId}`);
        this.tweenTo(pageId);
        this._currentPage = pageId;
        if(this._onPageChange){
            this._onPageChange(pageId);
        }
    }

    public get pageId(){
        return this._currentPage;
    }

    public set pageId(n:number){
        this._currentPage = n;
        this.tweenTo(n);
    }

    // onScrollBarChange(event){
    //     super.onScrollBarChange(event);
        
    //     console.info("ScrollBar Change => ", this.scrollBar.slider.value);
    // }

    private _onPageChange:(pageId:number)=>void = null;
    public set onPageChangeHandler(handler:(pageId:number)=>void){
        this._onPageChange = handler;
    }
    public get onPageChangeHandler(){
        return this._onPageChange;
    }
}