private void SetElement(float distance2Top, ElementPositionInfo elementPositionInfo)
 {
     if (distance2Top >= this.visualRange.x && distance2Top <= this.visualRange.y && !elementPositionInfo.Visible)
     {
         if (elementPositionInfo.Invisible)
         {
             ElementBuffer buffer = GetUsableBuffer(elementPositionInfo.ElementIndex);
             if (buffer != null)
             {
                 buffer.Use(elementPositionInfo);
                 buffer.SetSize(this.GetElementSize(elementPositionInfo.ElementIndex));
                 this.Adapter.FillElementData(buffer, elementPositionInfo.ElementIndex);
             }
         }
         else if (elementPositionInfo.VisibleAndNeedRefresh)
         {
             ElementBuffer buffer = elementPositionInfo.Buffer;
             if (buffer != null)
             {
                 buffer.Use(elementPositionInfo);
                 buffer.SetSize(this.GetElementSize(elementPositionInfo.ElementIndex));
                 this.Adapter.FillElementData(buffer, elementPositionInfo.ElementIndex);
             }
         }
     }
 }
        public virtual void GotoIndex(int index, float duration = 0.5f, Action onComplete = null)
        {
            ElementPositionInfo element = null;

            if (this.elementPositionInfoMapper.TryGetValue(index, out element))
            {
                if (this.Vertical)
                {
                    float height = -element.LocalPos.y;

                    if (duration > 0)
                    {
                        DOTween.Sequence().Append(content.DOLocalMoveY(height, duration))
                        .AppendCallback(() =>
                        {
                            if (onComplete != null)
                            {
                                onComplete();
                            }
                        }).Play();
                    }
                    else
                    {
                        content.localPosition = new Vector3(content.localPosition.x, height, content.localPosition.z);
                        this.FillData();
                        if (onComplete != null)
                        {
                            onComplete();
                        }
                    }
                }
                else if (this.Horizontal)
                {
                    float width = -element.LocalPos.x;
                    if (duration > 0)
                    {
                        DOTween.Sequence().Append(content.DOLocalMoveX(width, duration))
                        .AppendCallback(() =>
                        {
                            if (onComplete != null)
                            {
                                onComplete();
                            }
                        }).Play();
                    }
                    else
                    {
                        content.localPosition = new Vector3(width, content.localPosition.y, content.localPosition.z);
                        this.FillData();
                        if (onComplete != null)
                        {
                            onComplete();
                        }
                    }
                }
            }
        }
        private void AddElementPositionInfo(int elementIndex, Vector3 localPos)
        {
            ElementPositionInfo positionInfo = null;

            if (this.elementPositionInfoMapper.TryGetValue(elementIndex, out positionInfo))
            {
                positionInfo.LocalPos = localPos;
            }
            else
            {
                this.elementPositionInfoMapper.Add(elementIndex, new ElementPositionInfo(elementIndex, localPos));
            }
        }
        public void Use(ElementPositionInfo elementPositionInfo)
        {
            this.isUsing      = true;
            this.positionInfo = elementPositionInfo;

            elementPositionInfo.SetBuffer(this);
            elementPositionInfo.State = ElementState.visible;

            this.elementIndex = elementPositionInfo.ElementIndex;
            this.bufferGameObject.SetActive(true);
            this.rectTransform.localPosition = elementPositionInfo.LocalPos;
            this.bufferGameObject.name       = elementPositionInfo.ElementIndex.ToString();
            this.rectTransform.SetSiblingIndex(elementPositionInfo.ElementIndex);
        }
        private void FillData(int currentIndex = -1)
        {
            RecycleBuffers();
            currentIndex = currentIndex == -1 ? this.GetCurrentIndex() : currentIndex;

            if (this.Vertical)
            {
                float currentPos   = content.localPosition.y;
                float distance2Top = 0f;
                for (int i = currentIndex; i >= 0 && distance2Top >= this.visualRange.x && distance2Top <= this.visualRange.y; i--)
                {
                    ElementPositionInfo elementPositionInfo = this.elementPositionInfoMapper[i];
                    distance2Top = -elementPositionInfo.LocalPos.y - currentPos;
                    SetElement(distance2Top, elementPositionInfo);
                }
                distance2Top = 0f;
                for (int i = currentIndex; i < this.elementPositionInfoMapper.Count && distance2Top >= this.visualRange.x && distance2Top <= this.visualRange.y; i++)
                {
                    ElementPositionInfo elementPositionInfo = this.elementPositionInfoMapper[i];
                    distance2Top = -elementPositionInfo.LocalPos.y - currentPos;
                    SetElement(distance2Top, elementPositionInfo);
                }
            }
            else if (this.Horizontal)
            {
                float currentPos   = content.localPosition.x;
                float distance2Top = 0f;
                for (int i = currentIndex; i >= 0 && distance2Top >= this.visualRange.x && distance2Top <= this.visualRange.y; i--)
                {
                    ElementPositionInfo elementPositionInfo = this.elementPositionInfoMapper[i];
                    distance2Top = elementPositionInfo.LocalPos.x + currentPos;
                    SetElement(distance2Top, elementPositionInfo);
                }
                distance2Top = 0f;
                for (int i = currentIndex; i < this.elementPositionInfoMapper.Count && distance2Top >= this.visualRange.x && distance2Top <= this.visualRange.y; i++)
                {
                    ElementPositionInfo elementPositionInfo = this.elementPositionInfoMapper[i];
                    distance2Top = elementPositionInfo.LocalPos.x + currentPos;
                    SetElement(distance2Top, elementPositionInfo);
                }
            }
        }