效果
点击视野范围边缘的tab按钮时触发一段滑动,将被点击的按钮移动至视野中心,如果tab按钮长度不够则滑动到最大值
1.补帧动画
用DoTween插件做的滑动补帧动画,用Unity的协程也可以。
public class UIScrollRect : ScrollRect {
public bool IsPlaying => _isPlaying;
private bool _isPlaying;
/// <summary>
/// 进度补帧动画
/// </summary>
/// <param name="targetNormalizedPosition">滚动进度</param>
/// <param name="duration">动画持续时间</param>
/// <returns></returns>
public Tween DoNormalizedPosition(Vector2 targetNormalizedPosition, float duration) {
_isPlaying = true;
return DOTween.To(
() => normalizedPosition,
(x) => normalizedPosition = x,
targetNormalizedPosition,
duration
).OnComplete(
() => { _isPlaying = false; });
}
}
2.滑动补充组件
点击第index个tab按钮时调用CheckFixScroll方法即可。
--------------------------------------------------------------
-- @file SupplementarySlidingComponent.lua
-- @brief 补充滑动组件
--
-- @author Shadowrabbit, yingtu0401@gmail.com
--
-- @Modified 2020/10/10 11:05
-- @Copyright Copyright (c) 2020, Shadowrabbit
--============================================================
local assert = assert
local Mathf = Mathf
local Vector2 = Vector2
local Logger = class.get("Logger") --- @type Logger
--- @class SupplementarySlidingComponent : Component
local SupplementarySlidingComponent = assert(self)
--- @brief 构造函数
--- @protected
function SupplementarySlidingComponent:Initialize()
self.exportedMethods = {
"CheckFixScroll"
}
end
--- @brief 析构函数
--- @protected
function SupplementarySlidingComponent:Finalize()
self.exportedMethods = nil
end
--- @brief 补充滑动检测
--- @public
--- @param index number 被点击tab的索引from1
--- @param compSr vFrame.UI.UIScrollRect 滑动组件
--- @param tabsCount number tabs总数
--- @param maxVisitableTabCount number 最大tabs可见数
--- @param duration number 滑动动画持续时间
function SupplementarySlidingComponent:CheckFixScroll(index, compSr, tabsCount, maxVisitableTabCount, duration)
--补充滑动 需要当前tabs超过视野范围最大数量
if tabsCount < maxVisitableTabCount then
return
end
--每个标签页长度 所占滑动进度的百分比
local tabScrollProgressRate = 1 / (tabsCount - maxVisitableTabCount)
--Logger.Info("ShopWindow", "每个标签页所占百分比=" .. tabScrollProgressRate)
--进度数据有误差 保留两位小数四舍五入
local fixScrollProgressValue = Mathf.Floor(compSr.horizontalNormalizedPosition * 100 + 0.5) / 100
--Logger.Info("ShopWindow", "当前滑动组件进度=" .. fixScrollProgressValue)
--当前视野范围内最小索引
local currentVisitableTabMinIndex = 1 + Mathf.Floor(fixScrollProgressValue / tabScrollProgressRate)
--Logger.Info("ShopWindow", "当前视野范围内最小索引=" .. currentVisitableTabMinIndex)
local currentVisitableTabMaxIndex = maxVisitableTabCount + Mathf.Ceil(fixScrollProgressValue / tabScrollProgressRate)
--Logger.Info("ShopWindow", "当前视野范围内最大索引=" .. currentVisitableTabMaxIndex)
--当前索引是视野范围内最后一项 补充左划
if index == currentVisitableTabMaxIndex or index == currentVisitableTabMinIndex then
--滑到index对应tab到视野中心
local indexMiddlePosProgress = (index - (maxVisitableTabCount * 0.5 + 0.5)) * tabScrollProgressRate
local fixIndexMiddlePosProgress = Mathf.Clamp01(indexMiddlePosProgress)
compSr:DoNormalizedPosition(Vector2(fixIndexMiddlePosProgress, compSr.verticalNormalizedPosition), duration)
return
end
-- 补充右划
if index == currentVisitableTabMinIndex then
--滑到index对应tab到视野中心 对应的滚动进度
local indexMiddlePosProgress = ((maxVisitableTabCount * 0.5 + 0.5) - index) * tabScrollProgressRate
local fixIndexMiddlePosProgress = Mathf.Clamp01(indexMiddlePosProgress)
compSr:DoNormalizedPosition(Vector2(fixIndexMiddlePosProgress, compSr.verticalNormalizedPosition), duration)
end
end