效果
布局
View层
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
[RequireComponent(typeof(CanvasGroup))]
public class ShowInfo : MonoBehaviour {
#region field
public Text m_Size;
public Image m_OffsetImage;
public Text m_Content;
public Text m_AddSize;
public Image m_AddOffsetImage;
public Text m_AddContent;
private Rect m_Offset;
private Vector2 m_AddOffset;
private RectTransform m_SizeTr;
private RectTransform m_AddSizeTr;
#endregion
#region encapsulation
public string Content
{
get
{
return m_Content.text;
}
set
{
m_Size.text = value;
m_Content.text = value;
}
}
public string AddContent
{
get
{
return m_AddContent.text;
}
set
{
m_AddSize.text = value;
m_AddContent.text = value;
}
}
private RectTransform SizeTr
{
get { return m_SizeTr ?? (m_SizeTr = m_Size.rectTransform); }
}
private RectTransform AddSizeTr
{
get { return m_AddSizeTr ?? (m_AddSizeTr = m_AddSize.rectTransform); }
}
#endregion
#region public function
public void Show()
{
m_AddSize.gameObject.SetActive(0 != AddContent.Length);
gameObject.SetActive(true);
}
public void Hide()
{
gameObject.SetActive(false);
SizeTr.offsetMin = new Vector2(Screen.width, 0);
AddSizeTr.offsetMin = new Vector2(Screen.width, 0);
}
/// <summary>
/// 移动
/// </summary>
/// <param name="rect">鼠标悬浮的格子的坐标和大小</param>
public void Move(Rect rect)
{
//ContentSizeFitter 在下一帧才更新布局
//延迟帧更新
StartCoroutine(OnUpdataPosition(rect));
}
#endregion
#region private function
private void Awake()
{
Hide();
SizeTr.pivot = Vector2.up;
AddSizeTr.pivot = Vector2.up;
InspectComponent(m_Size.gameObject);
InspectComponent(m_AddSize.gameObject);
GetComponent<CanvasGroup>().blocksRaycasts = false;
RectTransform tr = m_OffsetImage.rectTransform;
m_Offset = new Rect(Abs(tr.offsetMin.x),
Abs(tr.offsetMax.y),
Abs(tr.offsetMax.x),
Abs(tr.offsetMin.y));
tr = m_AddOffsetImage.rectTransform;
m_AddOffset = new Vector2(Abs(tr.offsetMin.x), Abs(tr.offsetMax.x));
}
private void InspectComponent(GameObject go)
{
ContentSizeFitter com = go.GetComponent<ContentSizeFitter>();
if (com == null)
com = go.AddComponent<ContentSizeFitter>();
com.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
com.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
}
/// <summary>
/// if 最大容纳高度 大于 界面高度
/// y = 鼠标y坐标 - 界面顶部偏移
/// else
/// y = 界面高度
///
/// if 需要对比物品
/// if 界面总宽度 + 附加界面总宽度 小于 屏幕剩余宽度
/// x = 格子右边坐标 + 界面左边偏移
/// addx = 界面右边左边 + 界面总宽度 + 附加界面左边偏移
/// else
/// x = 格子坐标 - 界面宽度
/// addx = 格子坐标 - 界面总宽度 - 附加界面宽度
/// else
/// if 界面总宽度 小于 屏幕剩余宽度
/// x = 格子右边坐标 + 界面左边偏移
/// else
/// x = 格子坐标 - 界面宽度
/// </summary>
private IEnumerator OnUpdataPosition(Rect rect)
{
yield return null;
float x, y, addx = 0;
if (MaxHeight() > PanelHeight())
y = Input.mousePosition.y - m_Offset.y * PanelScale().y;
else
y = PanelHeight();
if (0 != AddContent.Length)
{
if (PanelTotalWidth() + AddPanelTotalWidth() < RemainingWidth(rect))
{
x = LatticeRightPoint(rect) + m_Offset.x * PanelScale().x;
addx = LatticeRightPoint(rect) + PanelTotalWidth() + m_AddOffset.x * AddPanelScanle().x;
}
else
{
x = rect.x - PanelRightWidth();
addx = rect.x - PanelTotalWidth() - AddPanelRightWidth();
}
m_AddSize.transform.position = new Vector3(addx, y, 0);
}
else
{
if (PanelTotalWidth() < RemainingWidth(rect))
x = LatticeRightPoint(rect) + m_Offset.x * PanelScale().x;
else
x = rect.x - PanelRightWidth();
}
m_Size.transform.position = new Vector3(x, y, 0);
}
private float Abs(float value)
{
return Mathf.Abs(value);
}
private Vector2 PanelScale()
{
return SizeTr.localScale;
}
private Vector2 AddPanelScanle()
{
return AddSizeTr.localScale;
}
private float MaxHeight()
{
return Input.mousePosition.y;
}
private float PanelHeight()
{
return (SizeTr.sizeDelta.y + m_Offset.height) * PanelScale().y;
}
private float PanelTotalWidth()
{
return (SizeTr.sizeDelta.x + m_Offset.x + m_Offset.width) * PanelScale().x;
}
private float AddPanelTotalWidth()
{
return (AddSizeTr.sizeDelta.x + m_AddOffset.x + m_Offset.width) * PanelScale().x;
}
private float PanelRightWidth()
{
return (SizeTr.sizeDelta.x + m_Offset.width) * PanelScale().x;
}
private float AddPanelRightWidth()
{
return (AddSizeTr.sizeDelta.x + m_AddOffset.y) * PanelScale().x;
}
private float LatticeRightPoint(Rect rect)
{
return rect.x + rect.width;
}
private float RemainingWidth(Rect rect)
{
return Screen.width - LatticeRightPoint(rect);
}
#endregion
}
Controller层
using UnityEngine;
public class ShowInfoController {
#region field
public ShowInfo m_Info;
#endregion
#region public function
public void Show(Rect rect, string info, string addInfo="")
{
m_Info.Content = info;
m_Info.AddContent = addInfo;
m_Info.Show();
m_Info.Move(rect);
}
public void Hide()
{
m_Info.Hide();
}
#endregion
}