目录
一、前言
二、效果
三、代码解析
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窗口中方便地设置左右箭头的引用。这种扩展方法既保留了原有组件的所有功能,又增强了用户体验,是一种推荐的组件扩展方式。