zoukankan      html  css  js  c++  java
  • NGUI 实现广告页的自动、拖动翻页功能

    本篇滑动原理是监听NGUI的UIScrollView的滑动事件onDragStarted、onStoppedMoving、onDragFinished(OnStoppedMoving有几率不触发),UGUI可以用easyTouch等插件监听。

    逻辑也很简单,onDragStarted记录开始滑动的位置,onStoppedMoving计算出本次滑动的距离offset,如果offset大于某个边界值EffortsFlip,进行翻页处理,否则还原当前页。逻辑在onMomentumMove方法。

    这边没有实现动态加载广告页,因为需求是最多5个广告页轮询,需要的可以自行扩展。理论上是可以用3个广告页gameobject实现n个广告页的切换的。

    这边不涉及业务逻辑(广告页可能不只是一张图,显示逻辑可能更复杂),每次分页变化都通过SetIndexPage发送事件ON_DRAG_PAGE_CHANGE通知业务。

    实现的大致效果:实现左右翻页、底部跳转指定页面、滑动翻页。

     先上源码:

    /// <summary>
    /// NGUI拖动翻页
    /// 如果autoSwitch为true,会间隔switchInterval翻一页,翻页方向从第一页到最后一页顺序播放,然后从最后一页到第一页逆序播放
    /// </summary>
    public class UIDragPage : MonoBehaviour
    {
        /// 
        /// 每页宽度
        /// 
        public float pageWidth;
        /// 
        /// 翻页力度,拖动距离大于该值才算翻页
        /// 
        public int EffortsFlip = 50;
        /// 
        /// 总页数
        /// 
        public int pageNums = 0;
    
        /// <summary>
        /// 自动播放切页
        /// </summary>
        public bool autoSwitch = true;
     
        /// 
        /// 当前所在页
        /// 
        public int pageIndex
        {
            get
            {
                return mPageIndex;
            }
            set {
                if(mPageIndex == value) return;
                value = Mathf.Clamp(value, 1, pageNums);
                
                if (isHorizontal)
                {
                    Page((value - mPageIndex) * - pageWidth);
                }
                else
                {
                    Page((value - mPageIndex) * pageWidth);
                }
            }
        }
        /// 
        /// 当前所在页
        /// 
        private int mPageIndex = 1;
        private UIScrollView mScrollView = null;
        private float nowLocation = 0; //拖动开始的坐标,用于计算本次拖动的距离
        private bool isDrag = false;
        private bool isSpringMove = false;
        private SpringPanel mSp = null;
        private bool isHorizontal = true;
        private float lastSwitch = 0;
        private int switchInterval = 4;//自动切换间隔
        private bool isForward = true;//自动翻页方向
        private BoxCollider boxMask;//防止自动更新时和玩家滑动冲突
     
        void Awake() {
            boxMask = gameObject.GetComponent<BoxCollider>();
            if(boxMask == null)
            {
                boxMask = gameObject.AddComponent<BoxCollider>();
            }
            
            mScrollView = gameObject.GetComponent<UIScrollView>();
            if(mScrollView == null)
            {
                mScrollView = gameObject.AddComponent<UIScrollView>();
            }
            mScrollView.onDragStarted = OnDragStarted;
            mScrollView.onStoppedMoving = onStoppedMoving;
            mScrollView.onDragFinished = onStoppedMoving;
            if (mScrollView.movement == UIScrollView.Movement.Horizontal)
            {
                isHorizontal = true;
            }
            else
            {
                isHorizontal = false;
            }
            
            onStoppedMoving();
        }
    
        private void Update() {
            if (!autoSwitch) return;
            if(isDrag || isSpringMove) return;//更新和移动中不更新
    
            if (lastSwitch >= switchInterval) 
            {
                if (isForward) 
                {
                    if (pageIndex == pageNums) {
                        isForward = false;
                        pageIndex = pageNums - 1;
                    } else {
                        pageIndex = pageIndex + 1;
                    }
                } else {
                    if (pageIndex == 1) {
                        isForward = true;
                        pageIndex = 2;
                    } else {
                        pageIndex = pageIndex - 1;
                    }
                }
            }
    
            lastSwitch += Time.deltaTime;
        }
    
        void OnDragStarted()
        {
            isDrag = true;
            SetNowLocation();
        }
        
        void onStoppedMoving() 
        {
            onMomentumMove();
            isDrag = false;
            SetNowLocation();
        }
        
        /// <summary>
        /// 处理移动事件,当拖动距离大于EffortsFlip才算翻页,否则复原位置
        /// </summary>
        void onMomentumMove()
        {
            if (!isDrag) return;
            Vector3 v3 = transform.localPosition;
            float value = 0;
            if (isHorizontal)
            {
                value = nowLocation - v3.x;
                if (Mathf.Abs(value) < EffortsFlip) 
                {
                    Page(0);
                } else {
                    if (value > 0)
                    {
                        if (mPageIndex < pageNums) Page(-pageWidth);
                    }
                    else
                    {
                        if (mPageIndex > 1)  Page(pageWidth);
                    }
                }
            }
            else
            {
                value = nowLocation - v3.y;
                if (Mathf.Abs(value) < EffortsFlip) 
                {
                    Page(0);
                } else {
                    if (value > 0)
                    {
                        if (mPageIndex > 1) Page(-pageWidth);
                    }
                    else
                    {
                        if (mPageIndex < pageNums) Page(pageWidth);
                    }
                }
            }
        }
        
        void Page(float value)
        {
            isSpringMove = true;
            boxMask.enabled = true;
            mSp = GetComponent<SpringPanel>();
            if (mSp == null)mSp = gameObject.AddComponent<SpringPanel>();
            //mSp.enabled = false;
            Vector3 pos = mSp.target;
            pos = isHorizontal ? new Vector3(pos.x + value, pos.y, pos.z) : new Vector3(pos.x, pos.y + value, pos.z);
            if (!SetIndexPage(pos)) return;
            SpringPanel.Begin(gameObject, pos, 8f);
            mSp.onFinished = SpringPanleMoveEnd;
            Debug.Log("page index="+mPageIndex);
        }
        
        bool SetIndexPage(Vector3 v3)
        {
            float value = isHorizontal ? v3.x : v3.y;
            //Debug.Log((pageNums - 1) * pageWidth);
            if(isHorizontal)
            {
                if (value > 0 || value < (pageNums - 1) * -pageWidth) return false;
            }
            else
            {
                if (value < 0 || value > (pageNums - 1) * pageWidth) return false;
            }
            value = Mathf.Abs(value);
            mPageIndex = (int)(value / pageWidth) + 1;
            lastSwitch = 0;
            LuaEventMgr.Instance.CallFunc(LuaEventDefine.ON_DRAG_PAGE_CHANGE, mPageIndex);
            return true;
        }
        
        void SpringPanleMoveEnd()
        {
            isSpringMove = false;
            boxMask.enabled = false;
        }
        
        void SetNowLocation()
        {
            if (isHorizontal)
            {
                nowLocation = gameObject.transform.localPosition.x;
            }
            else
            {
                nowLocation = gameObject.transform.localPosition.y;
            }
        }
        
        #region 公共接口 
        /// 
        /// 上一页
        /// 
        public void PreviousPage()
        {
            if (isHorizontal)
            {
                if (mPageIndex > 1) Page(pageWidth);
            }
            else
            {
                if (mPageIndex < pageNums) Page(pageWidth);
            }
        }
        /// 
        /// 下一页
        /// 
        public void NextPage()
        {
            if (isHorizontal)
            {
                 if (mPageIndex < pageNums) Page(-pageWidth);
            }
            else
            {
                if (mPageIndex > 1) Page(-pageWidth);
            }
        }
        #endregion
        
        // Test
    #if UNITY_EDITOR
        [ContextMenu("上一页")]
        void GoPrevious() {
            PreviousPage();
        }
        
        [ContextMenu("下一页")]
        void GoNext() {
            NextPage();
        }
        
        [ContextMenu("跳转指定页")]
        void GoAssignPage() {
            pageIndex = 4;
        }
    #endif
    }
    

     使用方法就比较糙了,直接获取了广告页的对象进行广告图、点击事件设置。 

    function SpecialSupplyPanel:InitAd()
        self._adsConfig = importTable("activity_ad")
        self._adBtnImg = {}
        local adCount = #self._adsConfig
        self._dragPage.pageNums = adCount--设置分页数量
    
        for i = 1, MaxAdCount do
            local isShow = adCount >= i
            local objBtn = self["BtnAd" .. i].gameObject
            local objImg = self["TexAD" .. i]
    
            objBtn:SetActive(isShow)
            objImg:SetActive(isShow)
    
            if isShow then
                CS.UIEventListener.Get(objBtn).onClick = function ()
                    self:BtnADSwitchClick(i)--设置指定广告页点击事件
                end
    
                self._adBtnImg[i] = objBtn:GetComponent("UISprite")
                self:SetAdBtnImage(i, false)
    
                local texName = self._adsConfig[i].image
                local bgPath = "ShopBanner/" .. texName
    
                ResourcesManager:LoadUITextureAsync(bgPath, function (data)
                    objImg.TexturePath = ""
                    objImg.mainTexture = data --设置广告页贴图
                end)
    
                CS.UIEventListener.Get(objImg.gameObject).onClick = function()
                    self:BtnADClick(i)--设置广告页点击事件
                end
            end
        end
    end
    

      

  • 相关阅读:
    'IDataObject': ambiguous symbol的解决方法
    捕获windows系统的sleep或hibernate状态
    CallingConvention理解
    Exception from HRESULT: 0x8001010D (RPC_E_CANTCALLOUT_ININPUTSYNCCALL))
    .Net Managed C++如何获取当前线程id和当前进程id
    div垂直居中于div中
    父级是relative,子级为absolute的情况下,子级宽度自适应
    background-img高度固定,图片自适应
    如何让两个input紧挨着.
    C# 调用百度短链接api
  • 原文地址:https://www.cnblogs.com/wang-jin-fu/p/13445176.html
Copyright © 2011-2022 走看看