{
if (mLayout != null)
{
- mLayout.StopScroll();
+ mLayout.StopScroll(false);
}
if (mAdapter != null)
{
offset = range - extent;
}
+ if (offset < 0)
+ {
+ offset = 0;
+ }
if (mScrollBar.Direction == ScrollBar.DirectionType.Vertical)
{
mScrollBar.ThumbSize = new Size(thickness, length);
{
if (e.PanGesture.State == Gesture.StateType.Started)
{
- mLayout.StopScroll();
+ mLayout.StopScroll(true);
}
else if (e.PanGesture.State == Gesture.StateType.Continuing)
{
Down
}
+ private readonly int SCROLL_ANIMATION_DURATION = 500;
+
private FlexibleView mFlexibleView;
private ChildHelper mChildHelper;
return;
}
- if (mScrollAni == null)
- {
- mScrollAni = new Animation();
- mScrollAni.Finished += OnScrollAnimationFinished;
- }
- else if (mScrollAni.State == Animation.States.Playing)
+ if (dx == 0)
{
- //StopScroll();
- mScrollAni.Stop(Animation.EndActions.StopFinal);
+ return;
}
- mScrollAni.Duration = 500;
- mScrollAni.DefaultAlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSquare);
-
- mScrollAni.Clear();
int childCount = mChildHelper.GetChildCount();
if (immediate == true)
}
else
{
+ if (mScrollAni == null)
+ {
+ mScrollAni = new Animation();
+ mScrollAni.Duration = SCROLL_ANIMATION_DURATION;
+ mScrollAni.DefaultAlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSquare);
+ }
+
+ // avoid out of boundary of flexibleview. delta value might be used for shadow.
+ // this must be done before animation clear.
+ if (childCount > 0)
+ {
+ ViewHolder vh = mChildHelper.GetChildAt(0);
+ if (vh.LayoutPosition == 0)
+ {
+ if ((int)(vh.Left + dx) > 0)
+ {
+ dx = 0 - vh.Left;
+ }
+ }
+
+ vh = mChildHelper.GetChildAt(childCount - 1);
+ if (vh.LayoutPosition == ItemCount - 1)
+ {
+ if ((int)(vh.Right + dx) < (int)Width + PaddingRight)
+ {
+ dx = Width + PaddingRight - vh.Right;
+ }
+ }
+ }
+
+ // save position before animation clear.
+ float[] childrenPositon = new float[childCount];
for (int i = childCount - 1; i >= 0; i--)
{
ViewHolder v = mChildHelper.GetChildAt(i);
+ childrenPositon[i] = v.ItemView.PositionX;
+ }
+
+ mScrollAni.Clear();
+ mScrollAni.Finished += OnScrollAnimationFinished;
+
+ for (int i = childCount - 1; i >= 0; i--)
+ {
+ ViewHolder v = mChildHelper.GetChildAt(i);
+ // set position again because position might be changed after animation clear.
+ v.ItemView.PositionX = childrenPositon[i];
mScrollAni.AnimateTo(v.ItemView, "PositionX", v.ItemView.PositionX + dx);
}
mScrollAni.Play();
return;
}
- if (mScrollAni == null)
- {
- mScrollAni = new Animation();
- mScrollAni.Finished += OnScrollAnimationFinished;
- }
- else if (mScrollAni.State == Animation.States.Playing)
+ if (dy == 0)
{
- //StopScroll();
- mScrollAni.Stop(Animation.EndActions.StopFinal);
+ return;
}
- mScrollAni.Duration = 500;
- mScrollAni.DefaultAlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSquare);
-
- mScrollAni.Clear();
int childCount = mChildHelper.GetChildCount();
if (immediate == true)
}
else
{
+ if (mScrollAni == null)
+ {
+ mScrollAni = new Animation();
+ mScrollAni.Duration = SCROLL_ANIMATION_DURATION;
+ mScrollAni.DefaultAlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSquare);
+ }
+
+ // avoid out of boundary of flexibleview. delta value might be used for shadow.
+ // this must be done before animation clear.
+ if (childCount > 0)
+ {
+ ViewHolder vh = mChildHelper.GetChildAt(0);
+ if (vh.LayoutPosition == 0)
+ {
+ if ((int)(vh.Top + dy) > 0)
+ {
+ dy = 0 - vh.Top;
+ }
+ }
+
+ vh = mChildHelper.GetChildAt(childCount - 1);
+ if (vh.LayoutPosition == ItemCount - 1)
+ {
+ if ((int)(vh.Bottom + dy) < (int)Height + PaddingBottom)
+ {
+ dy = Height + PaddingBottom - vh.Bottom;
+ }
+ }
+ }
+
+ // save position before animation clear.
+ float[] childPositon = new float[childCount];
for (int i = childCount - 1; i >= 0; i--)
{
ViewHolder v = mChildHelper.GetChildAt(i);
+ childPositon[i] = v.ItemView.PositionY;
+ }
+
+ mScrollAni.Clear();
+ mScrollAni.Finished += OnScrollAnimationFinished;
+
+ for (int i = childCount - 1; i >= 0; i--)
+ {
+ ViewHolder v = mChildHelper.GetChildAt(i);
+ // set position again because position might be changed after animation clear.
+ v.ItemView.PositionY = childPositon[i];
mScrollAni.AnimateTo(v.ItemView, "PositionY", v.ItemView.PositionY + dy);
}
mScrollAni.Play();
[EditorBrowsable(EditorBrowsableState.Never)]
protected abstract int GetNextPosition(int position, FlexibleView.LayoutManager.Direction direction);
+ /// <summary>
+ /// Retrieves the first visible item view.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected virtual ViewHolder FindFirstVisibleItemView()
+ {
+ return null;
+ }
+
+ /// <summary>
+ /// Retrieves the last visible item view.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected virtual ViewHolder FindLastVisibleItemView()
+ {
+ return null;
+ }
+
internal virtual ViewHolder OnFocusSearchFailed(FlexibleView.ViewHolder focused, LayoutManager.Direction direction, Recycler recycler)
{
return null;
mChildHelper = recyclerView.mChildHelper;
}
- internal void StopScroll()
+ internal void StopScroll(bool doSomethingAfterAnimationStopped)
{
if (mScrollAni != null && mScrollAni.State == Animation.States.Playing)
{
- mScrollAni.Stop(Animation.EndActions.StopFinal);
- mScrollAni.Clear();
- OnScrollAnimationFinished(mScrollAni, null);
+ mScrollAni.Finished -= OnScrollAnimationFinished;
+ mScrollAni.Stop();
+
+ if (doSomethingAfterAnimationStopped)
+ {
+ OnScrollAnimationFinished(mScrollAni, null);
+ }
}
}
private void OnScrollAnimationFinished(object sender, EventArgs e)
{
- RecycleChildrenInt(mFlexibleView.mRecycler);
+ foreach (ViewHolder holder in mPendingRecycleViews)
+ {
+ holder.PendingRecycle = false;
+ }
+ mPendingRecycleViews.Clear();
+
+ int start = NO_POSITION;
+ ViewHolder firstItemView = FindFirstVisibleItemView();
+ if (firstItemView != null)
+ start = firstItemView.LayoutPosition;
+ else
+ start = 0;
+
+ int itemCount = ChildCount;
+
+ int end = NO_POSITION;
+ ViewHolder lastItemView = FindLastVisibleItemView();
+ if (lastItemView != null)
+ end = lastItemView.LayoutPosition;
+ else
+ end = itemCount - 1;
+
+ List<ViewHolder> removedViewList = new List<ViewHolder>();
+ for (int i = 0; i < itemCount; i++)
+ {
+ ViewHolder v = GetChildAt(i);
+
+ //if item view of holder is visible, it should not be recycled.
+ if (v.LayoutPosition >= start && v.LayoutPosition <= end)
+ continue;
+
+ removedViewList.Add(v);
+ }
+
+ for (int i = 0; i < removedViewList.Count; i++)
+ {
+ ViewHolder v = removedViewList[i];
+ v.PendingRecycle = false;
+ mFlexibleView.mRecycler.RecycleView(v);
+ mChildHelper.RemoveView(v);
+ }
+
+ // relayout
}
private void AddViewInternal(ViewHolder holder, int index, bool disappearing)
return NO_POSITION;
}
+ /// <summary>
+ /// Retrieves the first visible item view.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected override FlexibleView.ViewHolder FindFirstVisibleItemView()
+ {
+ int childCount = ChildCount;
+ if (mShouldReverseLayout == false)
+ {
+ for (int i = 0; i < childCount; i++)
+ {
+ FlexibleView.ViewHolder child = GetChildAt(i);
+ int end = (int)mOrientationHelper.GetViewHolderEnd(child);
+ if (end >= 0 && end < (int)mOrientationHelper.GetEnd())
+ {
+ return child;
+ }
+ }
+ }
+ else
+ {
+ for (int i = childCount - 1; i >= 0; i--)
+ {
+ FlexibleView.ViewHolder child = GetChildAt(i);
+ int end = (int)mOrientationHelper.GetViewHolderEnd(child);
+ if (end >= 0 && end < (int)mOrientationHelper.GetEnd())
+ {
+ return child;
+ }
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Retrieves the last visible item view.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ protected override FlexibleView.ViewHolder FindLastVisibleItemView()
+ {
+ int childCount = ChildCount;
+ if (mShouldReverseLayout == false)
+ {
+ for (int i = childCount - 1; i >= 0; i--)
+ {
+ FlexibleView.ViewHolder child = GetChildAt(i);
+ int start = (int)mOrientationHelper.GetViewHolderStart(child);
+ if (start > 0 && start < (int)mOrientationHelper.GetEnd())
+ {
+ return child;
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i < childCount; i++)
+ {
+ FlexibleView.ViewHolder child = GetChildAt(i);
+ int start = (int)mOrientationHelper.GetViewHolderStart(child);
+ if (start > 0 && start < (int)mOrientationHelper.GetEnd())
+ {
+ return child;
+ }
+ }
+ }
+ return null;
+ }
+
internal virtual void LayoutChunk(FlexibleView.Recycler recycler,
LayoutState layoutState, LayoutChunkResult result)
{
return false;
}
- FlexibleView.ViewHolder anchorChild = FindFirstCompleteVisibleItemView();
+ FlexibleView.ViewHolder anchorChild = FindFirstVisibleItemView();
if (anchorChild == null)
{
- return false;
+ Log.Error("flexibleview", $"exception occurs when updating anchor information!");
+ anchorChild = GetChildAt(0);
}
anchorInfo.Position = anchorChild.LayoutPosition;
anchorInfo.Coordinate = mOrientationHelper.GetViewHolderStart(anchorChild);
mLayoutState.Extra = mOrientationHelper.GetStartAfterPadding();
}
- private FlexibleView.ViewHolder FindFirstVisibleItemView()
- {
- int childCount = ChildCount;
- if (mShouldReverseLayout == false)
- {
- for (int i = 0; i < childCount; i++)
- {
- FlexibleView.ViewHolder child = GetChildAt(i);
- if ((int)mOrientationHelper.GetViewHolderEnd(child) > 0)
- {
- return child;
- }
- }
- }
- else
- {
- for (int i = childCount - 1; i >= 0; i--)
- {
- FlexibleView.ViewHolder child = GetChildAt(i);
- if ((int)mOrientationHelper.GetViewHolderEnd(child) > 0)
- {
- return child;
- }
- }
- }
- return null;
- }
-
private FlexibleView.ViewHolder FindFirstCompleteVisibleItemView()
{
int childCount = ChildCount;
for (int i = 0; i < childCount; i++)
{
FlexibleView.ViewHolder child = GetChildAt(i);
- if ((int)mOrientationHelper.GetViewHolderStart(child) > 0)
+ int start = (int)mOrientationHelper.GetViewHolderStart(child);
+ if (start > 0 && start < (int)mOrientationHelper.GetEnd())
{
return child;
}
for (int i = childCount - 1; i >= 0; i--)
{
FlexibleView.ViewHolder child = GetChildAt(i);
- if ((int)mOrientationHelper.GetViewHolderStart(child) > 0)
- {
- return child;
- }
- }
- }
- return null;
- }
-
- private FlexibleView.ViewHolder FindLastVisibleItemView()
- {
- int childCount = ChildCount;
- if (mShouldReverseLayout == false)
- {
- for (int i = childCount - 1; i >= 0; i--)
- {
- FlexibleView.ViewHolder child = GetChildAt(i);
- if ((int)mOrientationHelper.GetViewHolderStart(child) < (int)mOrientationHelper.GetEnd())
- {
- return child;
- }
- }
- }
- else
- {
- for (int i = 0; i < childCount; i++)
- {
- FlexibleView.ViewHolder child = GetChildAt(i);
- if ((int)mOrientationHelper.GetViewHolderStart(child) < (int)mOrientationHelper.GetEnd())
+ int start = (int)mOrientationHelper.GetViewHolderStart(child);
+ if (start > 0 && start < (int)mOrientationHelper.GetEnd())
{
return child;
}