Duilib List中Item内容切换效果

先看几个效果:
在正常状态下是这样的:
鼠标经过是这样的:
选中的时候是这样的:

这里以List为容器实现这样的切换效果(当然也可以使用Tree实现):

项目地址:github(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、继承CListUIIDialogBuilderCallback两个类实现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);
	}
}

效果图



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值