iOS流式布局的原理和代碼實現

fwcm 9年前發布 | 38K 次閱讀 布局 iOS開發 移動開發

最簡單的流式布局模型, 其實就是: 靠左, 靠右, 或者堆疊. 根據這個簡單的理論, 可以用兩個棧(Stack)數據結構, 一個表示靠左邊的控件列表, 另一個表示靠右邊的控件列表, 即可實現流式布局模型.

用偽代碼表示如下:

// 視圖控件
class View{
    private FlowLayouter layouter;

// 當控件發生 frame 改變后, 調用此方法標記為需要重新布局
void setNeedsLayout(){
    View view = this;
    while(view){
        view.markNeedsLayout();
        // 當控件需要重新布局時, 一般地, 它的父節點也需要重新布局
        view = view.parent;
    }
}

void layout(){
    for(View child in this.children){
        this.layouter.place(child);
    }
}

}

// 流式布局管理器 class FlowLayouter{ private Stack leftViews; private Stack rightViews;

void place(View child){
    Position pos;
    child.layout(); // 子節點先進行布局
    while(!this.spaceFits(child)){
        if(child.floatLeft){
            View view = this.leftViews.pop();
            pos = view.pos;
            // 當被移除的節點比其它節點更高時, 繼續移除
            while(pos.y > this.leftViews.last.y){
                View view = this.leftViews.pop();
                pos = view.pos;
            }
        }
        if(child.floatRight){
            View view = this.rightViews.pop();
            pos = view.pos;
            // 當被移除的節點比其它節點更高時, 繼續移除
            while(pos.y > this.rightViews.last.y){
                View view = this.rightViews.pop();
                pos = view.pos;
            }
        }
    }

    // place child here
    child.pos = pos;

    if(child.floatLeft){
        this.leftViews.push(child.pos);
    }
    if(child.floatRight){
        this.rightViews.push(child.pos);
    }
}

}</pre>

這段代碼最重要的是兩點:

1. 當某個控件發生改變時, 它需要重新布局. 同時, 它的父節點, 以及父節點的父節點, 一直到節點樹的根節點, 都需要重新布局. 當然, 這是性能最差的方案, 優化的思路就是減少需要重新布局的節點的數量, 這需要發動每個人的聰明才智來想.

2. 用兩個 Stack 來分別表示靠左的和靠右節點列表. 如果當前的空白空間不足以放下一個控件, 那么, 嘗試從節點列表中移除一個節點, 這樣, 這個布局區域就空出來了一些空間. 當然, 這個空間應該往下移, 不能和被移除的節點所占據的空間重疊. 因為流式布局的基本原理就是不重疊(除非通過特殊設定, 如負數的偏移量).

有了這個簡單的流式布局模型, 你可以在所有最基本的絕對定位的 GUI 庫上面實現功能強大的流式布局, 例如, iOS 的 UIKit 不支持流式布局, 你可以根據上面的代碼擴展, 給 iOS 界面開發加上流式布局功能.

流式布局其實是非常有趣的一項功能, 它的模型很簡潔, 但功能強大且應用廣泛. GUI 界面的本質是樹, 樹是簡潔而優美的, 而流式布局使用的數據結構是 Stack, 又是一種非常基礎的數據結構.

說句題外話, 我已經實現了 iOS 系統上面的 UI 流式布局 -CocoaUI, 你可以試用下.

Related posts:

  1. JavaScript 類/函數繼承最佳實踐
  2. C# 版的 SimpleXML
  3. 生產者消費者模型中生產者的速度快于消費者時所產生的問題及其解決方法討論
  4. C#封裝log4net
  5. .Net程序中使用log4net記錄日志
  6. </ol> </div>

    原文鏈接: http://www.ideawu.net/blog/archives/868.html


 本文由用戶 fwcm 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!