duilib List控件,横向滚动时列表项不移动或者显示错位的bug的修复
来源:互联网 发布:asp响应式h5网站源码 编辑:程序博客网 时间:2024/05/01 00:27
转载请说明出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/42264673
关于这个bug的修复我之前写过一篇博客,连接为:http://blog.csdn.net/zhuhongshu/article/details/40622705
本以为已经修复好,但是后来有网友私聊我,反映到还存在bug。原本已经解决的bug如下:
1.当List出现滚动条后,拖动滚动条,这时ListContainElementUI控件内部的子控件跟随Header自动调节位置会有差错,明显看到偏移不正确
2.当List出现滚动条后,拖动滚动条到任意位置让ListContainElementUI控件内部的子控件位移,然后最小化窗体再恢复。发现本应该发生偏移的子控件这时却跑到了原位。
新的bug是:当List出现滚动条后,拖动滚动条到任意位置让ListContainElementUI控件内部的子控件位移,然后最大化窗体,就发现列表项的偏移不正确,再次恢复后的列表项位置也有问题。
尝试从ListContainElementUI控件的SetPos函数解决问题,发现总是无法十全十美,没办法既顾及到最小化又顾及最大化,同时还要计算偏移。尝试修复几个小时都不成功。
回头想想,前面的三个问题的根源都在于,List容器先重新计算列表项的位置,再去计算表头的位置。而列表项要根据表头的位置去自适应。之前的做法一直是在列表项调整位置时去尝试计算表头的位置,而这样做的致命缺点就是,当最小化和最大化后表头的位置会有突然的变化而知道计算失误。
换个思路,只要让列表先计算表头的位置,再去计算列表项的位置,自然就没问题了。······,感觉以前的思路好傻。
通过这个思路可以简单有效的修复所有bug,之前的文章的修复过程全部作废,bug的修复过程如下:
修复过程:
一、List控件的SetPos函数源码如下:
void CListUI::SetPos(RECT rc){CVerticalLayoutUI::SetPos(rc); if( m_pHeader == NULL ) return; // Determine general list information and the size of header columns m_ListInfo.nColumns = MIN(m_pHeader->GetCount(), UILIST_MAX_COLUMNS); // The header/columns may or may not be visible at runtime. In either case // we should determine the correct dimensions... if( !m_pHeader->IsVisible() ) { for( int it = 0; it < m_pHeader->GetCount(); it++ ) { static_cast<CControlUI*>(m_pHeader->GetItemAt(it))->SetInternVisible(true); } m_pHeader->SetPos(CDuiRect(rc.left, 0, rc.right, 0)); } int iOffset = m_pList->GetScrollPos().cx; for( int i = 0; i < m_ListInfo.nColumns; i++ ) { CControlUI* pControl = static_cast<CControlUI*>(m_pHeader->GetItemAt(i)); if( !pControl->IsVisible() ) continue; if( pControl->IsFloat() ) continue; RECT rcPos = pControl->GetPos(); if( iOffset > 0 ) { rcPos.left -= iOffset; rcPos.right -= iOffset; pControl->SetPos(rcPos); } m_ListInfo.rcColumn[i] = pControl->GetPos(); } if( !m_pHeader->IsVisible() ) { for( int it = 0; it < m_pHeader->GetCount(); it++ ) { static_cast<CControlUI*>(m_pHeader->GetItemAt(it))->SetInternVisible(false); } }}
代码里首先调用父类的SetPos函数,在父类的SetPos里面会初始化表头和列表项的位置,然后可以看到List的SetPos根据滚动条的位置重新调整了表头的位置。
首先要在函数的最后加入这句代码来重新计算列表项的位置:
m_pList->SetPos(m_pList->GetPos());
二、当横向滚动条控件移动时,会通知父控件已经移动来让父控件做出响应。也就是列表滚动条控件会调用List的SetScrollPos函数,而List控件的SetScrollPos函数会调用CListBodyUI控件的SetScrollPos函数,CListBodyUI控件是所有列表项的容器。在CListBodyUI控件的SetScrollPos函数里,先计算了列表项的位置,后计算表头的位置。所以修改对应代码的位置就可以了,修改后的代码如下:
void CListBodyUI::SetScrollPos(SIZE szPos){ int cx = 0; int cy = 0; if( m_pVerticalScrollBar && m_pVerticalScrollBar->IsVisible() ) { int iLastScrollPos = m_pVerticalScrollBar->GetScrollPos(); m_pVerticalScrollBar->SetScrollPos(szPos.cy); cy = m_pVerticalScrollBar->GetScrollPos() - iLastScrollPos; } if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsVisible() ) { int iLastScrollPos = m_pHorizontalScrollBar->GetScrollPos(); m_pHorizontalScrollBar->SetScrollPos(szPos.cx); cx = m_pHorizontalScrollBar->GetScrollPos() - iLastScrollPos; } if( cx == 0 && cy == 0 ) return;if( cx != 0 && m_pOwner ) {CListHeaderUI* pHeader = m_pOwner->GetHeader();if( pHeader == NULL ) return;TListInfoUI* pInfo = m_pOwner->GetListInfo();pInfo->nColumns = MIN(pHeader->GetCount(), UILIST_MAX_COLUMNS);if( !pHeader->IsVisible() ) {for( int it = 0; it < pHeader->GetCount(); it++ ) {static_cast<CControlUI*>(pHeader->GetItemAt(it))->SetInternVisible(true);}}for( int i = 0; i < pInfo->nColumns; i++ ) {CControlUI* pControl = static_cast<CControlUI*>(pHeader->GetItemAt(i));if( !pControl->IsVisible() ) continue;if( pControl->IsFloat() ) continue;RECT rcPos = pControl->GetPos();rcPos.left -= cx;rcPos.right -= cx;pControl->SetPos(rcPos);pInfo->rcColumn[i] = pControl->GetPos();}if( !pHeader->IsVisible() ) {for( int it = 0; it < pHeader->GetCount(); it++ ) {static_cast<CControlUI*>(pHeader->GetItemAt(it))->SetInternVisible(false);}}} RECT rcPos; for( int it2 = 0; it2 < m_items.GetSize(); it2++ ) { CControlUI* pControl = static_cast<CControlUI*>(m_items[it2]); if( !pControl->IsVisible() ) continue; if( pControl->IsFloat() ) continue; rcPos = pControl->GetPos(); rcPos.left -= cx; rcPos.right -= cx; rcPos.top -= cy; rcPos.bottom -= cy; pControl->SetPos(rcPos); } Invalidate();}
三、当表头的位置计算好后,最后修改ListContainElementUI的SetPos函数去计算他的子控件的位置,代码比以前的版本简单了很多:
void CListContainerElementUI::SetPos(RECT rc){CHorizontalLayoutUI::SetPos(rc);if( m_pOwner == NULL ) return;CListUI* pList = static_cast<CListUI*>(m_pOwner);if (pList == NULL) return;CListHeaderUI *pHeader = pList->GetHeader();if (pHeader == NULL || !pHeader->IsVisible())return;int nCount = m_items.GetSize();for (int i = 0; i < nCount; i++){CControlUI *pListItem = static_cast<CControlUI*>(m_items[i]);CControlUI *pHeaderItem = pHeader->GetItemAt(i);if (pHeaderItem == NULL)return;RECT rcHeaderItem = pHeaderItem->GetPos();if (pListItem != NULL && !(rcHeaderItem.left ==0 && rcHeaderItem.right ==0) ){RECT rt = pListItem->GetPos();rt.left =rcHeaderItem.left;rt.right = rcHeaderItem.right;pListItem->SetPos(rt);}}}
总结:
有这个修复代码后,以前的文章的修复代码就作废了。
如果要修改ListContainElementUI的朋友可以根据我上面给出的代码修改,也可以直接下载我自己的Duilib库。
我的Duilib库代码下载地址:点击打开链接Redrain 2014.12.30
- duilib List控件,横向滚动时列表项不移动或者显示错位的bug的修复
- duilib List控件,横向滚动时列表项不移动或者移动错位的bug的修复
- duilib combo控件,当鼠标滚动时下拉列表自动关闭的bug的修复
- [duilib]修复UIOption同时显示背景图和背景色时,背景图不显示的bug
- duilib 修复CTreeViewUI控件动态添加子控件时,对是否显示判断不足的bug
- duilib的Combo控件滚动条不显示的问题
- duilib中CTextUI控件设置文字时不刷新显示的bug
- duilib中CTextUI控件设置文字时不刷新显示的bug
- duilib 修复 容器控件 rightbordersize和bottombordersize属性显示错误的bug
- 【duilib界面库】duilib界面库(干货) 修复UIScrollBar鼠标移出控件外显示异常的BUG
- duilib 修复CTreeViewUI复选功能判断不准确的bug
- 修复duilib库UISlider控件的4个bug
- duilib relativepos属性导致控件错误的bug修复
- 给你的list控件添加横向的滚动条
- 修复duilib CEditUI控件和CWebBrowserUI控件中按Tab键无法切换焦点的bug
- duilib 修复Text控件无法设置宽度的bug,增加自动加算宽度的属性
- duilib的list控件的键盘上下键激活并获取子项名失败的bug
- 修复miniblink某些网站图片不显示的bug
- 初识敏捷开发原则
- 敏捷开发博客汇总
- linux静态ip设置
- 一个程序员的内心独白
- 缓冲区是什么?
- duilib List控件,横向滚动时列表项不移动或者显示错位的bug的修复
- 摄像头基础知识-配件相关
- NetBSD IPv6环境建立
- Objective-C 通过运行时遍历类所有成员变量
- UIWebview隐藏滚动条______iOSMD5加密NSString/NSData
- BeginPaint和GetDC有什么区别?
- 连续登录判定 判定网络是否可用
- 教你一步步编写新闻客户端二
- 【Tips】27个iOS开发中的小技巧