zoukankan      html  css  js  c++  java
  • Laya 实现带有子菜单的List

    Laya 用List实现固定大小的二级菜单

    @ixenos 2020-10-29 11:19:38

    1.继承修改了List

      1     /**
      2      * 改良List
      3      * 改良目标:单列列表,item不规则大小
      4      * 
      5      * @author ixenos 2020-10-27 14:40:00 
      6      * 
      7      */
      8     public class CList extends List
      9     {
     10         /**单元格渲染定位处理器(默认返回参数 _isVertical:Boolean,cell:Box,pos:Number,index:int)*/
     11         public var posHandler:Handler;
     12         /**数据单元位置缓存,设计给单列列表使用,多列列表再斟酌一下*/
     13         private var posCache:Array = [];
     14         
     15         public function CList()
     16         {
     17             super();
     18         }
     19         
     20         /**
     21          * 渲染一个单元格。
     22          * @param cell 需要渲染的单元格对象。
     23          * @param index 单元格索引。
     24          */
     25         override protected function renderItem(cell:*, index:int):void {
     26             if (_array && index >= 0 && index < _array.length) {
     27                 cell.visible = true;
     28                 
     29                 if (cell._$bindData) {
     30                     cell._dataSource = _array[index];
     31                     _bindData(cell, _array[index]);
     32                 } else cell.dataSource = _array[index];
     33                 
     34                 if (!cacheContent) {
     35                     //TODO:
     36                     posCell(cell, index);
     37                 }
     38                 if (hasListener(Event.RENDER)) event(Event.RENDER, [cell, index]);
     39                 if (renderHandler) renderHandler.runWith([cell, index]);
     40             } else {
     41                 cell.visible = false;
     42                 cell.dataSource = null;
     43             }
     44         }
     45 
     46         /**
     47          * @private
     48          * 滚动条的 <code>Event.CHANGE</code> 事件侦听处理函数。
     49          */
     50         override protected function onScrollBarChange(e:Event = null):void {
     51             runCallLater(changeCells);
     52             var scrollValue:Number = _scrollBar.value;
     53             var lineX:int = (_isVertical ? this.repeatX : this.repeatY);
     54             var lineY:int = (_isVertical ? this.repeatY : this.repeatX);
     55             var scrollLine:int = Math.floor(scrollValue / _cellSize);
     56             
     57             //CList: 增加序号精度, 仅限用于单列列表 --ixenos 2020-10-28 09:47:22
     58             if(posCache && posCache.length>0){
     59                 for (var j:int = 0; j < posCache.length; j++) {
     60                     var pos:Number = posCache[j];
     61                     var lastPos:Number = j-1<0?0:posCache[j-1];
     62                     if(scrollValue <= pos){
     63                         var len:Number = pos - lastPos;
     64                         var len1:Number = scrollValue - lastPos;
     65                         if(len1>len*99/100){
     66                             scrollLine = j;
     67                         }else{
     68                             scrollLine = j-1;
     69                         }
     70                         
     71                         break;
     72                     }
     73                 }
     74             }
     75             
     76             if (!cacheContent) {
     77                 var index:int = scrollLine * lineX;
     78                 var num:int = 0;
     79                 
     80                 if (index > _startIndex) {
     81                     num = index - _startIndex;
     82                     var down:Boolean = true;
     83                     var toIndex:int = _startIndex + lineX * (lineY + 1);
     84                     _isMoved = true;
     85                 } else if (index < _startIndex) {
     86                     num = _startIndex - index;
     87                     down = false;
     88                     toIndex = _startIndex - 1;
     89                     _isMoved = true;
     90                 }
     91                 
     92                 for (var i:int = 0; i < num; i++) {
     93                     if (down) {
     94                         var cell:Box = _cells.shift();
     95                         _cells[_cells.length] = cell;
     96                         var cellIndex:int = toIndex + i;
     97                     } else {
     98                         cell = _cells.pop();
     99                         _cells.unshift(cell);
    100                         cellIndex = toIndex - i;
    101                     }
    102                     pos = Math.floor(cellIndex / lineX) * _cellSize;
    103                     _isVertical ? cell.y = pos : cell.x = pos;
    104                     renderItem(cell, cellIndex);
    105                 }
    106                 _startIndex = index;
    107                 changeSelectStatus();
    108             } else {
    109                 num = (lineY + 1);
    110                 if (_createdLine - scrollLine < num) {
    111                     _createItems(_createdLine, lineX, _createdLine + num);
    112                     renderItems(_createdLine * lineX, 0);
    113                     _createdLine += num;
    114                 }
    115             }
    116             
    117             var r:Rectangle = _content.scrollRect;
    118             if (_isVertical) {
    119                 r.y = scrollValue - _offset.y;
    120                 r.x = -_offset.x;
    121             } else {
    122                 r.y = -_offset.y;
    123                 r.x = scrollValue - _offset.x;
    124             }
    125             _content.scrollRect = r;
    126         }
    127         
    128         private function _createItems(startY:int, numX:int, numY:int):void {
    129             var box:Box = _content;
    130             var cell:Box = _getOneCell();
    131             var cellWidth:Number = cell.width + _spaceX;
    132             var cellHeight:Number = cell.height + _spaceY;
    133             
    134             if (cacheContent) {
    135                 var cacheBox:Box = new Box();
    136                 cacheBox.cacheAsBitmap = true;
    137                 cacheBox.pos((_isVertical ? 0 : startY) * cellWidth, (_isVertical ? startY : 0) * cellHeight);
    138                 _content.addChild(cacheBox);
    139                 _content.optimizeScrollRect = true;
    140                 box = cacheBox;
    141             } else {
    142                 var arr:Array = [];
    143                 for (var i:int = _cells.length - 1; i > -1; i--) {
    144                     var item:Box = _cells[i];
    145                     item.removeSelf();
    146                     arr.push(item);
    147                 }
    148                 _cells.length = 0;
    149             }
    150             
    151             for (var k:int = startY; k < numY; k++) {
    152                 for (var l:int = 0; l < numX; l++) {
    153                     if (arr && arr.length) {
    154                         cell = arr.pop();
    155                     } else {
    156                         cell = createItem();
    157                     }
    158                     cell.x = (_isVertical ? l : k) * cellWidth - box.x;
    159                     cell.y = (_isVertical ? k : l) * cellHeight - box.y;
    160                     cell.name = "item" + (k * numX + l);
    161                     box.addChild(cell);
    162                     addCell(cell);
    163                 }
    164             }
    165         }
    166         
    167         private function _getOneCell():Box {
    168             if (_cells.length === 0) {
    169                 var item:Box = createItem();
    170                 _offset.setTo(item.x, item.y);
    171                 if (cacheContent) return item;
    172                 _cells.push(item);
    173             }
    174             return _cells[0];
    175         }
    176         
    177         private function posCell(cell:Box, cellIndex:int):void {
    178             if (!_scrollBar) return;
    179             var lineX:int = (_isVertical ? this.repeatX : this.repeatY);
    180             var lineY:int = (_isVertical ? this.repeatY : this.repeatX);
    181             var pos:Number = Math.floor(cellIndex / lineX) * _cellSize;
    182             _isVertical ? cell.y = pos : cell.x = pos;
    183             
    184             //CList: 新增posHandler --ixenos 2020-10-27 15:00:17
    185             posHandler && posHandler.runWith([_isVertical, cell, pos, cellIndex]);
    186             posCache[cellIndex] = cell.y;
    187         }
    188         
    189         private function _bindData(cell:*, data:Object):void {
    190             var arr:Array = cell._$bindData;
    191             for (var i:int = 0, n:int = arr.length; i < n; i++) {
    192                 var ele:* = arr[i++];
    193                 var prop:String = arr[i++];
    194                 var value:String = arr[i];
    195                 var fun:Function = UIUtils.getBindFun(value);
    196                 ele[prop] = fun.call(this, data);
    197             }
    198         }
    199         
    200         /**
    201          * @private
    202          * 更改单元格的信息。
    203          * @internal 在此销毁、创建单元格,并设置单元格的位置等属性。相当于此列表内容发送改变时调用此函数。
    204          */
    205         override protected function changeCells():void {
    206             _cellChanged = false;
    207             if (_itemRender) {
    208                 //获取滚动条
    209                 scrollBar = getChildByName("scrollBar") as ScrollBar;
    210                 
    211                 //自适应宽高                
    212                 var cell:Box = _getOneCell();
    213                 
    214                 var cellWidth:Number = (cell.width + _spaceX) || 1;
    215                 var cellHeight:Number = (cell.height + _spaceY) || 1;
    216                 if (_width > 0) _repeatX2 = _isVertical ? Math.round(_width / cellWidth) : Math.ceil(_width / cellWidth);
    217                 if (_height > 0) _repeatY2 = _isVertical ? Math.ceil(_height / cellHeight) : Math.round(_height / cellHeight);
    218                 
    219                 var listWidth:Number = _width ? _width : (cellWidth * repeatX - _spaceX);
    220                 var listHeight:Number = _height ? _height : (cellHeight * repeatY - _spaceY);
    221                 _cellSize = _isVertical ? cellHeight : cellWidth;
    222                 _cellOffset = _isVertical ? (cellHeight * Math.max(_repeatY2, _repeatY) - listHeight - _spaceY) : (cellWidth * Math.max(_repeatX2, _repeatX) - listWidth - _spaceX);
    223                 
    224                 if (_isVertical && _scrollBar) _scrollBar.height = listHeight;
    225                 else if (!_isVertical && _scrollBar) _scrollBar.width = listWidth;
    226                 setContentSize(listWidth, listHeight);
    227                 
    228                 //创建新单元格                
    229                 var numX:int = _isVertical ? repeatX : repeatY;
    230                 var numY:int = (_isVertical ? repeatY : repeatX) + (_scrollBar ? 1 : 0);
    231                 _createItems(0, numX, numY);
    232                 _createdLine = numY;
    233                 
    234                 if (_array) {
    235                     array = _array;
    236                     runCallLater(renderItems);
    237                 }
    238             }
    239         }
    240     }

    2.业务伪代码

     1         private function init():void
     2         {
     3             lui.listCate.posHandler = Handler.create(this, listCatePos, null, false);
     4             lui.listCate.repeatY = 4;
     5             lui.listCate.scrollBar.max = getListContentHeight();
     6         }
     7 
     8         private function onToggleCate(index:int):void{
     9             var dat:* = lui.listCate.getItem(index);
    10             dat["open"] = !dat["open"];
    11             lui.listCate.setItem(index, dat);
    12             lui.listCate.refresh();
    13             lui.listCate.scrollBar.max = getListContentHeight();
    14         }
    15         
    16         private function getOpenNumBeforeCurIdx(curIdx:int):int{
    17             var ret:int = 0;
    18             for (var i:int = 0; i < curIdx; i++) {
    19                 var dat:* = lui.listCate.getItem(i);
    20                 if(dat && dat["open"]){
    21                     ret++;
    22                 }
    23             }
    24             return ret;
    25         }
    26         
    27         private function getListContentHeight():Number{
    28             var ret:Number = 130 * lui.listCate.length + lui.listCate.spaceY * (lui.listCate.length - 1) - 440;//TODO 这个值需要参数绑定
    29             for (var i:int = 0; i < lui.listCate.length; i++) {
    30                 var dat:* = lui.listCate.getItem(i);
    31                 ret += dat["open"]?_subH:0;
    32             }
    33             ret -= lui.listCate.spaceY;
    34             return ret;
    35         }
    36         
    37         private function listCatePos(isVertical:Boolean,cell:Box, pos:Number, index:int):Number{
    38             var totalOpenNum:int = getOpenNumBeforeCurIdx(index);
    39             var closeLength:Number = (index - totalOpenNum) * _subH;
    40             pos -= closeLength;
    41             if(isVertical){
    42                 cell.y = pos;
    43             }else{
    44                 cell.x = pos;
    45             }
    46             
    47             return pos;
    48         }
    49         
    50         private function listCateRender(cell:StageSelectItem, index:int):void{
    51             var dat:* = lui.listCate.getItem(index);
    52             var isOpen:Boolean = dat["open"];
    53             var totalOpenNum:int = getOpenNumBeforeCurIdx(index);
    54             cell.updateView(index, isOpen, totalOpenNum);
    55             cell.toggleHandler = Handler.create(this, onToggleCate, [index], false);
    56         }
     
  • 相关阅读:
    使用 IntraWeb (15)
    使用 IntraWeb (10)
    使用 IntraWeb (8)
    Oralce问题之Oracle ORA-28001:某用户密码过期
    Oralce问题之ORA-12560:TNS协议适配器错误
    JS中数组初始化以及赋值
    EasyUI中取的DataGrid中选中行数据
    反编译DLL并修改DLL中的内容
    在SqlServer和Oralce中创建索引
    SQL中左连接on and条件和where条件执行先后顺序
  • 原文地址:https://www.cnblogs.com/ixenos/p/13895816.html
Copyright © 2011-2022 走看看