nim_duilib之virtualListbox用法(22)


概述

  • 本文將介紹virtualListbox的用法。
  • 更多請參考源碼。

一個樣式

樣式丑了點,勿噴。

重寫函數

使用virtualListbox, 需要一個派生類(繼承自基類VirtualListInterface)重寫父類的以下3個函數

class VirtualListInterface
{
public:
	/**
	 * @brief 創建一個子項
	 * @return 返回創建后的子項指針
	 */
	virtual Control* CreateElement() = 0;

	/**
	 * @brief 填充指定子項
	 * @param[in] control 子項控件指針
	 * @param[in] index 索引
	 * @return 返回創建后的子項指針
	 */
	virtual void FillElement(Control *control, int index) = 0;

	/**
	 * @brief 獲取子項總數
	 * @return 返回子項總數
	 */
	virtual int GetElementtCount() = 0;
};

session_list類

  • 自己定義了一個類,並繼承了VirtualListInterface類。
{
public:
	explicit session_list(ui::VirtualListBox* pvlb) :plistbox_(pvlb) {}
	session_list() {}

	// 初始化參數
	int init(ui::VirtualListBox* pvlb);
      .......
}
  • 重寫下面3個函數后,virtualListbox(它的數據代理類型VirtualListInterface類型)會自動調用下面的函數。

CreateElement 函數

  • 如其名,負責創建一個list_item,我們可以定制自己item的樣式, 創建就需要寫在這里。
  • 我的重寫如下:
ui::Control* session_list::CreateElement()
{
	session_list_item* pitem = new(std::nothrow) session_list_item;
	if (NULL == pitem)
		return nullptr;

	std::wstring session_item_xml(L"list_session/sersson_item.xml");
	ui::GlobalManager::FillBoxWithCache(pitem, session_item_xml);

        // 關聯item中的控件
	pitem->init_controls_();

	return pitem;
}

這里創建一個新的item, 其中sersson_item.xml,是item的自定義布局,后面貼其完整源碼

FillElement

它負責填充數據,比如,上面創建了item,item中的顯示內容可以放在這個函數實現。

void session_list::FillElement(ui::Control *control, int index)
{
	if (nullptr == control || NULL == control || 0 > index)
		return;

	session_list_item* pitem = (session_list_item *)(control);
	// 定制顯示數據
	pitem->init_data_();
}

GetElementtCount

告訴當前有多少個item. 比如,100, 2000, 我這里設置的是20.

int session_list::GetElementtCount()
{
	return 20;
}

還需要

上面僅僅是定制了item, 要顯示, 需要下面的函數配合使用才能達到效果

plistbox_->SetDataProvider(this);
plistbox_->SetElementHeight(50);
plistbox_->InitElement(20);
plistbox_->Refresh();

SetDataProvider

需要顯示指定其數據代理的對象。 我這里傳遞的是this, 是因為我自己定義的類是繼承的VirtualListInterface

SetElementHeight

設置子項高度, 示例中,使用DPI,額,我這里就先跳過。我這里設置的是50, 可以參考自己的session_item.xml中定義的height.

下面開始介紹item的個性化

ListContainerElement類

同樣的,需要自己新增一個類 繼承自ListContainerElement。 負責與界面控件的關聯就寫在這個派生類中,函數名可以自定義,下面的兩個函數非父類的函數。

class session_list_item :public ui::ListContainerElement
{
public:
	// 關聯控件
	virtual int init_controls_();

	// 設置初始化數據
	int init_data_();

private:
	// 下面的控件用於與界面的控件綁定
	
	// 頭像
	ui::Label*	label_protrait_ = nullptr;
	// 姓名
	ui::Label*	label_name_ = nullptr;
	// 最新消息
	ui::RichEdit*	rich_edit_last_msg_ = nullptr;
	// 最新消息時間
	ui::Label*	label_last_msg_time_ = nullptr;
	// 是否靜音
	ui::Label*	label_is_muted_ = nullptr;
};

init_controls_

我把初始化控件放在了這個函數中,當創建了item,再調用該函數完成控件綁定

int session_list_item::init_controls_()
{
	auto find_sub_ctrl = [&](const std::wstring name, ui::Label* pdst)
	{
		ui::Control* ptmp = FindSubControl(name);
		if (ptmp)
			label_protrait_ = dynamic_cast<ui::Label*>(ptmp);
	};

	// 1.關聯其他label控件
	find_sub_ctrl(L"label_portrait", label_protrait_);
	find_sub_ctrl(L"label_name", label_name_);
	find_sub_ctrl(L"label_last_msg_time", label_last_msg_time_);
	find_sub_ctrl(L"label_is_muted", label_is_muted_);

	// 2.關聯上一條消息控件
	ui::Control* ptmp = FindSubControl(L"rich_edit_last_msg");
	if (ptmp)
		rich_edit_last_msg_ = dynamic_cast<ui::RichEdit*>(ptmp);

	return 0;
}

init_data_

item顯示的內容的填充,可以放到這個函數中,FillElement函數中可以調用該函數完成數據綁定。

int session_list_item::init_data_()
{

	//if (rich_edit_last_msg_)
	//	rich_edit_last_msg_->SetText(L"33");

	auto set_text = [&](ui::Label*label, std::wstring str)
	{
		if (label)
			label->SetText(str);
	};

	static int index = 0;
	std::wstring str = fmt::format(L"{}", ++index);
	set_text(label_protrait_, str);
	//set_text(label_name_, L"22");
	//set_text(label_last_msg_time_, L"33");
	//set_text(label_is_muted_, L"44");

	return 0;
}

session_item.xml

  • 單獨維護item的樣式,很方便。 上面例子中的item樣式定義如下
  • 整體采用水平布局。
  • xml源碼內容
<?xml version="1.0" encoding="UTF-8"?>
<Window>
    <ListContainerElement class="listitem" normalcolor="bk_wnd_lightcolor" height="60" margin="0,3,0,3">
      <!--整體水平布局-->
      <HBox width="stretch" height="stretch">
        <!--頭像-->
        <Label  name="label_portrait" text="頭像" width="50" height="50" bkcolor="green" />

        <!--中間顯示部分:姓名和上一條消息-->
        <VBox width="stretch" height="stretch" bkcolor="red">
          <!--姓名-->
          <Label text="王老板" name="label_name" width="stretch"/>

          <Control />
          <!--上一條消息-->
          <RichEdit text="這個月加班XXXXXXXXX" name="rich_edit_last_msg" multiline="false" vscrollbar="false" autovscroll="autovscroll" readonly="true" />
        </VBox>
        
        <!--右側顯示的事件和是否顯示提醒圖標-->
        <VBox width="50" height="stretch" bkcolor="bk_listitem_selected" >
          <!--上一條消息時間-->
          <Label name="label_last_msg_time" text="08:08" />

          <Control />
          <!--是否顯示消息提醒圖標-->
          <Label name="label_is_muted" text="靜音" />
        </VBox>
      
      </HBox>
      <!--整體水平布局-->
    </ListContainerElement>
</Window>

virtualListbox的xml

其定義不在上面的sesson_item.xml,如下,

  <Box name="box_list_box" width="stretch" height="stretch">
        <VirtualListBox class="list" name="virtual_list_box" vscrollunit="1" bkcolor="green" margin="10,0,0,0" vscrollbar="true" />
  </Box>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM