我的notion筆記
邏輯
直接繼承自UIBehaviour
- 提供了RegisterToggle接口,Toggle組在SetToggleGroup中調用,将自身加入m_Toggles
public void RegisterToggle(Toggle toggle)
{
if (!m_Toggles.Contains(toggle))
m_Toggles.Add(toggle);
if (!allowSwitchOff && !AnyTogglesOn())
{
toggle.isOn = true;
NotifyToggleOn(toggle);
}
}
- allowSwitchOff 用于控制再次點選是否關閉。如果是false的話,說明始終有一個是on狀态,在toggle有變化時會進行檢查
- UnregisterToggle接口,RegisterToggle的反向操作,也會有2的檢查
public void UnregisterToggle(Toggle toggle)
{
if (m_Toggles.Contains(toggle))
m_Toggles.Remove(toggle);
if (!allowSwitchOff && !AnyTogglesOn() && m_Toggles.Count != 0)
{
m_Toggles[0].isOn = true;
NotifyToggleOn(m_Toggles[0]);
}
}
- NotifyToggleOn接口,當toggle激活時調用。在toggle的isOn被設定時,會判斷toggle是否有group,調用group的NotifyToggleOn接口。将除了指定的toggle外的toggle關閉。
/// <summary>
/// Notify the group that the given toggle is enabled.
/// </summary>
/// <param name="toggle">The toggle that got triggered on</param>
public void NotifyToggleOn(Toggle toggle, bool sendCallback = true)
{
ValidateToggleIsInGroup(toggle);
// disable all toggles in the group
for (var i = 0; i < m_Toggles.Count; i++)
{
if (m_Toggles[i] == toggle)
continue;
if (sendCallback)
m_Toggles[i].isOn = false;
else
m_Toggles[i].SetIsOnWithoutNotify(false);
}
}
- Toggle的set,設定不一樣的值時觸發,如果有組的話,當設定為true或者組内沒有toggle被激活且必須有一個toggle被激活時觸發,調用組的NotifyToggleOn接口。 如果需要sendCallback時,調用
接口觸發回調。public ToggleEvent onValueChanged = new ToggleEvent();
void Set(bool value, bool sendCallback = true)
{
if (m_IsOn == value)
return;
// if we are in a group and set to true, do group logic
m_IsOn = value;
if (m_Group != null && IsActive())
{
if (m_IsOn || (!m_Group.AnyTogglesOn() && !m_Group.allowSwitchOff))
{
m_IsOn = true;
m_Group.NotifyToggleOn(this, sendCallback);
}
}
// Always send event when toggle is clicked, even if value didn't change
// due to already active toggle in a toggle group being clicked.
// Controls like Dropdown rely on this.
// It's up to the user to ignore a selection being set to the same value it already was, if desired.
PlayEffect(toggleTransition == ToggleTransition.None);
if (sendCallback)
{
UISystemProfilerApi.AddMarker("Toggle.value", this);
onValueChanged.Invoke(m_IsOn);
}
}
優化點
-
申明為List,變長數組(類似C++的vector),而注冊/反注冊接口使用了Contain、Remove,除此之外還有些查找操作,更适合使用map/hashmap/set。List<Toggle> m_Toggles
- AnyTogglesOn會在toggle初始化時和toggle設定值時被頻繁調用,可以将結果緩存起來或在改變時動态記錄,不用每次周遊。
- ActiveToggles 視項目調用頻繁程度,可做2的優化
附錄
C# List 源碼Contains:
// Contains returns true if the specified element is in the List.
// It does a linear, O(n) search. Equality is determined by calling
// item.Equals().
//
public bool Contains(T item) {
if ((Object) item == null) {
for(int i=0; i<_size; i++)
if ((Object) _items[i] == null)
return true;
return false;
}
else {
EqualityComparer<T> c = EqualityComparer<T>.Default;
for(int i=0; i<_size; i++) {
if (c.Equals(_items[i], item)) return true;
}
return false;
}
}
Remove: 這個用在這裡更廢,先周遊找到item對應下标,再從數組中移除(需要将index後的元素複制到前面)
// Removes the element at the given index. The size of the list is
// decreased by one.
//
public bool Remove(T item) {
int index = IndexOf(item);
if (index >= 0) {
RemoveAt(index);
return true;
}
return false;
}