XPageView = XClass(XLuaBehaviour, "XPageView") function XPageView:Ctor(rootUi, pageView, innerContainer, pageValue, dir) self.Dir = dir or XScrollConfig.HORIZONTAL self.InnerContainer = innerContainer self.InnerTransform = innerContainer.transform self.InnerGameObject = innerContainer.gameObject self.AniCurve = CS.UnityEngine.AnimationCurve.Linear(0, 0, 1, 1) self.CurPos = CS.UnityEngine.Vector3(0, 0, 0) local pos = self.InnerTransform.anchoredPosition self.OriginPos = CS.UnityEngine.Vector3(pos.x, pos.y, 0) self.LastValue = 0 self:RegisterListener() self:SetPageWidth(pageValue) end function XPageView:SetPageWidth(pageValue) if self.Dir == XScrollConfig.HORIZONTAL then self.SettedPageWidth = pageValue self.SettedPageHeight = nil else self.SettedPageWidth = nil self.SettedPageHeight = pageValue end self:RefreshSizeData() end function XPageView:RefreshSizeData() local rect = self.GameObject:GetComponent("RectTransform").rect self.Width = rect.width self.Height = rect.height self.PageWidth = self.SettedPageWidth or rect.width self.PageHeight = self.SettedPageHeight or rect.height local innerRectTrans = self.InnerGameObject:GetComponent("RectTransform") rect = innerRectTrans.rect self.InnerWidth = rect.width self.InnerHeight = rect.height if self.Dir == XScrollConfig.HORIZONTAL then self.TotalPage = math.ceil((self.InnerWidth - 20) / self.PageWidth) self.InnerWidth = self.TotalPage * self.PageWidth self.Reverse = innerRectTrans.pivot.x == 0 and 1 or -1 self.Offset = innerRectTrans.pivot.x * (self.InnerWidth - self.Width) else self.TotalPage = math.ceil((self.InnerHeight - 20) / self.PageHeight) self.InnerHeight = self.TotalPage * self.PageHeight self.Reverse = innerRectTrans.pivot.y == 0 and 1 or -1 self.Offset = innerRectTrans.pivot.y * (self.InnerHeight - self.Height) end end function XPageView:RefreshView() CS.UnityEngine.Canvas.ForceUpdateCanvases() self:RefreshSizeData() end function XPageView:ScrollToPage(pageNum, time) self.CurAniTime = 0 pageNum = XMath.Clamp(pageNum, 0, self.TotalPage - 1) if self.Dir == XScrollConfig.HORIZONTAL then self.LastValue = self.CurPos.x local targetP = XMath.Clamp( pageNum * self.PageWidth * self.Reverse, - self.Offset, self.InnerWidth - self.Width - self.Offset) self.Offset = targetP - self.CurPos.x else self.LastValue = self.CurPos.y local targetP = XMath.Clamp( pageNum * self.PageHeight * self.Reverse, - self.Offset, self.InnerHeight - self.Height - self.Offset) self.Offset = targetP - self.CurPos.y end self.AniTime = time or 0.2 self.Anim = self.Offset ~= 0 end function XPageView:GetTotalPage() self:RefreshSizeData() return self.TotalPage end function XPageView:GetCurPage() self:RefreshSizeData() local curPage if self.Dir == XScrollConfig.HORIZONTAL then curPage = math.floor(math.abs(self.CurPos.x) / self.PageWidth) else curPage = math.floor(math.abs(self.CurPos.y) / self.PageHeight) end return curPage end function XPageView:NextPage(time) self:ScrollToPage(self:GetCurPage() + 1, time) end function XPageView:PrevPage(time) self:ScrollToPage(self:GetCurPage() - 1, time) end function XPageView:RegisterListener() self.UiWidget = self.GameObject:AddComponent(typeof(CS.XUiWidget)) self.UiWidget:AddBeginDragListener(function(eventData) self:OnBeginDrag(eventData) end) self.UiWidget:AddEndDragListener(function(eventData) self:OnEndDrag(eventData) end) self.UiWidget:AddDragListener(function (eventData) self:OnDrag(eventData) end) end function XPageView:OnBeginDrag(eventData) self:RefreshSizeData() self.StartClickPoint = eventData.position self.StartPos = CS.UnityEngine.Vector3( self.CurPos.x, self.CurPos.y, self.CurPos.z ) self.DeltaPos = CS.UnityEngine.Vector3.zero self.Anim = false self.IsDrag = true end function XPageView:OnDrag(eventData) local curPos = eventData.position self.DeltaPos = self.StartClickPoint - curPos if self.Dir == XScrollConfig.HORIZONTAL then self:OnCalcDrag("x", "InnerWidth", "Width") else self:OnCalcDrag("y", "InnerHeight", "Height") end end function XPageView:OnCalcDrag(axisName, totalWidthName, widthName) local maxPos = self[totalWidthName] - self[widthName] - self.Offset local minPos = - self.Offset local calcPos = self.StartPos[axisName] + self.DeltaPos[axisName] if calcPos < minPos then calcPos = minPos - (minPos - calcPos) / 5 elseif calcPos > maxPos then calcPos = maxPos + (calcPos - maxPos) / 5 end self.CurPos[axisName] = calcPos end function XPageView:OnCalcEnd(axisName, pageWidthName, totalWidthName, widthName) local TargetP local checkDis = self[pageWidthName] / 4 local startLoc = math.floor(self.CurPos[axisName] / self[pageWidthName]) * self[pageWidthName] local offset = self.CurPos[axisName] - startLoc if offset < checkDis then TargetP = XMath.Clamp(startLoc, - self.Offset, self[totalWidthName] - self[widthName] - self.Offset) elseif offset > self[pageWidthName] - checkDis then TargetP = XMath.Clamp(startLoc + self[pageWidthName], - self.Offset, self[totalWidthName] - self[widthName] - self.Offset) else if self.DeltaPos and self.DeltaPos[axisName] > 0 then TargetP = XMath.Clamp(startLoc + self[pageWidthName], - self.Offset, self[totalWidthName] - self[widthName] - self.Offset) else TargetP = XMath.Clamp(startLoc, - self.Offset, self[totalWidthName] - self[widthName]) end end self.Offset = TargetP - self.CurPos[axisName] self.LastValue = self.CurPos[axisName] self.AniTime = XMath.Clamp(math.abs(offset * 2 / self[pageWidthName]), 0, 0.2) end function XPageView:OnEndDrag() if self.Dir == XScrollConfig.HORIZONTAL then self:OnCalcEnd("x", "PageWidth", "InnerWidth", "Width") else self:OnCalcEnd("y", "PageHeight", "InnerHeight", "Height") end self.IsDrag = false self.CurAniTime = 0 self.Anim = self.Offset ~= 0 end function XPageView:Update() if not self.IsDrag and not self.Anim then return end if self.Anim then self.CurAniTime = self.CurAniTime + CS.UnityEngine.Time.deltaTime local value if self.AniTime > 0 then value = self.AniCurve:Evaluate(self.CurAniTime / self.AniTime) else value = self.AniCurve:Evaluate(1) end if self.Dir == XScrollConfig.HORIZONTAL then self.CurPos.x = self.LastValue + self.Offset * value else self.CurPos.y = self.LastValue + self.Offset * value end if self.CurAniTime >= self.AniTime then self.Anim = false end end self.InnerTransform.anchoredPosition = CS.UnityEngine.Vector2(self.OriginPos.x - self.CurPos.x, self.OriginPos.y - self.CurPos.y) end function XPageView:Dispose() local xLuaBehaviour = self.Transform:GetComponent("XLuaBehaviour") if (xLuaBehaviour) then CS.UnityEngine.GameObject.Destroy(xLuaBehaviour) end if (self.UiWidget) then CS.UnityEngine.GameObject.Destroy(self.UiWidget) end end