您的位置:首页 > 移动开发 > Unity3D

unity3d中自带的GUI实现下拉列表框

2012-10-09 14:29 543 查看
using UnityEngine;

using System.Collections;

using System.Collections.Generic;

using System.Linq;

using System;

public class ComboBox : MonoBehaviour

{

private Dictionary<object, object> dataSource;

private object currentValue;

private object currentDisplayText;

private int currentIndex;

private GUISkin skin;

private Rect rect;

private Rect relativeRect;

private Rect parentWinRect;

private Rect rectList;

private Rect rectListView;

private Rect rectListViewGroupTop;

private Rect rectListViewGroupBottom;

private bool showList;

private int listItemCount;

private Vector2 scrollPosition;

private Texture2D scrollBarBg;

private Texture2D scrollBarThumb;

private float showListTime;

private int guiDepth;

private bool alreadyInitGuiDepth;

/// <summary>

/// 选择项更改事件参数

/// </summary>

public class SelectItemChangedArgs : EventArgs

{

private object itemValue;

private object itemDisplayText;

public object ItemValue{

get{

return itemValue;

}

}

public object ItemDisplayText{

get{

return itemDisplayText;

}

}

public SelectItemChangedArgs (object iValue, object iDisplayText)

{

itemValue = iValue;

itemDisplayText = iDisplayText;

}

}

/// <summary>

/// 选择项更改事件

/// </summary>

public event EventHandler<SelectItemChangedArgs> OnSelectItemChanged;

public object SelectValue {

get { return currentValue; }

}

public object SelectDisplayText {

get { return currentDisplayText; }

}

public float ShowListTime {

get { return showListTime; }

}

/// <summary>

/// 数据源

/// </summary>

public Dictionary<object, object> DataSource{

set{

dataSource = value;

currentDisplayText = null;

currentValue = null;

}

get{

return dataSource;

}

}

/// <summary>

/// 初始化各项参数,控件应该只调用一次此方法,进行重置数据源直接使用DataSource属性即可

/// </summary>

/// <param name="s">

/// A <see cref="GUISkin"/>

/// </param>

/// <param name="data">

/// A <see cref="Dictionary<System.Object, System.Object>"/>

/// </param>

/// <param name="r">

/// A <see cref="Rect"/>

/// </param>

/// <param name="listCount">

/// A <see cref="System.Int32"/>

/// </param>

/// <param name="barBg">

/// A <see cref="Texture2D"/>

/// </param>

/// <param name="barThumb">

/// A <see cref="Texture2D"/>

/// </param>

/// <param name="depth">

/// A <see cref="System.Int32"/>

/// </param>

public void Init(GUISkin s, Dictionary<object, object> data, Rect r, int listCount, Texture2D barBg, Texture2D barThumb, int depth)

{

skin = s;

dataSource = data;

relativeRect = r;

listItemCount = listCount;

scrollBarBg = barBg;

scrollBarThumb = barThumb;

currentIndex = -1;

//将控件置于当前GUI元素之上,并且只在第一次调用初始化方法设置GUI深度,防止循环中重复调用

if (!alreadyInitGuiDepth){

guiDepth = GUI.depth - 1;

alreadyInitGuiDepth = true;

}

currentDisplayText = null;

currentValue = null;

GUI.skin.verticalScrollbar.normal.background = scrollBarBg;

GUI.skin.verticalScrollbar.margin = new RectOffset (0, 0, 0, 0);

GUI.skin.verticalScrollbarThumb.normal.background = scrollBarThumb;

}

/// <summary>

/// 设置父类容器的坐标范围,计算控件在屏幕上真正的坐标位置

/// </summary>

/// <param name="rectParent">

/// A <see cref="Rect"/>

/// </param>

public void SetParentRect(Rect rectParent)

{

parentWinRect = rectParent;

rect = new Rect(parentWinRect.x + relativeRect.x, parentWinRect.y + relativeRect.y,relativeRect.width,relativeRect.height);

}

/// <summary>

/// 强行设置下拉列表是否是示

/// </summary>

/// <param name="show">

/// A <see cref="System.Boolean"/>

/// </param>

public void SetShowList(bool show)

{

if (showList){

showList = show;

}

}

/// <summary>

/// 绘制下拉列表框

/// </summary>

public void Draw ()

{

if (skin == null || dataSource == null) {

return;

}

if (currentDisplayText == null || currentValue == null) {

if (dataSource.Count > 0) {

currentDisplayText = dataSource.Values.First ();

currentValue = dataSource.Keys.First ();

currentIndex = 0;

}

else{

currentDisplayText = "无";

currentValue = -1;

currentIndex = -1;

}

}

if (GUI.Button (rect, currentDisplayText == null ? "" : currentDisplayText.ToString (), skin.GetStyle ("combobox"))) {

showList = !showList;

if (showList) {

showListTime = Time.time;

} else {

showListTime = 0f;

}

}

this.DrawList();

}

/// <summary>

/// 绘制列表项

/// </summary>

public void DrawList ()

{

if (showList == true) {

this.calculateItemCount();

if (listItemCount < dataSource.Count) {

//为了留出最方下的横线,这里高度减1

rectList = new Rect (rect.x, rect.y + rect.height, rect.width, rect.height * listItemCount - 1);

rectListView = new Rect (rect.x, rect.y + rect.height, rect.width - GUI.skin.verticalScrollbar.fixedWidth, rect.height * dataSource.Count);

rectListViewGroupTop = new Rect (rectList.x, rectList.y, rectList.width, rectList.height + 1 - rect.height);

rectListViewGroupBottom = new Rect (rectList.x, rectList.y + rectListViewGroupTop.height, rectList.width, rect.height);

GUI.Box(rectListViewGroupTop,"", skin.GetStyle ("comboxlist"));

GUI.Box(rectListViewGroupBottom,"", skin.GetStyle ("comboxlistbottom"));

//scrollPosition = GUI.BeginScrollView (rectList, scrollPosition, rectListView, false, true);

scrollPosition = Vector2.Lerp(scrollPosition,GUI.BeginScrollView(rectList, scrollPosition, rectListView, false, true),0.5f);

float top = rectList.y;

for (int i = 0; i < dataSource.Count; i++) {

drawItem(new Rect (rectList.x, top, rect.width, rect.height),i);

top += rect.height;

}

GUI.EndScrollView ();

}

else if (dataSource.Count>0){

rectList = new Rect (rect.x, rect.y + rect.height, rect.width, rect.height * dataSource.Count - 1);

rectListViewGroupTop = new Rect (rectList.x, rectList.y, rectList.width, rectList.height + 1 - rect.height);

rectListViewGroupBottom = new Rect (rectList.x, rectList.y + rectListViewGroupTop.height, rectList.width, rect.height);

GUI.Box(rectListViewGroupTop,"", skin.GetStyle ("comboxlist"));

GUI.Box(rectListViewGroupBottom,"", skin.GetStyle ("comboxlistbottom"));

GUI.BeginGroup(rectList);

float top = 0;

for (int i = 0; i < dataSource.Count; i++) {

drawItem(new Rect (0, top, rect.width, rect.height),i);

top += rect.height;

}

GUI.EndGroup();

}

}

}

/// <summary>

/// 当listItemCount为0时,动态计算可以容纳的数据行数

/// </summary>

private void calculateItemCount()

{

if (listItemCount==0){

int availableAreaHeight = (int)(parentWinRect.height - relativeRect.y - relativeRect.height -1);

listItemCount = availableAreaHeight/(int)relativeRect.height;

}

}

/// <summary>

/// 绘制内容项,并响应事件

/// </summary>

/// <param name="r">

/// A <see cref="Rect"/>

/// </param>

/// <param name="index">

/// A <see cref="System.Int32"/>

/// </param>

private void drawItem (Rect r,int index)

{

if (GUI.Button (r, dataSource.Values.ElementAt(index).ToString (), skin.GetStyle ("comboxitem"))) {

currentDisplayText = dataSource.Values.ElementAt (index);

currentValue = dataSource.Keys.ElementAt (index);

if (currentIndex!=index){

currentIndex = index;

if (OnSelectItemChanged!=null){

OnSelectItemChanged(this,new SelectItemChangedArgs(currentValue,currentDisplayText));

}

}

showList = false;

}

}

void OnGUI()

{

GUI.depth = guiDepth;

this.Draw();

}

/// <summary>

/// 按时间比较各ComboBox控件的顺序,初衷是为了点击新的控件时,其它ComboBox控件下拉列表自动隐藏

/// </summary>

public class ShowListComparer : IComparer<ComboBox>

{

#region IComparer[ComboBox] implementation

int IComparer<ComboBox>.Compare (ComboBox x, ComboBox y)

{

return x.showListTime.CompareTo (y.showListTime) * -1;

}

#endregion

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: