2 using Tizen.NUI.Constants;
4 using System.Runtime.InteropServices;
5 using System.Collections.Generic;
9 public class ScrollContainer : CustomView
11 private View _container; // View Container will be the first item added to ScrollContainer and parent to all the items added to the ScrollContainer.
12 private Size _itemSize; // Size of the item / images added to the ScrollContainer.
13 private List<View> _itemList; // List collection of View items/images added to the ScrollContainer.
14 private int _itemCount; // Number of items / images added to the ScrollContainer.
15 private int _focusedItem; // Index of currently focused View item / image on the ScrollContainer.
16 private float _scrollDisplacement; // Used for horizontal pan displacement.
17 private float _currentScrollPosition; // Used for horizontal scroll position.
18 private float _gap; // Used for gap / padding between items / images on the ScrollContainer.
19 private float _width; // Width of the ScrollContainer.
20 private float _height; // Height of the ScrollContainer.
21 private bool _isFocused; // Flag to check if ScrollContainer is enabled or not.
22 private float _marginX; // Extra horizontal margin is used to add an extra gap between items / images after a focused and scaled item / image.
23 private float _marginY; // Extra vertical margin (not used at the moment).
24 private float _offsetYFactor; // Vertical Position offset Factor of item height.
25 private float _offsetX; // Horizontal Position offset of ScrollContainer.
26 private Stage _stage; // Reference to Dali stage.
27 private Size2D _stageSize; // Reference to Dali stage size.
28 private ImageView _shadowBorder; // Reference to Shadow border ImageView applied to the focused item on ScrollContainer.
29 private ImageView _spotLight; // Reference to SpotLight ImageView applied to the focused item on ScrollContainer.
30 private Animation _spotLightAnimation; // SpotLight Animation applied to the focused item on ScrollContainer.
31 private Animation _focusAnimation; // Focused position animation on ScrollContainer.
32 private Animation _scrollAnimation; // Scroll animation on items of ScrollContainer.
33 private Animation _focusTransitionAnimation; // Focus Transition (scaling /unscaling) animation on items of ScrollContainer.
34 private Path _circularPath; // Circular path used for SpotLight Animation applied to the focused item on ScrollContainer.
36 public ScrollContainer() : base(ViewBehaviour.DisableStyleChangeSignals |
37 ViewBehaviour.RequiresKeyboardNavigationSupport)
48 public Tizen.NUI.View Container
75 Position topLeft = new Position(-0.25f * _itemSize.Width, -0.25f * _itemSize.Height, 0.0f);
76 Position topRight = new Position(0.25f * _itemSize.Width, -0.25f * _itemSize.Height, 0.0f);
77 Position bottomRight = new Position(0.25f * _itemSize.Width, 0.25f * _itemSize.Height, 0.0f);
78 Position bottomLeft = new Position(-0.25f * _itemSize.Width, 0.25f * _itemSize.Height, 0.0f);
80 _circularPath = new Path();
81 _circularPath.AddPoint(topLeft);
82 _circularPath.AddPoint(topRight);
83 _circularPath.AddPoint(bottomRight);
84 _circularPath.AddPoint(bottomLeft);
85 _circularPath.AddPoint(topLeft);
86 _circularPath.GenerateControlPoints(0.5f);
116 public float OffsetYFator
120 return _offsetYFactor;
125 _offsetYFactor = value;
181 public ImageView ShadowBorder
185 return _shadowBorder;
190 _shadowBorder = value;
194 public ImageView SpotLight
207 public int FocusedItemID
211 if (_focusedItem < 0)
220 // This override method is called automatically after the Control has been initialized.
221 // Any second phase initialization is done here.
222 public override void OnInitialize()
224 _itemSize = new Size(0.0f, 0.0f, 0.0f);
228 _currentScrollPosition = 0.0f;
234 _offsetYFactor = 0.0f;
237 _container = new View();
238 this.Add(_container);
240 _itemList = new List<View>();
242 this.ParentOrigin = Tizen.NUI.ParentOrigin.TopLeft;
243 this.AnchorPoint = Tizen.NUI.AnchorPoint.TopLeft;
244 this.WidthResizePolicy = ResizePolicyType.FillToParent;
245 this.HeightResizePolicy = ResizePolicyType.FillToParent;
246 this.Focusable = (true);
248 _container.ParentOrigin = Tizen.NUI.ParentOrigin.TopLeft;
249 _container.AnchorPoint = Tizen.NUI.AnchorPoint.TopLeft;
250 _container.WidthResizePolicy = ResizePolicyType.FillToParent;
251 _container.HeightResizePolicy = ResizePolicyType.FillToParent;
253 _stage = Stage.Instance;
254 _stageSize = _stage.Size;
256 _spotLightAnimation = new Animation(Constants.SpotLightDuration);
257 _focusTransitionAnimation = new Animation(Constants.FocusTransitionDuration);
258 _focusAnimation = new Animation(Constants.FocusDuration);
259 _focusAnimation.EndAction = Animation.EndActions.StopFinal;
260 _scrollAnimation = new Animation(Constants.ScrollDuration);
261 _scrollAnimation.EndAction = Animation.EndActions.StopFinal;
\r
263 //changed to internal
\r
264 //EnableGestureDetection(Gesture.Type.Pan);
267 // This will be invoked automatically if an item/image is added to the ScrollContainer
268 public override void OnChildAdd(Actor actor)
270 View item = View.DownCast(actor);
271 //View item = actor as View;
273 if (item is View && item != _container)
275 item.AnchorPoint = Tizen.NUI.AnchorPoint.BottomCenter;
276 item.ParentOrigin = Tizen.NUI.ParentOrigin.BottomCenter;
278 item.Size = _itemSize;
279 item.Focusable = (true);
280 item.Position = GetItemPosition(_itemCount, _currentScrollPosition);
281 item.Name = _itemCount.ToString();
283 _container.Add(item);
290 // This will be invoked automatically if an item/image is removed from the ScrollContainer
291 public override void OnChildRemove(Actor actor)
293 View item = View.DownCast(actor);
294 //View item = actor as View;
296 if (item is View && item != _container)
298 _container.Remove(item);
301 _itemList.Remove(item);
305 // This override function supports two dimensional keyboard navigation.
306 // This function returns the next keyboard focusable actor in ScrollContainer control towards the given direction.
307 public override View GetNextFocusableView(View currentFocusedView, View.FocusDirection direction, bool loopEnabled)
\r
309 if (direction == View.FocusDirection.Left)
\r
311 return View.DownCast(FocusPrevious(loopEnabled));
\r
313 else if (direction == View.FocusDirection.Right)
\r
315 return View.DownCast(FocusNext(loopEnabled));
\r
319 return View.DownCast(currentFocusedView);
\r
323 public override void OnFocusChangeCommitted(View commitedFocusableView)
\r
329 // This override function is invoked before chosen focusable actor will be focused.
\r
330 // This allows the application to preform any actions (i.e. Scroll and SpotLight animations) before the focus is actually moved to the chosen actor.
\r
332 // This override function is invoked whenever a pan gesture is detected on this control.
\r
333 // Perform Scroll Animation based upon pan gesture velocity / speed.
\r
334 /*public override void OnPan(PanGesture pan)
\r
336 return; //currently not used
\r
339 // This function returns current focused actor
\r
340 public View GetCurrentFocusedActor()
342 if (_focusedItem < 0)
347 return _itemList[_focusedItem];
350 public void SetFocused(bool focused)
352 _isFocused = focused;
354 // Perform Focus animation if the ScrollContainer is not focused already
357 Actor parent = _shadowBorder.Parent;
360 parent.Remove(_shadowBorder);
363 parent = _spotLight.Parent;
366 parent.Remove(_spotLight);
369 _focusTransitionAnimation.Clear();
371 for (int i = 0; i < _itemList.Count; ++i)
373 Position targetPosition = GetItemPosition(i, _currentScrollPosition);
375 _focusTransitionAnimation.AnimateTo(_itemList[i], "Position", targetPosition, new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSine));
377 _focusTransitionAnimation.AnimateTo(_itemList[i], "Scale", new Size(1.0f, 1.0f, 1.0f), new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSine));
380 _focusTransitionAnimation.Play();
388 // Obtain ID of first visible item/image on the screen of the ScrollContainer
389 private int GetFirstVisibleItemId()
391 int firstItemId = -1;
395 firstItemId = (int)Math.Floor((-1.0 * _currentScrollPosition + _marginX * 2.0f) / (_itemSize.Width + _gap));
399 firstItemId = (int)Math.Floor(-1.0 * _currentScrollPosition / (_itemSize.Width + _gap));
410 // Obtain ID of last visible item/image on the screen of the ScrollContainer
411 private int GetLastVisibleItemId()
417 lastItemId = (int)Math.Ceiling(((_width - _currentScrollPosition - _marginX * 2.0f) / _itemSize.Width) - 1);
421 lastItemId = (int)Math.Ceiling(((_width - _currentScrollPosition) / _itemSize.Width) - 1);
424 if (lastItemId >= _itemList.Count)
427 lastItemId = _itemList.Count - 1;
433 // Obtain Next item/image (Right of the currently focused item) of the ScrollContainer
434 private Actor FocusNext(bool loopEnabled)
438 if (_focusedItem < GetFirstVisibleItemId() || _focusedItem > GetLastVisibleItemId())
440 nextItem = GetFirstVisibleItemId();
444 nextItem = _focusedItem + 1;
447 if (nextItem >= _itemList.Count)
455 nextItem = _itemList.Count - 1;
459 _focusedItem = nextItem;
460 return _itemList[_focusedItem];
463 // Obtain Previous item/image (left of the currently focused item) of the ScrollContainer
464 private Actor FocusPrevious(bool loopEnabled)
466 int previousItem = -1;
468 if (_focusedItem < GetFirstVisibleItemId() || _focusedItem > GetLastVisibleItemId())
470 previousItem = GetFirstVisibleItemId();
474 previousItem = _focusedItem - 1;
477 if (previousItem < 0)
481 previousItem = _itemList.Count - 1;
489 _focusedItem = previousItem;
490 return _itemList[_focusedItem];
493 // Perform ScrollAnimation on each item
494 private void Scroll(float amount, int baseItem)
496 float tagetScrollPosition = _currentScrollPosition + amount;
497 float totalItemSize = _itemList.Count * (_itemSize.Width + _gap) + _gap + (_marginX * 2.0f);
499 float maxScrollPosition = _width - totalItemSize;
501 if (tagetScrollPosition < maxScrollPosition)
503 tagetScrollPosition = maxScrollPosition;
506 if (tagetScrollPosition > 0.0f)
508 tagetScrollPosition = 0.0f;
511 _scrollAnimation.Clear();
513 for (int i = 0; i < _itemList.Count; ++i)
515 Position targetPosition = GetItemPosition(i, tagetScrollPosition);
517 _scrollAnimation.AnimateTo(_itemList[i], "Position", targetPosition, new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSine));
520 _currentScrollPosition = tagetScrollPosition;
521 _scrollAnimation.Play();
524 // This function uses ItemId as next FocusedItem and preforms Scroll and SpotLight animations on that item.
525 private void Focus(int itemId)
532 else if (itemId >= _itemList.Count)
534 itemId = _itemList.Count - 1;
537 _itemList[itemId].Add(_shadowBorder);
538 _itemList[itemId].Add(_spotLight);
540 // Perform Spot Light animation
541 if (_focusedItem != itemId && _spotLight != null)
543 _spotLightAnimation.Clear();
544 _spotLightAnimation.AnimatePath(_spotLight, _circularPath, new Vector3(0.0f, 0.0f, 0.0f));
545 _spotLightAnimation.Looping = true;
546 _spotLightAnimation.Play();
549 _focusedItem = itemId;
551 Position itemPosition = GetItemPosition(_focusedItem, _currentScrollPosition);
553 _focusAnimation.Clear();
555 float relativeItemPositionX = itemPosition.X - _itemSize.Width * 0.5f + (_stageSize.Width * 0.5f) + _offsetX;
556 if (relativeItemPositionX < _marginX + _offsetX + _gap)
558 float amount = _marginX + _offsetX + _gap - relativeItemPositionX;
559 Scroll(amount, itemId + 1); // Perform Scroll animation
561 else if (relativeItemPositionX + _itemSize.Width + _gap + _marginX > _stageSize.Width)
563 float amount = relativeItemPositionX + _marginX + _gap + _itemSize.Width - _stageSize.Width;
564 Scroll(-amount, itemId - 1); // Perform Scroll animation
568 // Perform animation when item is focused
569 for (int i = 0; i < _itemList.Count; ++i)
571 Position targetPosition = GetItemPosition(i, _currentScrollPosition);
573 _focusAnimation.AnimateTo(_itemList[i], "Position",targetPosition, new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSine) );
577 for (int i = 0; i < _itemList.Count; ++i)
579 // Perform scale animation on Focused item
580 if (i == _focusedItem)
582 _focusAnimation.AnimateTo(_itemList[i], "Scale", new Size(1.2f, 1.2f, 1.2f), new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSine));
587 _focusAnimation.AnimateTo(_itemList[i], "Scale", new Size(1.0f, 1.0f, 1.0f), new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSine) );
591 _focusAnimation.Play();
595 // Calculate Position of any item/image of ScrollContainer
596 private Position GetItemPosition(int itemId, float scrollPosition)
600 // used (_itemSize.Width * 0.5f) because of AnchorPointCenter
601 // used (_stageSize.Width * 0.5f) because of ParentOriginCenter
602 if (_focusedItem > itemId)
604 float positionX = (_itemSize.Width * itemId) + (_gap * (itemId + 1)) + scrollPosition + (_itemSize.Width * 0.5f) - (_stageSize.Width * 0.5f);
605 return new Position(positionX, -_itemSize.Height * _offsetYFactor, 0.0f);
607 else if (_focusedItem == itemId)
609 float positionX = (_itemSize.Width * itemId) + (_gap * (itemId + 1)) + scrollPosition + _marginX + (_itemSize.Width * 0.5f) - (_stageSize.Width * 0.5f);
610 return new Position(positionX, -_itemSize.Height * _offsetYFactor, 0.0f);
614 float positionX = (_itemSize.Width * itemId) + (_gap * (itemId + 1)) + scrollPosition + _marginX * 2.0f + (_itemSize.Width * 0.5f) - (_stageSize.Width * 0.5f);
615 return new Position(positionX, -_itemSize.Height * _offsetYFactor, 0.0f);
620 float positionX = (_itemSize.Width * itemId) + (_gap * (itemId + 1)) + scrollPosition + (_itemSize.Width * 0.5f) - (_stageSize.Width * 0.5f);
621 return new Position(positionX, -_itemSize.Height * _offsetYFactor, 0.0f);