namespace UIWidgets
{
using System;
using EasyLayoutNS;
using UIWidgets.Attributes;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;
///
/// ScrollRectBlock.
///
public abstract class ScrollRectBlock : MonoBehaviourConditional
{
///
/// ScrollRect.
///
[SerializeField]
protected ScrollRect ScrollRect;
///
/// Header.
///
[SerializeField]
[FormerlySerializedAs("Header")]
protected RectTransform Block;
///
/// Is ScrollRect has horizontal direction.
///
[SerializeField]
public bool IsHorizontal = false;
///
/// Display type.
///
[SerializeField]
[FormerlySerializedAs("HeaderType")]
protected ScrollRectHeaderType DisplayType = ScrollRectHeaderType.Reveal;
///
/// Min size of the header.
///
[SerializeField]
[FormerlySerializedAs("HeaderMinSize")]
[EditorConditionEnum("DisplayType", new int[] { (int)ScrollRectHeaderType.Resize })]
public float MinSize = 30f;
///
/// Last position of the ScrollRect.content.
///
[NonSerialized]
protected Vector2 LastPosition;
///
/// Header size.
///
[NonSerialized]
protected Vector2 MaxSize;
///
/// Layout.
///
[NonSerialized]
protected EasyLayout Layout;
///
/// Layout margin delta.
///
[NonSerialized]
protected float MarginDelta;
///
/// ScrollRect transform.
///
[NonSerialized]
protected RectTransform ScrollRectTransform;
[NonSerialized]
bool isInited;
///
/// Start this instance.
///
protected virtual void Start()
{
Init();
}
///
/// Init this instance.
///
public virtual void Init()
{
if (isInited)
{
return;
}
isInited = true;
if ((ScrollRect != null) && (Block != null))
{
ScrollRect.onValueChanged.AddListener(Scroll);
ScrollRectTransform = ScrollRect.transform as RectTransform;
LastPosition = GetPosition();
MaxSize = Block.rect.size;
Layout = ScrollRect.content.GetComponent();
InitReveal();
InitLayout();
Scroll(Vector2.zero);
}
}
///
/// Init for reveal display type.
///
protected abstract void InitReveal();
///
/// Init layout.
///
protected abstract void InitLayout();
///
/// Update layout.
///
/// Size.
protected abstract void UpdateLayout(float size);
///
/// Get position.
///
/// position.
protected virtual Vector2 GetPosition()
{
return ScrollRect.content.anchoredPosition;
}
///
/// Process ScrollRect.onValueChanged event.
///
/// ScrollRect value.
protected void Scroll(Vector2 scrollPosition)
{
var position = GetPosition();
switch (DisplayType)
{
case ScrollRectHeaderType.Resize:
Resize(position);
break;
case ScrollRectHeaderType.Reveal:
Reveal(position);
break;
default:
throw new NotSupportedException(string.Format("Unknown ScrollRectHeaderType: {0}", EnumHelper.ToString(DisplayType)));
}
LastPosition = position;
}
///
/// Get visible rate.
///
/// Scroll position.
/// Visible rate.
protected float VisibleRate(Vector2 scrollPosition)
{
var scroll = IsHorizontal ? -scrollPosition.x : scrollPosition.y;
var size = IsHorizontal ? MaxSize.x : MaxSize.y;
var visible_rate = 1f - Mathf.Clamp01(scroll / size);
return visible_rate;
}
///
/// Get reveal position.
///
/// Visible rate.
/// Position.
protected abstract float RevealPosition(float rate);
///
/// Reveal header.
///
/// Current scroll position.
protected void Reveal(Vector2 scrollPosition)
{
var current_pos = Block.anchoredPosition;
var visible_rate = VisibleRate(scrollPosition);
if (IsHorizontal)
{
current_pos.x = RevealPosition(visible_rate);
}
else
{
current_pos.y = RevealPosition(visible_rate);
}
Block.anchoredPosition = current_pos;
var new_size = (IsHorizontal ? MaxSize.x : MaxSize.y) * visible_rate;
UpdateLayout(new_size);
}
///
/// Resize header.
///
/// Current ScrollRect.content position.
protected void Resize(Vector2 scrollPosition)
{
var visible_rate = VisibleRate(scrollPosition);
var new_size = Mathf.Lerp(MinSize, IsHorizontal ? MaxSize.x : MaxSize.y, visible_rate);
var axis = IsHorizontal ? RectTransform.Axis.Horizontal : RectTransform.Axis.Vertical;
Block.SetSizeWithCurrentAnchors(axis, new_size);
UpdateLayout(new_size);
}
///
/// Destroy this instance.
///
protected virtual void OnDestroy()
{
if (ScrollRect != null)
{
ScrollRect.onValueChanged.RemoveListener(Scroll);
}
}
}
}