Unity ScrollView子物体拖拽被拦截、拖拽子物体无法拖拽

Unity UGUI之Scroll View 专栏收录该内容
1 篇文章 0 订阅

参考:
大神的主页:http://dingxiaowei.cn/2017/04/25/
他的github:https://github.com/dingxiaowei/ScrollRect
改进:
https://blog.csdn.net/chenfujun818/article/details/83545853#comments
ScrollRect拖拽事件和子物体的拖拽事件有冲突的解决办法。

工作中遇到ScrollView的拖拽事件和其子物体下的拖拽事件有冲突,拖拽子物体时左右移动,ScrollView也会动,查CSDN遇到的都是ScrollView的子物体点击事件被拦截的情况,不是拖拽事件。好不容易找到一个讲的也不详细,当时着急实现,所以也不知道文章代码里写的其他内容什么意思。
当时想到的就是根据拖拽时手指的移动方向是沿ScrollView滑动方向还是拖拽方向这个思路,但是不太灵敏,直到我搜了GitHub上的大神写的ScrollView效果大全,里面的一种效果就是我要的效果,就是写的有点复杂了,我就拿来改了改,成了下面这简单版。(文章后附大神的github链接):)

一、相关代码和UI效果。
这个结构就是实现拖拽的全部结构。首先是Canvas的相关设置(包括屏幕适配)。
Canvas相关设置
我这里适配的是1334*750的大小,接下来设置Panel。Panel的设置
Panel设置成这个模式,再根据canvas中的设置,就屏幕适配了。
接下来创建一个Scroll View,因为我不需要显示bar,所以只留Viewport,Scrollbar Horizontal和Scrollbar Vertical全部删除。Scroll View身上的Scroll Rect组件中的ContentViewport直接拖拽上去,(默认创建Scroll View时就已经添加,检查一下就好)。Movement Type选择Clamped模式(这个自己到时候看需要什么效果吧)。在这里插入图片描述

接下来就是Content身上添加Content Size Fitter组件,选择Horizontal Fit为Preferred Size,作用就是根据Content的子物体的数量调节Content的宽度。
添加Grid Layout Group,设置如图。在这里插入图片描述
保持Content在屏幕底部就行,接下来在Content下创建子物体,尽量创建多一些。然后写脚本。

上代码,此脚本需要给Content的每个子物体去挂载.

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;
//using DG.Tweening;
using System.Collections.Generic;
using System;

public class ImageDrag : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler//, IDropHandler
{
    /// <summary>
    /// 拖拽的偏移量
    /// </summary>
    private Vector3 _touchOffset; 
    /// <summary>
    /// 场景中的Panel,设置拖拽过程中的父物体
    /// </summary>
    private Transform _panel;      
    /// <summary>
    /// Scroll View上的Scroll Rect组件
    /// </summary>
    private ScrollRect _scrollRect; 
    /// <summary>
    /// 拖拽的是否是子物体
    /// </summary>
    private bool _isDragItem;      

    void Awake()
    {

        Input.multiTouchEnabled = false;    //限制多指拖拽

        _panel = this.transform.root.transform.Find("Panel");

        //注意面板中默认创建的ScrollView中间有空格
        _scrollRect = _panel.transform.Find("ScrollView").GetComponent<ScrollRect>();

        _isDragItem = false;

    }

   
    /// <summary>
    /// 开始拖拽
    /// </summary>
    /// <param name="eventData"></param>

    public void OnBeginDrag(PointerEventData eventData)
    {
       
        Vector2 touchDeltaPosition = Vector2.zero;
#if UNITY_EDITOR
        float delta_x = Input.GetAxis("Mouse X");
        float delta_y = Input.GetAxis("Mouse Y");
        touchDeltaPosition = new Vector2(delta_x, delta_y);

#elif UNITY_ANDROID || UNITY_IPHONE
        touchDeltaPosition = Input.GetTouch(0).deltaPosition;  
#endif
        //通过touchDeltaPosition去判断你的手指(鼠标)的移动方向,是和Scroll View同方向还是拖拽的方向
        if (Mathf.Abs(touchDeltaPosition.x) < Mathf.Abs(touchDeltaPosition.y))
        {
            //在这里区分是拖拽Item还是ScrollRect
            _isDragItem = true;

            this.transform.SetParent(_panel);//设置Item的父物体,为什么要在一开始确定是拖拽Item后就设置父物体??你可以注掉试试

            this.transform.SetAsLastSibling();//设置为同父物体的最从底层,也就是不会被其同级遮挡。

            Vector3 uguiPos = new Vector3();   //定义一个接收返回的ugui坐标
            if (RectTransformUtility.ScreenPointToWorldPointInRectangle(this.gameObject.GetComponent<RectTransform>(),
                 eventData.position, Camera.main, out uguiPos))
            {
                //计算图片中心和鼠标点的差值
                _touchOffset = this.transform.position - uguiPos;
            }
        }
        else
        {
            _isDragItem = false;
            if (_scrollRect != null)
                //调用Scroll的OnBeginDrag方法,有了区分,就不会被item的拖拽事件屏蔽
            _scrollRect.OnBeginDrag(eventData);
        }     
    }

    public void OnDrag(PointerEventData eventData)
    {
            //OnDrag的方法都是在OnBeginDrag中区分的。
        if (_isDragItem)
        {
            Vector3 pos;
            if (RectTransformUtility.ScreenPointToWorldPointInRectangle(this.gameObject.GetComponent<RectTransform>(),
                eventData.position, Camera.main, out pos))
            {
                this.transform.position = pos + _touchOffset;
            }
        }
        else
        {
            if (_scrollRect != null)
                _scrollRect.OnDrag(eventData);
        }
    }

    /// <summary>
    /// 结束拖拽
    /// </summary>
    /// <param name="eventData"></param>
    public void OnEndDrag(PointerEventData eventData)
    {
        if (_isDragItem)
        {
            //处理item拖拽结束的逻辑处理
            Debug.Log("--------拖拽子物体结束-----------");
        }
        else
        {
            //Scroll Rect 拖拽结束
            if (_scrollRect != null)
                _scrollRect.OnEndDrag(eventData);
        }

    }
}

这就是简单的解决Scroll View拖拽子物体有冲突的方法,就是在拖拽冲突的Item脚本上去区分是拖拽的Scroll View还是拖拽Item。
效果图就一张图片,gif图我还没找到合适的软件制作,凑合看吧。在这里插入图片描述
打完收工。

  • 2
    点赞
  • 0
    评论
  • 8
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值