目录
一、前言
二、效果
三、代码解析
EnhancedScrollRect.cs 解析
Start 方法
HandleArrowVisibility 方法
EnhancedScrollRectEditor.cs 解析
OnEnable 方法
OnInspectorGUI 方法
四、完整代码
EnhancedScrollRect.cs
EnhancedScrollRectEditor.cs
五、总结
Demo链接:
https://download.csdn.net/download/qq_41973169/89428682https://download.csdn.net/download/qq_41973169/89428682
一、前言
Unity版本:2022.3.x
在Unity游戏开发中,ScrollRect是一个常用的UI组件,用于实现可滚动的内容区域。然而,默认的ScrollRect组件并不提供对内容边缘的指示功能,例如在内容可以向左或向右继续滚动时显示箭头。为了解决这个问题,我们扩展了ScrollRect组件,增加了两个箭头指示器(leftArrow和rightArrow),用于提示用户当前内容是否可以继续滚动。这两个脚本分别是EnhancedScrollRect.cs
和EnhancedScrollRectEditor.cs
。
二、效果
三、代码解析
EnhancedScrollRect.cs 解析
Start 方法
在Start
方法中,我们首先调用了基类的Start
方法,然后添加了一个监听器,当ScrollRect的值改变时触发HandleArrowVisibility
方法。接着,我们检查内容是否有ContentSizeFitter
组件,如果有的话,我们强制立即重建布局以确保内容的尺寸正确。最后,我们手动调用一次HandleArrowVisibility
方法,以初始化箭头的可见性。
protected override void Start()
{
base.Start();
onValueChanged.AddListener(HandleArrowVisibility);
var contentSizeFitter = content.GetComponent<ContentSizeFitter>();
if (!contentSizeFitter.IsUnityNull())
{
LayoutRebuilder.ForceRebuildLayoutImmediate(content);
}
HandleArrowVisibility(new Vector2());
}
HandleArrowVisibility 方法
HandleArrowVisibility
方法主要用于根据内容的位置来更新箭头的可见性。首先,我们检查各种关键组件是否为null,如果有任何一个为null,则直接返回。然后,我们计算内容的起始位置和结束位置,并根据这些位置判断是否应该显示左右箭头。
private void HandleArrowVisibility(Vector2 position)
{
if (content.IsUnityNull() || viewport.IsUnityNull() || leftArrow.IsUnityNull() || rightArrow.IsUnityNull())
{
return;
}
var contentStart = content.anchoredPosition.x;
var contentEnd = contentStart + content.rect.width - viewport.rect.width;
leftArrow.gameObject.SetActive(contentStart < -1.0f);
rightArrow.gameObject.SetActive(contentEnd > 1.0f);
}
EnhancedScrollRectEditor.cs 解析
OnEnable 方法
在OnEnable
方法中,我们首先调用基类的OnEnable
方法,然后使用serializedObject.FindProperty
方法查找leftArrow
和rightArrow
属性,并将结果存储在相应的变量中。
protected override void OnEnable()
{
base.OnEnable();
_leftArrow = serializedObject.FindProperty("leftArrow");
_rightArrow = serializedObject.FindProperty("rightArrow");
}
OnInspectorGUI 方法
在OnInspectorGUI
方法中,我们首先调用基类的OnInspectorGUI
方法,然后更新序列化对象的状态。接着,我们使用EditorGUILayout.PropertyField
方法绘制leftArrow
和rightArrow
属性的编辑字段。最后,我们应用修改并在检测到GUI发生变化时,将目标对象标记为脏,以确保更改被保存。
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
EditorGUILayout.PropertyField(_leftArrow);
EditorGUILayout.PropertyField(_rightArrow);
serializedObject.ApplyModifiedProperties();
if (GUI.changed)
{
EditorUtility.SetDirty(target);
}
}
四、完整代码
EnhancedScrollRect.cs
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
public class EnhancedScrollRect : ScrollRect
{
[SerializeField] private RectTransform leftArrow;
[SerializeField] private RectTransform rightArrow;
protected override void Start()
{
base.Start();
onValueChanged.AddListener(HandleArrowVisibility);
var contentSizeFitter = content.GetComponent<ContentSizeFitter>();
if (!contentSizeFitter.IsUnityNull())
{
LayoutRebuilder.ForceRebuildLayoutImmediate(content);
}
HandleArrowVisibility(new Vector2());
}
private void HandleArrowVisibility(Vector2 position)
{
if (content.IsUnityNull() || viewport.IsUnityNull() || leftArrow.IsUnityNull() || rightArrow.IsUnityNull())
{
return;
}
var contentStart = content.anchoredPosition.x;
var contentEnd = contentStart + content.rect.width - viewport.rect.width;
leftArrow.gameObject.SetActive(contentStart < -1.0f);
rightArrow.gameObject.SetActive(contentEnd > 1.0f);
}
}
EnhancedScrollRectEditor.cs
using UnityEditor;
using UnityEditor.UI;
using UnityEngine;
[CustomEditor(typeof(EnhancedScrollRect), true)]
[CanEditMultipleObjects]
public class EnhancedScrollRectEditor : ScrollRectEditor
{
private SerializedProperty _leftArrow;
private SerializedProperty _rightArrow;
protected override void OnEnable()
{
base.OnEnable();
_leftArrow = serializedObject.FindProperty("leftArrow");
_rightArrow = serializedObject.FindProperty("rightArrow");
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
EditorGUILayout.PropertyField(_leftArrow);
EditorGUILayout.PropertyField(_rightArrow);
serializedObject.ApplyModifiedProperties();
if (GUI.changed)
{
EditorUtility.SetDirty(target);
}
}
}
五、总结
通过这两个脚本,我们扩展了Unity的ScrollRect组件,使其能够根据内容的滚动状态显示左右箭头,提示用户内容可以继续滚动。此外,我们还自定义了编辑器,可以在Inspector窗口中方便地设置左右箭头的引用。这种扩展方法既保留了原有组件的所有功能,又增强了用户体验,是一种推荐的组件扩展方式。