using DG.Tweening; using UniRx; using UniRx.Triggers; using UnityEngine; using UnityEngine.UI; public class BtnScrollViewPanel : MonoBehaviour { protected CompositeDisposable disposables = new CompositeDisposable(); public ScrollRect scrollRect; public GameObject bg_mask; public Image img_mask; public Button btn_arrow_top; public Button btn_arrow_bottom; public float height = 164f; public int ShowCount = 7; public int TopPX = 50; public int BottomPX = 50; public float duration = 0.3f; int currentShowCount = 0; private void Start() { scrollRect.onValueChanged.AddListener(OnScrollValueChanged); btn_arrow_top.onClick.AddListener(() => { scrollRect.DOVerticalNormalizedPos(1, duration); }); btn_arrow_bottom.onClick.AddListener(() => { scrollRect.DOVerticalNormalizedPos(0, duration); }); //所有子物体 添加监听 激活状态改变时 检测ScrollRect是否可用 foreach (Transform child in scrollRect.content) { child.OnEnableAsObservable() .Subscribe(_ => CheckScrollRectEnabled()).AddTo(disposables); child.OnDisableAsObservable() .Subscribe(_ => CheckScrollRectEnabled()).AddTo(disposables); } CheckScrollRectEnabled(); ShowCount = Mathf.RoundToInt((scrollRect.viewport.rect.height + 16) / height); } private void OnScrollValueChanged(Vector2 value) { SetBtnArrow(currentShowCount > ShowCount); } async void CheckScrollRectEnabled() { currentShowCount = 0; foreach (Transform child in scrollRect.content) { if (child.gameObject.activeSelf) { currentShowCount++; } } await Awaiters.NextFrame; SetScrollRectEnabled(currentShowCount > ShowCount); } void SetScrollRectEnabled(bool enabled) { if (this == null) { return; } img_mask.enabled = enabled; scrollRect.enabled = enabled; bg_mask.SetActive(enabled); SetBtnArrow(enabled); Vector2 offsetMax = scrollRect.viewport.offsetMax; Vector2 offsetMin = scrollRect.viewport.offsetMin; if (enabled) { offsetMax = new Vector2(offsetMax.x, -TopPX); offsetMin = new Vector2(offsetMin.x, BottomPX); } else { offsetMax = new Vector2(offsetMax.x, 0); offsetMin = new Vector2(offsetMin.x, 0); scrollRect.content.anchoredPosition = Vector2.zero; } if ((int)scrollRect.viewport.offsetMax.y != (int)offsetMax.y) { scrollRect.viewport.offsetMax = offsetMax; } if ((int)scrollRect.viewport.offsetMin.y != (int)offsetMin.y) { scrollRect.viewport.offsetMin = offsetMin; } } void SetBtnArrow(bool enabled) { if (!enabled) { btn_arrow_top.gameObject.SetActive(false); btn_arrow_bottom.gameObject.SetActive(false); return; } if (scrollRect.content.anchoredPosition.y > 10) { btn_arrow_top.gameObject.SetActive(true); } else { btn_arrow_top.gameObject.SetActive(false); } if (scrollRect.content.anchoredPosition.y + scrollRect.viewport.rect.height < scrollRect.content.rect.height - 10) { btn_arrow_bottom.gameObject.SetActive(true); } else { btn_arrow_bottom.gameObject.SetActive(false); } } void OnDisable() { disposables?.Dispose(); disposables = null; } }