先看几个效果:
在正常状态下是这样的:
1.png鼠标经过是这样的:
2.png选中的时候是这样的:
3.png这里以List为容器实现这样的切换效果(当然也可以使用Tree实现):
项目地址:https://github.com/Washington-DC/Duilib-ListView
1、首先,每个Item有这样的几种布局界面,需要将这几种布局包含在TabLayout中,使用TabLayout进行布局的切换。如图,包含了这三种状态的布局。
2、创建一个List的布局文件,这里我用自定义的ListView标签。
<?xml version="1.0" encoding="UTF-8"?>
<Window size="800,450">
<VerticalLayout bkcolor="FFF3F3F3">
<ListView name="mylist" header="hidden" vscrollbar="true">
</ListView>
</VerticalLayout>
</Window>
3、继承CListContainerElementUI类实现我们自己的ListItem,并重写DoEvent方法。
class CListItemUI:public CListContainerElementUI
{
public:
CListItemUI();
~CListItemUI();
LPCTSTR GetClass() const;
void DoEvent(TEventUI& event);
bool m_bActive;//标识是否被选中
void SetActive(bool bActive = true);//是否选中
//以下为item中的内容,根据自己需要
LPCTSTR m_strItemName;
LPCTSTR m_strItemContent;
LPCTSTR m_strItemInfo;
void SetItemName(LPCTSTR strName);
void SetItemContent(LPCTSTR strContent);
void SetItemInfo(LPCTSTR strInfo);
};
void CListItemUI::DoEvent(TEventUI& event)
{
CTabLayoutUI* pTabUI = static_cast<CTabLayoutUI*>(this->FindSubControl(L"tab"));
if (!m_bActive)
{
if (event.Type == UIEVENT_MOUSEENTER)//enter
{
pTabUI->SelectItem(1);
}
else if (event.Type == UIEVENT_MOUSELEAVE)//leave
{
pTabUI->SelectItem(0);
}
else if (event.Type == UIEVENT_MOUSEHOVER)//hover
{
}
}
CListContainerElementUI::DoEvent(event);
}
4、添加SetActive方法,用于选中处理
void CListItemUI::SetActive(bool bActive /*= true*/)
{
m_bActive = bActive;
CTabLayoutUI* pTabUI = static_cast<CTabLayoutUI*>(this->FindSubControl(L"tab"));
if (m_bActive)
{
this->SetFixedHeight(80);
pTabUI->SelectItem(2);
}
else
{
this->SetFixedHeight(50);
pTabUI->SelectItem(0);
}
}
5、继承CListUI和IDialogBuilderCallback两个类实现ListView,并重写一些方法。
class CListViewUI:public CListUI,public IDialogBuilderCallback
{
public:
CListViewUI();
~CListViewUI();
LPCTSTR GetClass() const;
LPVOID GetInterface(LPCTSTR pstrName);
void DoEvent(TEventUI& event);
int m_nActiveItem;//标识选中的item
bool SetActiveItem(int iIndex,bool bTakeFocus);
CControlUI* CreateControl(LPCTSTR pstrClass);
};
LPVOID CListViewUI::GetInterface(LPCTSTR pstrName)
{
if (_tcscmp(pstrName, _T("ListView")) == 0)
return this;
return CListUI::GetInterface(pstrName);
}
CControlUI* CListViewUI::CreateControl(LPCTSTR pstrClass)
{
if (_tcsicmp(pstrClass, L"ListItem") == 0)
return new CListItemUI();
return NULL;
}
6、用SetActiveItem方法更改选中项item的状态
bool CListViewUI::SetActiveItem(int iIndex, bool bTakeFocus)
{
if (!__super::SelectItem(iIndex,bTakeFocus))
{
return false;
}
//取消原有的选中状态
if (m_nActiveItem != -1)
{
CListItemUI* pItem = static_cast<CListItemUI*>(this->GetItemAt(m_nActiveItem));
pItem->SetActive(false);
}
m_nActiveItem = iIndex;
//将新的item选中状态
if (m_nActiveItem != -1)
{
CListItemUI* pItem = static_cast<CListItemUI*>(this->GetItemAt(m_nActiveItem));
pItem->SetActive(true);
}
return true;
}
7、最后在主对话框中创建ListView,并处理DUI_MSGTYPE_ITEMSELECT消息即可。
CControlUI * CDuiMainWnd::CreateControl(LPCTSTR pstrClass)
{
if (_tcsicmp(pstrClass, L"ListView") == 0)
return new CListViewUI();
if (_tcsicmp(pstrClass, L"ListItem") == 0)
return new CListItemUI();
return NULL;
}
void CDuiMainWnd::Notify(TNotifyUI& msg)
{
CListViewUI* pListView = static_cast<CListViewUI*>(m_PaintManager.FindControl(L"mylist"));
if (msg.sType == DUI_MSGTYPE_ITEMSELECT)
{
int index = pListView->GetCurSel();
pListView->SetActiveItem(index, true);
}
__super::Notify(msg);
}
在初始化窗口时添加一些示例数据,就可以看到效果了。
void CDuiMainWnd::InitWindow()
{
CListViewUI* pListView = static_cast<CListViewUI*>(m_PaintManager.FindControl(L"mylist"));
for (int i = 0; i < 20; i++)
{
CDialogBuilder builder;
CListItemUI* pItem = static_cast<CListItemUI*>(builder.Create(L"ListItemLayout.xml", (UINT)0, this, &m_PaintManager));
CDuiString text;
text.Format(L"test-%02d", i);
pItem->SetItemName(text);
pListView->Add(pItem);
}
}
网友评论