麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

Duilib中帶有權(quán)重的靈活控件排列實(shí)現(xiàn)(一)

2019-11-10 20:24:37
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
在開發(fā)播放器軟件過(guò)程中,因?yàn)榇翱诘拇笮∈强勺兊模瑸榱俗尶刂茩诓糠值目丶úシ牛弦患乱患粒帜坏龋┻m應(yīng)窗口的尺寸的變化而顯示隱藏,產(chǎn)品經(jīng)理會(huì)定義一系列的規(guī)則,好讓在任何時(shí)候都最核心的功能提供給用戶使用。先列一下產(chǎn)品經(jīng)理給予的需求:兩邊往中間縮,保證左側(cè)LOGO和右側(cè)X最優(yōu)先顯示。頂部隱藏優(yōu)先級(jí):搜索欄,換膚,意見反饋,播放記錄,最小化,最大化底部隱藏優(yōu)先級(jí):全屏,畫質(zhì)增強(qiáng),無(wú)痕,打開文件,播放順序,音量條在處理這個(gè)需求過(guò)程中,前人也嘗試了一些方法,比較通過(guò)全float絕對(duì)布局的方式,自己通過(guò)管理類來(lái)完全訂制。而我個(gè)人還是希望通過(guò)而優(yōu)雅的相對(duì)布局,并利用Container自身的排布算法來(lái)實(shí)現(xiàn)。經(jīng)過(guò)幾天的探索,大致實(shí)現(xiàn)上這種效果,在此分享一下思路與實(shí)現(xiàn)。在分析此需求時(shí),我希望引來(lái)類似于第3維的權(quán)重(weight)概念,即當(dāng)父容器所提供的位置不足于將所有子控件擺放顯示完全時(shí),就按照重要性自低到高依次隱藏,將該控件的顯示騰出來(lái)提供給更為重要的控件來(lái)擺放,簡(jiǎn)單推演一下,應(yīng)該是可行的,按照這樣簡(jiǎn)單的規(guī)則,可以比較輕松地解決這個(gè)需求,并且代碼維護(hù)起來(lái)相對(duì)簡(jiǎn)單。只需要一個(gè)能夠按照子控件的weight值來(lái)排列的父容器,命名為CWeightHorizontalLayoutUI。OK,讓我們來(lái)實(shí)現(xiàn)這個(gè)父容器,首先我介紹一下 CHorizontalLayoutUI::SetPos的方法。其實(shí)就是兩次for循環(huán),前一次來(lái)試算,將沒有設(shè)置寬度的控件記錄下來(lái),將剩余的空間求個(gè)平均數(shù),設(shè)置給自適應(yīng)的控件,而設(shè)置了寬度的控件則按設(shè)置的值排布。
    void CWeightHorizontalLayoutUI::SetPos(RECT rc)    {        CControlUI::SetPos(rc);        rc = m_rcItem;        std::map<CControlUI*, int /*width*/> mapAjust;        // Adjust for inset        rc.left     += m_rcInset.left;        rc.top      += m_rcInset.top;        rc.right    -= m_rcInset.right;        rc.bottom   -= m_rcInset.bottom;        if (m_items.GetSize() == 0) {            PRocessScrollBar(rc, 0, 0);            return;        }        if (!m_bScrollFloat && m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible())             rc.right -= m_pVerticalScrollBar->GetFixedWidth();        if (!m_bScrollFloat && m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible())             rc.bottom -= m_pHorizontalScrollBar->GetFixedHeight();        ResetWeightDisplayControlState(); //  讀取當(dāng)前子控件的權(quán)重        m_mapWeight.clear();        for (int i = 0; i < m_items.GetSize(); i++) {            DuiLib::CControlUI* pControl = static_cast<DuiLib::CControlUI*>(m_items[i]);            if (pControl == nullptr) continue;            CStdString strweight = pControl->GetCustomAttribute(L"weight");            int nweight = _ttoi(strweight.GetData());            m_mapWeight[i] = nweight;        }        m_mapWeightCache = m_mapWeight;        // 查找最小權(quán)重控件          auto HideMinWeigth = [&](int index) -> bool {            CControlUI* pControl = static_cast<CControlUI*>(m_items[index]);            if (pControl && pControl->IsVisible()) {                pControl->SetInternVisible(false);                m_arrWeightHideControl.push_back(pControl);                return true;            }            return false;        };        // Determine the width of elements that are sizeable        SIZE szAvailable = { rc.right - rc.left, rc.bottom - rc.top };        if (m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible())            szAvailable.cx += m_pHorizontalScrollBar->GetScrollRange();        int nAdjustables = 0;        int cxFixed = 0;        int nEstimateNum = 0;        int cxExpand = 0;        std::pair<int, int> min_weight; // first:control index, second:weight        std::map<CControlUI*, int /*width*/> m_mapEstimateWidth;  // 試算時(shí)控件的預(yù)設(shè)寬度        std::map<CControlUI*, int /*width*/> m_mapBookWidth;        do {            // 查找出當(dāng)前權(quán)重值最小,并且顯示著的控件            min_weight = std::make_pair(999, 999);            std::for_each(m_mapWeight.begin(), m_mapWeight.end(), [&](std::pair<int, int> item)-> void {                CControlUI* pControl = static_cast<CControlUI*>(m_items[item.first]);                if (item.second <= min_weight.second && pControl->IsVisible())                    min_weight = item;            });            // 已經(jīng)找到后從map中移除,以避免下次查找的還是這個(gè)控件            auto min_it = std::find_if(m_mapWeight.begin(), m_mapWeight.end(), [min_weight](std::pair<int, int> item)-> bool {                return (item.first == min_weight.first && item.second == item.second);            });            if (min_it != m_mapWeight.end()) m_mapWeight.erase(min_it);            // 試算中            nAdjustables = 0;            cxFixed = 0;            nEstimateNum = 0;            for (int it1 = 0; it1 < m_items.GetSize(); it1++) {                CControlUI* pControl = static_cast<CControlUI*>(m_items[it1]);                if (pControl->IsFloat()) continue;                if (!pControl->IsVisible()) continue;                SIZE sz = pControl->EstimateSize(szAvailable);                if (sz.cx == 0) {                                                         nAdjustables++;                }                else {                    if (sz.cx < pControl->GetMinWidth()) sz.cx = pControl->GetMinWidth();                    if (sz.cx > pControl->GetMaxWidth()) sz.cx = pControl->GetMaxWidth();                }                m_mapEstimateWidth[pControl] = sz.cx;                cxFixed += sz.cx + pControl->GetPadding().left + pControl->GetPadding().right;                nEstimateNum++;            }            cxFixed += (nEstimateNum - 1) * m_iChildPadding;            cxExpand = 0;            if (nAdjustables > 0) cxExpand = max(0, (szAvailable.cx - cxFixed) / nAdjustables);// 此處下節(jié)解釋            // 如果小于空間不夠,先嘗試從低到高縮減帶有adjust屬性的控件            if (szAvailable.cx - cxFixed < 0) {                std::vector<std::pair<CControlUI*, int>> adj_ctrls;                for (int it1 = 0; it1 < m_items.GetSize(); it1++) {                    CControlUI* pControl = static_cast<CControlUI*>(m_items[it1]);                    if (pControl->IsFloat()) continue;                    //if (!pControl->IsVisible()) continue;                    if (pControl->GetCustomAttribute(L"adjustwidth") == NULL ||                        _tcscmp(pControl->GetCustomAttribute(L"adjustwidth"), L"true")) continue;                    adj_ctrls.push_back(std::make_pair(pControl, m_mapWeightCache[it1]));                }                // 自小到大按權(quán)重,先嘗試最小權(quán)重                std::sort(adj_ctrls.begin(), adj_ctrls.end(), [&](std::pair<CControlUI*, int> lhs,                    std::pair<CControlUI*, int> rhs) -> bool {                    return lhs.second < rhs.second;                });                             for (auto it = adj_ctrls.begin(); it != adj_ctrls.end(); it++) {                    auto ctrl = it->first;                    if (m_mapEstimateWidth[ctrl] > ctrl->GetMinWidth()) {                        int sub_width = min(abs(szAvailable.cx - cxFixed), m_mapEstimateWidth[ctrl] - ctrl->GetMinWidth());                        m_mapEstimateWidth[ctrl] = m_mapEstimateWidth[ctrl] - sub_width;    // 新的試算寬度                         m_mapBookWidth[ctrl] = m_mapEstimateWidth[ctrl];                        cxFixed -= sub_width;                        if (szAvailable.cx - cxFixed >= 0) break; // 已經(jīng)滿足排列空間                    }                                    }            }            // 空間不夠,從權(quán)重最小的依次隱藏        } while (szAvailable.cx - cxFixed < 0 && HideMinWeigth(min_weight.first));        // Position the elements        SIZE szRemaining = szAvailable;        int iposX = rc.left;        if (m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible()) {            iPosX -= m_pHorizontalScrollBar->GetScrollPos();        }        int iAdjustable = 0;        int cxFixedRemaining = cxFixed;        for (int it2 = 0; it2 < m_items.GetSize(); it2++) {            CControlUI* pControl = static_cast<CControlUI*>(m_items[it2]);            if (!pControl->IsVisible()) continue;            if (pControl->IsFloat()) {                SetFloatPos(it2);                continue;            }            RECT rcPadding = pControl->GetPadding();            szRemaining.cx -= rcPadding.left;            SIZE sz = pControl->EstimateSize(szRemaining);            if (sz.cx == 0) {                iAdjustable++;                sz.cx = cxExpand;                //最后一個(gè)自適應(yīng)尺寸大小無(wú)需另行計(jì)算                //if( iAdjustable == nAdjustables ) {                //	sz.cx = MAX(0, szRemaining.cx -cxFixedRemaining);                //}                if (sz.cx < pControl->GetMinWidth()) sz.cx = pControl->GetMinWidth();                if (sz.cx > pControl->GetMaxWidth()) sz.cx = pControl->GetMaxWidth();            }            else {                if (sz.cx < pControl->GetMinWidth()) sz.cx = pControl->GetMinWidth();                if (sz.cx > pControl->GetMaxWidth()) sz.cx = pControl->GetMaxWidth();            }            sz.cy = pControl->GetFixedHeight();            if (sz.cy == 0) sz.cy = rc.bottom - rc.top - rcPadding.top - rcPadding.bottom;            if (sz.cy < 0) sz.cy = 0;            if (sz.cy < pControl->GetMinHeight()) sz.cy = pControl->GetMinHeight();            if (sz.cy > pControl->GetMaxHeight()) sz.cy = pControl->GetMaxHeight();            //padding不算控件寬度//2012/09/12            //RECT rcCtrl = { iPosX + rcPadding.left, rc.top + rcPadding.top, iPosX + sz.cx + rcPadding.left + rcPadding.right, rc.top + rcPadding.top + sz.cy};            if (m_mapBookWidth.find(pControl) != m_mapBookWidth.end() &&                m_mapBookWidth[pControl] != sz.cx) {                sz.cx = m_mapBookWidth[pControl];            }            RECT rcCtrl = { iPosX + rcPadding.left, rc.top + rcPadding.top, min(iPosX + sz.cx + rcPadding.left, rc.right) , rc.top + rcPadding.top + sz.cy };            pControl->SetPos(rcCtrl);            iPosX += sz.cx + m_iChildPadding + rcPadding.left + rcPadding.right;            szRemaining.cx -= sz.cx + m_iChildPadding + rcPadding.right;            if (m_bWholeDisplay && rcCtrl.right > rc.left + szAvailable.cx)                m_arrWholeDisplayControl.push_back(pControl);        }        // Process the scrollbar        ProcessScrollBar(rc, 0, 0);    }以上代碼主要是在試算過(guò)程中,在剩余的空間寬度不足時(shí)隱藏一下最小的權(quán)重控件,再次試算一遍需要留心的是當(dāng)Hide時(shí)不能夠直接調(diào)用子控件的SetVisible接口,這樣會(huì)改變控件的基礎(chǔ)狀態(tài),而應(yīng)使用SetInternVisible,并且在再次SetPos時(shí),清除這樣的記錄,并將狀態(tài)重置,這樣,不影響再次的試算過(guò)程。基本以上實(shí)現(xiàn)了控制欄的自定義隱藏順序。而我們只需要在xml文件中配置一下各個(gè)控件的權(quán)重即可。實(shí)現(xiàn)效果:
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 日韩精品久久久久久久九岛 | 国产午夜亚洲精品理论片大丰影院 | 香蕉久久久 | 国产人成精品一区二区三 | 国产精品亚洲激情 | 黄色网络免费看 | 久久欧美亚洲另类专区91大神 | 中文区永久区 | 国产精品久久久久久久午夜片 | av免费在线观看国产 | 久久精品99国产国产精 | 国产乱淫av片免费 | 久久精品黄 | 久久伊人精品视频 | 毛片免费看的 | 202z中文字幕第一页 | 欧美视频在线一区二区三区 | 欧美××××黑人××性爽 | 国产成年人在线观看 | av成人在线电影 | 国产精品久久久久久久av | 日日狠狠久久偷偷四色综合免费 | 国产小视频在线 | 亚洲成人第一区 | 在线成人免费视频 | 亚洲日本韩国精品 | 蜜桃成品人免费视频 | 爱爱视频天天干 | 欧美日韩国产成人在线观看 | 日本在线视频二区 | 久久精品99北条麻妃 | 一级一片免费 | 久久久久久久久久性 | 国产成人在线观看免费 | 欧美wwwwww| 国产成人在线免费视频 | 成人免费在线视频 | 又黄又爽免费无遮挡在线观看 | 91亚洲免费视频 | 91av久久 | 久草在线视频福利 |