前段时间需要做到识别屏幕滑动的一个简单识别,甚至搜了一些插件,有FingerGesture什么的。这样的组件功能缺失很强大,但是仅为简单的识别就倒入一个大的资源包太不值得。发现简单的包装下UIScrollView组件就可以实现左右上下滑屏,而且也不会有多余的性能开销。
先上效果图,可以识别上下左右的滑动,左上角的按钮为初始组件,右边的log是添加的回调事件。
我用的NGUI版本是3.7.2,NGUI更新的感觉比较快,更新着可能以前的组件字段就失去意义了。在这里我主要用到了UIScrollView的一个字段:mLastPos,其实记录的是滑动是最后滑动到的坐标点,再增加一个变量mStartPos,记录鼠标落下时的坐标,两个坐标就能简单计算出滑动的方向了。
protected Vector3 mLastPos;
protected Vector3 mStartPos; //记录当前点的坐标
public Vector3 MLastPos
{
get
{
return mLastPos;
}
}
public Vector3 MStartPos //刚点击的坐标
{
get
{
return mStartPos;
}
}
其中mStartPos赋值为press事件触发的时候,如图:
好了,定义好UIScrollView必须的变量,可以开始写我们自己的组件了,新建一个文件MyScrollView,预定义移动方向枚举:
public enum MoveDirection
{
toRight= 1,
toLeft = 2,
toDown = 3,
toUp = 4,
none = 5
}
//组件中定义一个回调事件 <span style="line-height: 29.7000007629395px; font-family: 'microsoft yahei'; white-space: pre-wrap;">OnDragFnishDelegate</span>
public class MyScrollView: MonoBehaviour
{
private UIScrollView _scrollView;
public delegate void OnDragFnishDelegate(MoveDirection dirction);
public OnDragFnishDelegate onDragFinishCallback;
private const float MOVE_MIN = 0.01f;
private Vector2 _areaSize;
}
添加一个组件初始化接口,传入的回调事件。其中传入的Vector2参数是后来扩充的用来指定滑动区域尺寸的一个参数。
public void InitComponent( Vector2 areaSize,OnDragFnishDelegate onDragFinishcallback = null)
{
_areaSize = areaSize;
_scrollView = this.GetComponent<UIScrollView>();
_scrollView.onDragFinished = OnDragFnish;
onDragFinishCallback = onDragFinishcallback;
this.GetComponent<UIPanel>().SetRect(0, 0, areaSize.x, areaSize.y);
this.transform.FindChild("grid").GetComponent<UIGrid>().cellWidth = areaSize.x;
this.transform.FindChild("grid").GetComponent<UIGrid>().cellHeight = areaSize.y;
Transform sprTran = this.transform.FindChild("grid/item").transform;
sprTran.GetComponent<BoxCollider>().size = new Vector3(areaSize.x, areaSize.y, 0f);
sprTran.GetComponent<UISprite>().width = (int)areaSize.x;
sprTran.GetComponent<UISprite>().height = (int)areaSize.y;
sprTran.GetComponent<UISprite>().alpha = 0.1f; // *= new Color(1, 1, 1, 0.1f);
}
onDragFinish的实现就用于计算滑动的方向:
//拖拽的回调
private void OnDragFnish()
{
Vector3 moveRelative = _scrollView.MLastPos - _scrollView.MStartPos; //移动的相对坐标
MoveDirection curDir = MoveDirection.none;
//决定识别水平还是垂直的
if(Mathf.Abs(moveRelative.x) > Mathf.Abs(moveRelative.y))
{
if(Mathf.Abs(moveRelative.x) < MOVE_MIN)
{
return ;
}
if(moveRelative.x>= MOVE_MIN)
{
curDir = MoveDirection.toRight;
}
if(moveRelative.x<=-MOVE_MIN)
{
curDir = MoveDirection.toLeft;
}
}
else
{
if(Mathf.Abs(moveRelative.y) < MOVE_MIN)
{
return;
}
if(moveRelative.y>=MOVE_MIN)
{
curDir = MoveDirection.toUp;
}
if(moveRelative.y <= -MOVE_MIN)
{
curDir = MoveDirection.toDown;
}
}
//Log("拖拽完毕=" + moveRelative+",dir="+curDir.ToString());
//拖拽完毕的回调
if (onDragFinishCallback != null)
{
onDragFinishCallback(curDir);
}
}
外部需要引用组件时:先要有个规范的ScrollView滑动节点如场景中:
其中,ScrollArea节点要包含UIpanel、UIScrollView组件,grid节点要包含UIGrid组件,item组件要包含DragScrollView、BoxCollider、UIsprite组件(不放张图不让人滑动,应该被直接过滤掉了。编辑状态下确实很丑,但是我试过,换用一张png透明度调的足够小就可以几乎看不清滑动区域了。)
场景的入口脚本中OnGUI()只需要添加一个简单的组件初始化代码,点击按钮后就调用滑动组件了:
void OnGUI()
{
if (GUILayout.Button("初始化 滑动组件"))
{
GameObject scrollObj = GameObject.Find("uiRoot/ScrollArea") as GameObject;
MyScrollView scrollViewCom = scrollObj.AddMissingComponent<MyScrollView>();
scrollViewCom.InitComponent(new Vector2(500, 500), ScrollFinishCallback);
}
}
最后附上附带下载链接:
http://download.youkuaiyun.com/detail/stephanie_1/8794169
建一个空项目,import这个资源包打开scrollView场景就可以运行看效果了。