[NUI] Fix some typos. (#1807)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Controls / FlexibleView / FlexibleViewLayoutManager.cs
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using Tizen.NUI.BaseComponents;
5
6 namespace Tizen.NUI.Components
7 {
8     /// <summary>
9     /// A FlexibleViewLayoutManager is responsible for measuring and positioning item views within a FlexibleView
10     /// as well as determining the policy for when to recycle item views that are no longer visible to the user.
11     /// </summary>
12     /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
13     [EditorBrowsable(EditorBrowsableState.Never)]
14     public abstract class FlexibleViewLayoutManager : Disposable
15     {
16         /// <summary>
17         /// Direction
18         /// </summary>
19         public enum Direction
20         {
21             /// <summary>
22             /// Left
23             /// </summary>
24             Left,
25
26             /// <summary>
27             /// Right
28             /// </summary>
29             Right,
30
31             /// <summary>
32             /// Up
33             /// </summary>
34             Up,
35
36             /// <summary>
37             /// Down
38             /// </summary>
39             Down
40         }
41
42         private readonly int SCROLL_ANIMATION_DURATION = 500;
43
44         private FlexibleView mFlexibleView;
45         private FlexibleView.ChildHelper mChildHelper;
46
47         private List<FlexibleViewViewHolder> mPendingRecycleViews = new List<FlexibleViewViewHolder>();
48
49         private Animation mScrollAni;
50
51         /// <summary>
52         /// Layout all relevant child views from the given adapter.
53         /// </summary>
54         /// <param name="recycler">Recycler to use for fetching potentially cached views for a position</param>
55         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
56         [EditorBrowsable(EditorBrowsableState.Never)]
57         public abstract void OnLayoutChildren(FlexibleViewRecycler recycler);
58
59         /// <summary>
60         /// Called after a full layout calculation is finished.
61         /// </summary>
62         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
63         [EditorBrowsable(EditorBrowsableState.Never)]
64         public virtual void OnLayoutCompleted()
65         {
66         }
67
68         /// <summary>
69         /// Gets the current focus position in adapter.
70         /// </summary>
71         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
72         [EditorBrowsable(EditorBrowsableState.Never)]
73         public int FocusPosition
74         {
75             get
76             {
77                 return mFlexibleView.FocusedItemIndex;
78             }
79         }
80
81         /// <summary>
82         /// Gets the datas count in data sets.
83         /// </summary>
84         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
85         [EditorBrowsable(EditorBrowsableState.Never)]
86         public int ItemCount
87         {
88             get
89             {
90                 FlexibleViewAdapter b = mFlexibleView != null ? mFlexibleView.GetAdapter() : null;
91
92                 return b != null ? b.GetItemCount() : 0;
93             }
94         }
95
96         /// <summary>
97         /// Query if horizontal scrolling is currently supported. The default implementation returns false.
98         /// </summary>
99         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
100         [EditorBrowsable(EditorBrowsableState.Never)]
101         public virtual bool CanScrollHorizontally()
102         {
103             return false;
104         }
105
106         /// <summary>
107         /// Query if vertical scrolling is currently supported. The default implementation returns false.
108         /// </summary>
109         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
110         [EditorBrowsable(EditorBrowsableState.Never)]
111         public virtual bool CanScrollVertically()
112         {
113             return false;
114         }
115
116         /// <summary>
117         /// Scroll horizontally by dy pixels in screen coordinates.
118         /// </summary>
119         /// <param name="dy">distance to scroll in pixels. Y increases as scroll position approaches the top.</param>
120         /// <param name="recycler">Recycler to use for fetching potentially cached views for a position</param>
121         /// <param name="immediate">Specify if the scroll need animation</param>
122         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
123         [EditorBrowsable(EditorBrowsableState.Never)]
124         public virtual float ScrollHorizontallyBy(float dy, FlexibleViewRecycler recycler, bool immediate)
125         {
126             return 0;
127         }
128
129         /// <summary>
130         /// Scroll vertically by dy pixels in screen coordinates.
131         /// </summary>
132         /// <param name="dy">distance to scroll in pixels. Y increases as scroll position approaches the top.</param>
133         /// <param name="recycler">Recycler to use for fetching potentially cached views for a position</param>
134         /// <param name="immediate">Specify if the scroll need animation</param>
135         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
136         [EditorBrowsable(EditorBrowsableState.Never)]
137         public virtual float ScrollVerticallyBy(float dy, FlexibleViewRecycler recycler, bool immediate)
138         {
139             return 0;
140         }
141
142         /// <summary>
143         /// Compute the extent of the scrollbar's thumb within the range.
144         /// </summary>
145         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
146         [EditorBrowsable(EditorBrowsableState.Never)]
147         public virtual float ComputeScrollExtent()
148         {
149             return 0;
150         }
151
152         /// <summary>
153         /// Compute the offset of the scrollbar's thumb within the range.
154         /// </summary>
155         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
156         [EditorBrowsable(EditorBrowsableState.Never)]
157         public virtual float ComputeScrollOffset()
158         {
159             return 0;
160         }
161
162         /// <summary>
163         /// Compute the range that the scrollbar represents.
164         /// </summary>
165         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
166         [EditorBrowsable(EditorBrowsableState.Never)]
167         public virtual float ComputeScrollRange()
168         {
169             return 0;
170         }
171
172         /// <summary>
173         /// Scroll the FlexibleView to make the position visible.
174         /// </summary>
175         /// <param name="position">Scroll to this adapter position</param>
176         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
177         [EditorBrowsable(EditorBrowsableState.Never)]
178         public virtual void ScrollToPosition(int position)
179         {
180
181         }
182
183         /// <summary>
184         /// Scroll to the specified adapter position with the given offset from resolved layout start.
185         /// </summary>
186         /// <param name="position">Scroll to this adapter position</param>
187         /// <param name="offset">The distance (in pixels) between the start edge of the item view and start edge of the FlexibleView.</param>
188         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
189         [EditorBrowsable(EditorBrowsableState.Never)]
190         public virtual void ScrollToPositionWithOffset(int position, int offset)
191         {
192
193         }
194
195         internal void MoveFocus(FlexibleViewLayoutManager.Direction direction, FlexibleViewRecycler recycler)
196         {
197             int prevFocusPosition = FocusPosition;
198             int nextFocusPosition = GetNextPosition(FocusPosition, direction);
199             if (nextFocusPosition == FlexibleView.NO_POSITION)
200             {
201                 return;
202             }
203
204             FlexibleViewViewHolder nextFocusChild = FindItemViewByPosition(nextFocusPosition);
205             if (nextFocusChild == null)
206             {
207                 nextFocusChild = OnFocusSearchFailed(null, direction, recycler);
208             }
209
210             if (nextFocusChild != null)
211             {
212                 RequestChildRectangleOnScreen(mFlexibleView, nextFocusChild, recycler, false);
213
214                 ChangeFocus(nextFocusPosition);
215             }
216         }
217
218         /**
219          * Requests that the given child of the FlexibleViewRecyclerView be positioned onto the screen. This
220          * method can be called for both unfocusable and focusable child views. For unfocusable
221          * child views, focusedChildVisible is typically true in which case, layout manager
222          * makes the child view visible only if the currently focused child stays in-bounds of RV.
223          * @param parent The parent FlexibleViewRecyclerView.
224          * @param child The direct child making the request.
225          * @param rect The rectangle in the child's coordinates the child
226          *              wishes to be on the screen.
227          * @param immediate True to forbid animated or delayed scrolling,
228          *                  false otherwise
229          * @param focusedChildVisible Whether the currently focused view must stay visible.
230          * @return Whether the group scrolled to handle the operation
231          */
232         internal bool RequestChildRectangleOnScreen(FlexibleView parent, FlexibleViewViewHolder child, FlexibleViewRecycler recycler, bool immediate)
233         {
234             Vector2 scrollAmount = GetChildRectangleOnScreenScrollAmount(parent, child);
235             float dx = scrollAmount[0];
236             float dy = scrollAmount[1];
237             if (dx != 0 || dy != 0)
238             {
239                 if (dx != 0 && CanScrollHorizontally())
240                 {
241                     ScrollHorizontallyBy(dx, recycler, immediate);
242                 }
243                 else if (dy != 0 && CanScrollVertically())
244                 {
245                     ScrollVerticallyBy(dy, recycler, immediate);
246                 }
247                 return true;
248             }
249             return false;
250         }
251
252         /// <summary>
253         /// Calls {@code FlexibleView#RelayoutRequest} on the underlying FlexibleView.
254         /// </summary>
255         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
256         [EditorBrowsable(EditorBrowsableState.Never)]
257         public void RelayoutRequest()
258         {
259             if (mFlexibleView != null)
260             {
261                 mFlexibleView.LayoutManagerRelayoutRequest();
262             }
263         }
264
265         /// <summary>
266         /// Lay out the given child view within the FlexibleView using coordinates that include view margins.
267         /// </summary>
268         /// <param name="child">Child to lay out</param>
269         /// <param name="left">Left edge, with item view left margin included</param>
270         /// <param name="top">Top edge, with item view top margin included</param>
271         /// <param name="width">Width, with item view left and right margin included</param>
272         /// <param name="height">Height, with item view top and bottom margin included</param>
273         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
274         [EditorBrowsable(EditorBrowsableState.Never)]
275         public void LayoutChild(FlexibleViewViewHolder child, float left, float top, float width, float height)
276         {
277             if (null == child) return;
278             View itemView = child.ItemView;
279             itemView.SizeWidth = width - itemView.Margin.Start - itemView.Margin.End;
280             itemView.SizeHeight = height - itemView.Margin.Top - itemView.Margin.Bottom;
281             itemView.PositionX = left + itemView.Margin.Start;
282             itemView.PositionY = top + itemView.Margin.Top;
283         }
284
285         /// <summary>
286         /// Change the FlexibleViewViewHolder with focusPosition to focus.
287         /// </summary>
288         /// <param name="focusPosition">the newly focus position</param>
289         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
290         [EditorBrowsable(EditorBrowsableState.Never)]
291         public void ChangeFocus(int focusPosition)
292         {
293             if (mFlexibleView != null)
294             {
295                 mFlexibleView.DispatchFocusChanged(focusPosition);
296             }
297         }
298
299         /// <summary>
300         /// Return the current number of child views attached to the parent FlexibleView.
301         /// </summary>
302         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
303         [EditorBrowsable(EditorBrowsableState.Never)]
304         public int ChildCount
305         {
306             get
307             {
308                 return mChildHelper != null ? mChildHelper.GetChildCount() : 0;
309             }
310         }
311
312         /// <summary>
313         /// Return the child view at the given index.
314         /// </summary>
315         /// <param name="index">child index</param>
316         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
317         [EditorBrowsable(EditorBrowsableState.Never)]
318         public FlexibleViewViewHolder GetChildAt(int index)
319         {
320             return mChildHelper != null ? mChildHelper.GetChildAt(index) : null;
321         }
322
323         /// <summary>
324         /// Finds the view which represents the given adapter position.
325         /// </summary>
326         /// <param name="position">adapter position</param>
327         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
328         [EditorBrowsable(EditorBrowsableState.Never)]
329         public FlexibleViewViewHolder FindItemViewByPosition(int position)
330         {
331             return mFlexibleView.FindViewHolderForLayoutPosition(position);
332         }
333
334         /// <summary>
335         /// Offset all child views attached to the parent FlexibleView by dx pixels along the horizontal axis.
336         /// </summary>
337         /// <param name="dx">Pixels to offset by </param>
338         /// <param name="immediate">specify if the offset need animation</param>
339         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
340         [EditorBrowsable(EditorBrowsableState.Never)]
341         public void OffsetChildrenHorizontal(float dx, bool immediate)
342         {
343             if (mChildHelper == null)
344             {
345                 return;
346             }
347
348             if (dx == 0)
349             {
350                 return;
351             }
352
353             int childCount = mChildHelper.GetChildCount();
354             if (immediate == true)
355             {
356                 for (int i = childCount - 1; i >= 0; i--)
357                 {
358                     FlexibleViewViewHolder v = mChildHelper.GetChildAt(i);
359                     v.ItemView.PositionX += dx;
360                 }
361             }
362             else
363             {
364                 if (mScrollAni == null)
365                 {
366                     mScrollAni = new Animation();
367                     mScrollAni.Duration = SCROLL_ANIMATION_DURATION;
368                     mScrollAni.DefaultAlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSquare);
369                 }
370
371                 // avoid out of boundary of flexibleview. delta value might be used for shadow.
372                 // this must be done before animation clear.
373                 if (childCount > 0)
374                 {
375                     FlexibleViewViewHolder vh = mChildHelper.GetChildAt(0);
376                     if (vh.LayoutPosition == 0)
377                     {
378                         if ((int)(vh.Left + dx) > 0)
379                         {
380                             dx = 0 - vh.Left;
381                         }
382                     }
383
384                     vh = mChildHelper.GetChildAt(childCount - 1);
385                     if (vh.LayoutPosition == ItemCount - 1)
386                     {
387                         if ((int)(vh.Right + dx) < (int)Width + PaddingRight)
388                         {
389                             dx = Width + PaddingRight - vh.Right;
390                         }
391                     }
392                 }
393
394                 // save position before animation clear.
395                 float[] childrenPosition = new float[childCount];
396                 for (int i = childCount - 1; i >= 0; i--)
397                 {
398                     FlexibleViewViewHolder v = mChildHelper.GetChildAt(i);
399                     childrenPosition[i] = v.ItemView.PositionX;
400                 }
401
402                 mScrollAni.Clear();
403                 mScrollAni.Finished += OnScrollAnimationFinished;
404
405                 for (int i = childCount - 1; i >= 0; i--)
406                 {
407                     FlexibleViewViewHolder v = mChildHelper.GetChildAt(i);
408                     // set position again because position might be changed after animation clear.
409                     v.ItemView.PositionX = childrenPosition[i];
410                     mScrollAni.AnimateTo(v.ItemView, "PositionX", v.ItemView.PositionX + dx);
411                 }
412                 mScrollAni.Play();
413             }
414         }
415
416         /// <summary>
417         /// Offset all child views attached to the parent FlexibleView by dy pixels along the vertical axis.
418         /// </summary>
419         /// <param name="dy">Pixels to offset by </param>
420         /// <param name="immediate">specify if the offset need animation</param>
421         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
422         [EditorBrowsable(EditorBrowsableState.Never)]
423         public void OffsetChildrenVertical(float dy, bool immediate)
424         {
425             if (mChildHelper == null)
426             {
427                 return;
428             }
429
430             if (dy == 0)
431             {
432                 return;
433             }
434
435             int childCount = mChildHelper.GetChildCount();
436             if (immediate == true)
437             {
438                 for (int i = childCount - 1; i >= 0; i--)
439                 {
440                     FlexibleViewViewHolder v = mChildHelper.GetChildAt(i);
441                     v.ItemView.PositionY += dy;
442                 }
443             }
444             else
445             {
446                 if (mScrollAni == null)
447                 {
448                     mScrollAni = new Animation();
449                     mScrollAni.Duration = SCROLL_ANIMATION_DURATION;
450                     mScrollAni.DefaultAlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSquare);
451                 }
452
453                 // avoid out of boundary of flexibleview. delta value might be used for shadow.
454                 // this must be done before animation clear.
455                 if (childCount > 0)
456                 {
457                     FlexibleViewViewHolder vh = mChildHelper.GetChildAt(0);
458                     if (vh.LayoutPosition == 0)
459                     {
460                         if ((int)(vh.Top + dy) > 0)
461                         {
462                             dy = 0 - vh.Top;
463                         }
464                     }
465
466                     vh = mChildHelper.GetChildAt(childCount - 1);
467                     if (vh.LayoutPosition == ItemCount - 1)
468                     {
469                         if ((int)(vh.Bottom + dy) < (int)Height + PaddingBottom)
470                         {
471                             dy = Height + PaddingBottom - vh.Bottom;
472                         }
473                     }
474                 }
475
476                 // save position before animation clear.
477                 float[] childPosition = new float[childCount];
478                 for (int i = childCount - 1; i >= 0; i--)
479                 {
480                     FlexibleViewViewHolder v = mChildHelper.GetChildAt(i);
481                     childPosition[i] = v.ItemView.PositionY;
482                 }
483
484                 mScrollAni.Clear();
485                 mScrollAni.Finished += OnScrollAnimationFinished;
486
487                 for (int i = childCount - 1; i >= 0; i--)
488                 {
489                     FlexibleViewViewHolder v = mChildHelper.GetChildAt(i);
490                     // set position again because position might be changed after animation clear.
491                     v.ItemView.PositionY = childPosition[i];
492                     mScrollAni.AnimateTo(v.ItemView, "PositionY", v.ItemView.PositionY + dy);
493                 }
494                 mScrollAni.Play();
495             }
496         }
497
498         /// <summary>
499         /// Return the width of the parent FlexibleView.
500         /// </summary>
501         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
502         [EditorBrowsable(EditorBrowsableState.Never)]
503         public float Width
504         {
505             get
506             {
507                 return mFlexibleView != null ? mFlexibleView.SizeWidth : 0;
508             }
509         }
510
511         /// <summary>
512         /// Return the height of the parent FlexibleView.
513         /// </summary>
514         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
515         [EditorBrowsable(EditorBrowsableState.Never)]
516         public float Height
517         {
518             get
519             {
520                 return mFlexibleView != null ? mFlexibleView.SizeHeight : 0;
521             }
522         }
523
524         /// <summary>
525         /// Return the left padding of the parent FlexibleView.
526         /// </summary>
527         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
528         [EditorBrowsable(EditorBrowsableState.Never)]
529         public int PaddingLeft
530         {
531             get
532             {
533                 return mFlexibleView?.Padding?.Start ?? 0;
534             }
535         }
536
537         /// <summary>
538         /// Return the top padding of the parent FlexibleView.
539         /// </summary>
540         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
541         [EditorBrowsable(EditorBrowsableState.Never)]
542         public int PaddingTop
543         {
544             get
545             {
546                 return mFlexibleView?.Padding?.Top ?? 0;
547             }
548         }
549
550         /// <summary>
551         /// Return the right padding of the parent FlexibleView.
552         /// </summary>
553         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
554         [EditorBrowsable(EditorBrowsableState.Never)]
555         public int PaddingRight
556         {
557             get
558             {
559                 return mFlexibleView?.Padding?.End ?? 0;
560             }
561         }
562
563         /// <summary>
564         /// Return the bottom padding of the parent FlexibleView.
565         /// </summary>
566         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
567         [EditorBrowsable(EditorBrowsableState.Never)]
568         public int PaddingBottom
569         {
570             get
571             {
572                 return mFlexibleView?.Padding?.Bottom ?? 0;
573             }
574         }
575
576         /// <summary>
577         /// Add a view to the currently attached FlexibleView if needed.<br />
578         /// FlexibleViewLayoutManagers should use this method to add views obtained from a FlexibleViewRecycler using getViewForPosition(int).<br />
579         /// </summary>
580         /// <param name="holder">view to add</param>
581         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
582         [EditorBrowsable(EditorBrowsableState.Never)]
583         public void AddView(FlexibleViewViewHolder holder)
584         {
585             AddView(holder, -1);
586         }
587
588         /// <summary>
589         /// Add a view to the currently attached FlexibleView if needed.<br />
590         /// FlexibleViewLayoutManagers should use this method to add views obtained from a FlexibleViewRecycler using getViewForPosition(int).<br />
591         /// </summary>
592         /// <param name="holder">view to add</param>
593         /// <param name="index">index to add child at</param>
594         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
595         [EditorBrowsable(EditorBrowsableState.Never)]
596         public void AddView(FlexibleViewViewHolder holder, int index)
597         {
598             AddViewInternal(holder, index, false);
599         }
600
601         /// <summary>
602         /// Temporarily detach and scrap all currently attached child views.
603         /// Views will be scrapped into the given FlexibleViewRecycler.
604         /// The FlexibleViewRecycler may prefer to reuse scrap views before other views that were previously recycled.
605         /// </summary>
606         /// <param name="recycler">Recycler to scrap views into</param>
607         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
608         [EditorBrowsable(EditorBrowsableState.Never)]
609         public void ScrapAttachedViews(FlexibleViewRecycler recycler)
610         {
611             if (null == mChildHelper || null == recycler)
612             {
613                 return;
614             }
615
616             recycler.Clear();
617
618             mChildHelper.ScrapViews(recycler);
619         }
620
621         /**
622          * Remove a child view and recycle it using the given FlexibleViewRecycler.
623          *
624          * @param index Index of child to remove and recycle
625          * @param recycler FlexibleViewRecycler to use to recycle child
626          */
627         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
628         [EditorBrowsable(EditorBrowsableState.Never)]
629         public void RemoveAndRecycleViewAt(int index, FlexibleViewRecycler recycler)
630         {
631             if (null == recycler) return;
632             FlexibleViewViewHolder v = mChildHelper.GetChildAt(index);
633             mChildHelper.RemoveViewAt(index);
634             recycler.RecycleView(v);
635         }
636
637         /// <summary>
638         /// ecycles children between given indices..
639         /// </summary>
640         /// <param name="recycler">Recycler to recycle views into</param>
641         /// <param name="startIndex">inclusive</param>
642         /// <param name="endIndex">exclusive</param>
643         /// <param name="immediate">recycle immediately or add to pending list and recycle later.</param>
644         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
645         [EditorBrowsable(EditorBrowsableState.Never)]
646         public void RecycleChildren(FlexibleViewRecycler recycler, int startIndex, int endIndex, bool immediate)
647         {
648             if (startIndex == endIndex)
649             {
650                 return;
651             }
652             if (endIndex > startIndex)
653             {
654                 for (int i = startIndex; i < endIndex; i++)
655                 {
656                     FlexibleViewViewHolder v = mChildHelper.GetChildAt(i);
657                     if (v.PendingRecycle == false)
658                     {
659                         v.PendingRecycle = true;
660                         mPendingRecycleViews.Add(v);
661                     }
662                 }
663             }
664             else
665             {
666                 for (int i = startIndex; i > endIndex; i--)
667                 {
668                     FlexibleViewViewHolder v = mChildHelper.GetChildAt(i);
669                     if (v.PendingRecycle == false)
670                     {
671                         v.PendingRecycle = true;
672                         mPendingRecycleViews.Add(v);
673                     }
674                 }
675             }
676             if (immediate == true)
677             {
678                 RecycleChildrenInt(recycler);
679             }
680         }
681
682         /// <summary>
683         /// Retrieves a position that neighbor to current position by direction.
684         /// </summary>
685         /// <param name="position">The anchor adapter position</param>
686         /// <param name="direction">The direction.</param>
687         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
688         [EditorBrowsable(EditorBrowsableState.Never)]
689         protected abstract int GetNextPosition(int position, FlexibleViewLayoutManager.Direction direction);
690
691         /// <summary>
692         /// Retrieves the first visible item view.
693         /// </summary>
694         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
695         [EditorBrowsable(EditorBrowsableState.Never)]
696         protected virtual FlexibleViewViewHolder FindFirstVisibleItemView()
697         {
698             return null;
699         }
700
701         /// <summary>
702         /// Retrieves the last visible item view.
703         /// </summary>
704         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
705         [EditorBrowsable(EditorBrowsableState.Never)]
706         protected virtual FlexibleViewViewHolder FindLastVisibleItemView()
707         {
708             return null;
709         }
710
711         /// <summary>
712         /// Dispose FlexibleView and all children on it.
713         /// </summary>
714         /// <param name="type">Dispose type.</param>
715         [EditorBrowsable(EditorBrowsableState.Never)]
716         protected override void Dispose(DisposeTypes type)
717         {
718             if (disposed)
719             {
720                 return;
721             }
722
723             if (type == DisposeTypes.Explicit)
724             {
725                 mScrollAni?.Dispose();
726             }
727
728             base.Dispose(type);
729         }
730
731         internal virtual FlexibleViewViewHolder OnFocusSearchFailed(FlexibleViewViewHolder focused, FlexibleViewLayoutManager.Direction direction, FlexibleViewRecycler recycler)
732         {
733             return null;
734         }
735
736         internal void SetRecyclerView(FlexibleView recyclerView)
737         {
738             mFlexibleView = recyclerView;
739             mChildHelper = recyclerView.GetChildHelper();
740         }
741
742         internal void ClearRecyclerView()
743         {
744             mFlexibleView = null;
745             mChildHelper = null;
746         }
747
748         internal void StopScroll(bool doSomethingAfterAnimationStopped)
749         {
750             if (mScrollAni != null && mScrollAni.State == Animation.States.Playing)
751             {
752                 mScrollAni.Finished -= OnScrollAnimationFinished;
753                 mScrollAni.Stop();
754
755                 if (doSomethingAfterAnimationStopped)
756                 {
757                     OnScrollAnimationFinished(mScrollAni, null);
758                 }
759             }
760         }
761
762         /**
763          * Returns the scroll amount that brings the given rect in child's coordinate system within
764          * the padded area of FlexibleViewRecyclerView.
765          * @param parent The parent FlexibleViewRecyclerView.
766          * @param child The direct child making the request.
767          * @param rect The rectangle in the child's coordinates the child
768          *             wishes to be on the screen.
769          * @param immediate True to forbid animated or delayed scrolling,
770          *                  false otherwise
771          * @return The array containing the scroll amount in x and y directions that brings the
772          * given rect into RV's padded area.
773          */
774         private Vector2 GetChildRectangleOnScreenScrollAmount(FlexibleView parent, FlexibleViewViewHolder child)
775         {
776             Vector2 ret = new Vector2(0, 0);
777             int parentLeft = PaddingLeft;
778             int parentTop = PaddingTop;
779             int parentRight = (int)Width - PaddingRight;
780             int parentBottom = (int)Height - PaddingBottom;
781             int childLeft = (int)child.Left;
782             int childTop = (int)child.Top;
783             int childRight = (int)child.Right;
784             int childBottom = (int)child.Bottom;
785
786             int offScreenLeft = Math.Min(0, childLeft - parentLeft);
787             int offScreenTop = Math.Min(0, childTop - parentTop);
788             int offScreenRight = Math.Max(0, childRight - parentRight);
789             int offScreenBottom = Math.Max(0, childBottom - parentBottom);
790
791             // Favor the "start" layout direction over the end when bringing one side or the other
792             // of a large rect into view. If we decide to bring in end because start is already
793             // visible, limit the scroll such that start won't go out of bounds.
794             int dx = offScreenLeft != 0 ? offScreenLeft
795                         : Math.Min(childLeft - parentLeft, offScreenRight);
796
797             // Favor bringing the top into view over the bottom. If top is already visible and
798             // we should scroll to make bottom visible, make sure top does not go out of bounds.
799             int dy = offScreenTop != 0 ? offScreenTop
800                     : Math.Min(childTop - parentTop, offScreenBottom);
801
802             ret.X = -dx;
803             ret.Y = -dy;
804
805             return ret;
806         }
807
808         private void OnScrollAnimationFinished(object sender, EventArgs e)
809         {
810             foreach (FlexibleViewViewHolder holder in mPendingRecycleViews)
811             {
812                 holder.PendingRecycle = false;
813             }
814             mPendingRecycleViews.Clear();
815
816             int start = FlexibleView.NO_POSITION;
817             FlexibleViewViewHolder firstItemView = FindFirstVisibleItemView();
818             if (firstItemView != null)
819                 start = firstItemView.LayoutPosition;
820             else
821                 start = 0;
822
823             int itemCount = ChildCount;
824
825             int end = FlexibleView.NO_POSITION;
826             FlexibleViewViewHolder lastItemView = FindLastVisibleItemView();
827             if (lastItemView != null)
828                 end = lastItemView.LayoutPosition;
829             else
830                 end = itemCount - 1;
831
832             List<FlexibleViewViewHolder> removedViewList = new List<FlexibleViewViewHolder>();
833             for (int i = 0; i < itemCount; i++)
834             {
835                 FlexibleViewViewHolder v = GetChildAt(i);
836
837                 //if item view of holder is visible, it should not be recycled.
838                 if (v.LayoutPosition >= start && v.LayoutPosition <= end)
839                     continue;
840
841                 removedViewList.Add(v);
842             }
843
844             for (int i = 0; i < removedViewList.Count; i++)
845             {
846                 FlexibleViewViewHolder v = removedViewList[i];
847                 v.PendingRecycle = false;
848                 mFlexibleView.GetRecycler().RecycleView(v);
849                 mChildHelper.RemoveView(v);
850             }
851
852             // relayout
853         }
854
855         private void AddViewInternal(FlexibleViewViewHolder holder, int index, bool disappearing)
856         {
857             if (null == holder) return;
858             if (holder.IsScrap())
859             {
860                 holder.Unscrap();
861                 mChildHelper.AttachView(holder, index);
862             }
863             else
864             {
865                 mChildHelper.AddView(holder, index);
866             }
867         }
868
869         private void RecycleChildrenInt(FlexibleViewRecycler recycler)
870         {
871             if (null == recycler) return;
872             foreach (FlexibleViewViewHolder holder in mPendingRecycleViews)
873             {
874                 holder.PendingRecycle = false;
875                 recycler.RecycleView(holder);
876                 mChildHelper.RemoveView(holder);
877             }
878             mPendingRecycleViews.Clear();
879         }
880
881         private void ScrapOrRecycleView(FlexibleViewRecycler recycler, FlexibleViewViewHolder itemView)
882         {
883             recycler.ScrapView(itemView);
884         }
885     }
886 }