2 using Tizen.NUI.Constants;
3 using Tizen.NUI.UIComponents;
4 using Tizen.NUI.BaseComponents;
6 using System.Runtime.InteropServices;
7 using System.Collections.Generic;
11 public class ScrollContainer : CustomView
13 private View _container; // View Container will be the first item added to ScrollContainer and parent to all the items added to the ScrollContainer.
14 private Size _itemSize; // Size of the item / images added to the ScrollContainer.
15 private List<View> _itemList; // List collection of View items/images added to the ScrollContainer.
16 private int _itemCount; // Number of items / images added to the ScrollContainer.
17 private int _focusedItem; // Index of currently focused View item / image on the ScrollContainer.
18 private float _scrollDisplacement; // Used for horizontal pan displacement.
19 private float _currentScrollPosition; // Used for horizontal scroll position.
20 private float _gap; // Used for gap / padding between items / images on the ScrollContainer.
21 private float _width; // Width of the ScrollContainer.
22 private float _height; // Height of the ScrollContainer.
23 private bool _isFocused; // Flag to check if ScrollContainer is enabled or not.
24 private float _marginX; // Extra horizontal margin is used to add an extra gap between items / images after a focused and scaled item / image.
25 private float _marginY; // Extra vertical margin (not used at the moment).
26 private float _offsetYFactor; // Vertical Position offset Factor of item height.
27 private float _offsetX; // Horizontal Position offset of ScrollContainer.
28 private Stage _stage; // Reference to Dali stage.
29 private Size2D _stageSize; // Reference to Dali stage size.
30 private ImageView _shadowBorder; // Reference to Shadow border ImageView applied to the focused item on ScrollContainer.
31 private ImageView _spotLight; // Reference to SpotLight ImageView applied to the focused item on ScrollContainer.
32 private Animation _spotLightAnimation; // SpotLight Animation applied to the focused item on ScrollContainer.
33 private Animation _focusAnimation; // Focused position animation on ScrollContainer.
34 private Animation _scrollAnimation; // Scroll animation on items of ScrollContainer.
35 private Animation _focusTransitionAnimation; // Focus Transition (scaling /unscaling) animation on items of ScrollContainer.
36 private Path _circularPath; // Circular path used for SpotLight Animation applied to the focused item on ScrollContainer.
38 static CustomView CreateInstance()
40 return new ScrollContainer();
43 // static constructor registers the control type (for user can add kinds of visuals to it)
44 static ScrollContainer()
46 // ViewRegistry registers control type with DALi type registery
47 // also uses introspection to find any properties that need to be registered with type registry
48 ViewRegistry.Instance.Register(CreateInstance, typeof(ScrollContainer));
51 public ScrollContainer() : base(typeof(ScrollContainer).Name, CustomViewBehaviour.DisableStyleChangeSignals |
52 CustomViewBehaviour.RequiresKeyboardNavigationSupport)
64 public Tizen.NUI.BaseComponents.View Container
91 Position topLeft = new Position(-0.25f * _itemSize.Width, -0.25f * _itemSize.Height, 0.0f);
92 Position topRight = new Position(0.25f * _itemSize.Width, -0.25f * _itemSize.Height, 0.0f);
93 Position bottomRight = new Position(0.25f * _itemSize.Width, 0.25f * _itemSize.Height, 0.0f);
94 Position bottomLeft = new Position(-0.25f * _itemSize.Width, 0.25f * _itemSize.Height, 0.0f);
96 _circularPath = new Path();
97 _circularPath.AddPoint(topLeft);
98 _circularPath.AddPoint(topRight);
99 _circularPath.AddPoint(bottomRight);
100 _circularPath.AddPoint(bottomLeft);
101 _circularPath.AddPoint(topLeft);
102 _circularPath.GenerateControlPoints(0.5f);
132 public float OffsetYFator
136 return _offsetYFactor;
141 _offsetYFactor = value;
197 public ImageView ShadowBorder
201 return _shadowBorder;
206 _shadowBorder = value;
210 public ImageView SpotLight
223 public int FocusedItemID
227 if (_focusedItem < 0)
236 // This override method is called automatically after the Control has been initialized.
237 // Any second phase initialization is done here.
238 public override void OnInitialize()
240 _itemSize = new Size(0.0f, 0.0f, 0.0f);
244 _currentScrollPosition = 0.0f;
250 _offsetYFactor = 0.0f;
253 _container = new View();
254 this.Add(_container);
256 _itemList = new List<View>();
258 this.ParentOrigin = Tizen.NUI.ParentOrigin.TopLeft;
259 this.WidthResizePolicy = ResizePolicyType.FillToParent;
260 this.HeightResizePolicy = ResizePolicyType.FillToParent;
261 this.Focusable = (true);
263 _container.ParentOrigin = Tizen.NUI.ParentOrigin.TopLeft;
264 _container.WidthResizePolicy = ResizePolicyType.FillToParent;
265 _container.HeightResizePolicy = ResizePolicyType.FillToParent;
267 _stage = Stage.Instance;
268 _stageSize = _stage.Size;
270 _spotLightAnimation = new Animation(Constants.SpotLightDuration);
271 _focusTransitionAnimation = new Animation(Constants.FocusTransitionDuration);
272 _focusAnimation = new Animation(Constants.FocusDuration);
273 _focusAnimation.EndAction = Animation.EndActions.StopFinal;
274 _scrollAnimation = new Animation(Constants.ScrollDuration);
275 _scrollAnimation.EndAction = Animation.EndActions.StopFinal;
277 //changed to internal
278 //EnableGestureDetection(Gesture.Type.Pan);
281 // This will be invoked automatically if an item/image is added to the ScrollContainer
282 public override void OnChildAdd(Actor actor)
284 View item = View.DownCast(actor);
285 //View item = actor as View;
287 if (item is View && item != _container)
289 item.PivotPoint = Tizen.NUI.PivotPoint.BottomCenter;
290 item.PositionUsesPivotPoint = true;
291 item.ParentOrigin = Tizen.NUI.ParentOrigin.BottomCenter;
293 item.Size = _itemSize;
294 item.Focusable = (true);
295 item.Position = GetItemPosition(_itemCount, _currentScrollPosition);
296 item.Name = _itemCount.ToString();
298 _container.Add(item);
305 // This will be invoked automatically if an item/image is removed from the ScrollContainer
306 public override void OnChildRemove(Actor actor)
308 View item = View.DownCast(actor);
309 //View item = actor as View;
311 if (item is View && item != _container)
313 _container.Remove(item);
316 _itemList.Remove(item);
320 // This override function supports two dimensional keyboard navigation.
321 // This function returns the next keyboard focusable actor in ScrollContainer control towards the given direction.
322 public override View GetNextFocusableView(View currentFocusedView, View.FocusDirection direction, bool loopEnabled)
324 if (direction == View.FocusDirection.Left)
326 return View.DownCast(FocusPrevious(loopEnabled));
328 else if (direction == View.FocusDirection.Right)
330 return View.DownCast(FocusNext(loopEnabled));
334 return View.DownCast(currentFocusedView);
338 public override void OnFocusChangeCommitted(View commitedFocusableView)
344 // This override function is invoked before chosen focusable actor will be focused.
345 // This allows the application to preform any actions (i.e. Scroll and SpotLight animations) before the focus is actually moved to the chosen actor.
347 // This override function is invoked whenever a pan gesture is detected on this control.
348 // Perform Scroll Animation based upon pan gesture velocity / speed.
349 /*public override void OnPan(PanGesture pan)
351 return; //currently not used
354 // This function returns current focused actor
355 public View GetCurrentFocusedActor()
357 if (_focusedItem < 0)
362 return _itemList[_focusedItem];
365 public void SetFocused(bool focused)
367 _isFocused = focused;
369 // Perform Focus animation if the ScrollContainer is not focused already
372 Actor parent = _shadowBorder.Parent;
375 parent.Remove(_shadowBorder);
378 parent = _spotLight.Parent;
381 parent.Remove(_spotLight);
384 _focusTransitionAnimation.Clear();
386 for (int i = 0; i < _itemList.Count; ++i)
388 Position targetPosition = GetItemPosition(i, _currentScrollPosition);
390 _focusTransitionAnimation.AnimateTo(_itemList[i], "Position", targetPosition, new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSine));
392 _focusTransitionAnimation.AnimateTo(_itemList[i], "Scale", new Size(1.0f, 1.0f, 1.0f), new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSine));
395 _focusTransitionAnimation.Play();
403 // Obtain ID of first visible item/image on the screen of the ScrollContainer
404 private int GetFirstVisibleItemId()
406 int firstItemId = -1;
410 firstItemId = (int)Math.Floor((-1.0 * _currentScrollPosition + _marginX * 2.0f) / (_itemSize.Width + _gap));
414 firstItemId = (int)Math.Floor(-1.0 * _currentScrollPosition / (_itemSize.Width + _gap));
425 // Obtain ID of last visible item/image on the screen of the ScrollContainer
426 private int GetLastVisibleItemId()
432 lastItemId = (int)Math.Ceiling(((_width - _currentScrollPosition - _marginX * 2.0f) / _itemSize.Width) - 1);
436 lastItemId = (int)Math.Ceiling(((_width - _currentScrollPosition) / _itemSize.Width) - 1);
439 if (lastItemId >= _itemList.Count)
442 lastItemId = _itemList.Count - 1;
448 // Obtain Next item/image (Right of the currently focused item) of the ScrollContainer
449 private Actor FocusNext(bool loopEnabled)
453 if (_focusedItem < GetFirstVisibleItemId() || _focusedItem > GetLastVisibleItemId())
455 nextItem = GetFirstVisibleItemId();
459 nextItem = _focusedItem + 1;
462 if (nextItem >= _itemList.Count)
470 nextItem = _itemList.Count - 1;
474 _focusedItem = nextItem;
475 return _itemList[_focusedItem];
478 // Obtain Previous item/image (left of the currently focused item) of the ScrollContainer
479 private Actor FocusPrevious(bool loopEnabled)
481 int previousItem = -1;
483 if (_focusedItem < GetFirstVisibleItemId() || _focusedItem > GetLastVisibleItemId())
485 previousItem = GetFirstVisibleItemId();
489 previousItem = _focusedItem - 1;
492 if (previousItem < 0)
496 previousItem = _itemList.Count - 1;
504 _focusedItem = previousItem;
505 return _itemList[_focusedItem];
508 // Perform ScrollAnimation on each item
509 private void Scroll(float amount, int baseItem)
511 float tagetScrollPosition = _currentScrollPosition + amount;
512 float totalItemSize = _itemList.Count * (_itemSize.Width + _gap) + _gap + (_marginX * 2.0f);
514 float maxScrollPosition = _width - totalItemSize;
516 if (tagetScrollPosition < maxScrollPosition)
518 tagetScrollPosition = maxScrollPosition;
521 if (tagetScrollPosition > 0.0f)
523 tagetScrollPosition = 0.0f;
526 _scrollAnimation.Clear();
528 for (int i = 0; i < _itemList.Count; ++i)
530 Position targetPosition = GetItemPosition(i, tagetScrollPosition);
532 _scrollAnimation.AnimateTo(_itemList[i], "Position", targetPosition, new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSine));
535 _currentScrollPosition = tagetScrollPosition;
536 _scrollAnimation.Play();
539 // This function uses ItemId as next FocusedItem and preforms Scroll and SpotLight animations on that item.
540 private void Focus(int itemId)
547 else if (itemId >= _itemList.Count)
549 itemId = _itemList.Count - 1;
552 _itemList[itemId].Add(_shadowBorder);
553 _itemList[itemId].Add(_spotLight);
555 // Perform Spot Light animation
556 if (_focusedItem != itemId && _spotLight != null)
558 _spotLightAnimation.Clear();
559 _spotLightAnimation.AnimatePath(_spotLight, _circularPath, new Vector3(0.0f, 0.0f, 0.0f));
560 _spotLightAnimation.Looping = true;
561 _spotLightAnimation.Play();
564 _focusedItem = itemId;
566 Position itemPosition = GetItemPosition(_focusedItem, _currentScrollPosition);
568 _focusAnimation.Clear();
570 float relativeItemPositionX = itemPosition.X - _itemSize.Width * 0.5f + (_stageSize.Width * 0.5f) + _offsetX;
571 if (relativeItemPositionX < _marginX + _offsetX + _gap)
573 float amount = _marginX + _offsetX + _gap - relativeItemPositionX;
574 Scroll(amount, itemId + 1); // Perform Scroll animation
576 else if (relativeItemPositionX + _itemSize.Width + _gap + _marginX > _stageSize.Width)
578 float amount = relativeItemPositionX + _marginX + _gap + _itemSize.Width - _stageSize.Width;
579 Scroll(-amount, itemId - 1); // Perform Scroll animation
583 // Perform animation when item is focused
584 for (int i = 0; i < _itemList.Count; ++i)
586 Position targetPosition = GetItemPosition(i, _currentScrollPosition);
588 _focusAnimation.AnimateTo(_itemList[i], "Position",targetPosition, new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSine) );
592 for (int i = 0; i < _itemList.Count; ++i)
594 // Perform scale animation on Focused item
595 if (i == _focusedItem)
597 _focusAnimation.AnimateTo(_itemList[i], "Scale", new Size(1.2f, 1.2f, 1.2f), new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSine));
602 _focusAnimation.AnimateTo(_itemList[i], "Scale", new Size(1.0f, 1.0f, 1.0f), new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSine) );
606 _focusAnimation.Play();
610 // Calculate Position of any item/image of ScrollContainer
611 private Position GetItemPosition(int itemId, float scrollPosition)
615 // used (_itemSize.Width * 0.5f) because of AnchorPointCenter
616 // used (_stageSize.Width * 0.5f) because of ParentOriginCenter
617 if (_focusedItem > itemId)
619 float positionX = (_itemSize.Width * itemId) + (_gap * (itemId + 1)) + scrollPosition + (_itemSize.Width * 0.5f) - (_stageSize.Width * 0.5f);
620 return new Position(positionX, -_itemSize.Height * _offsetYFactor, 0.0f);
622 else if (_focusedItem == itemId)
624 float positionX = (_itemSize.Width * itemId) + (_gap * (itemId + 1)) + scrollPosition + _marginX + (_itemSize.Width * 0.5f) - (_stageSize.Width * 0.5f);
625 return new Position(positionX, -_itemSize.Height * _offsetYFactor, 0.0f);
629 float positionX = (_itemSize.Width * itemId) + (_gap * (itemId + 1)) + scrollPosition + _marginX * 2.0f + (_itemSize.Width * 0.5f) - (_stageSize.Width * 0.5f);
630 return new Position(positionX, -_itemSize.Height * _offsetYFactor, 0.0f);
635 float positionX = (_itemSize.Width * itemId) + (_gap * (itemId + 1)) + scrollPosition + (_itemSize.Width * 0.5f) - (_stageSize.Width * 0.5f);
636 return new Position(positionX, -_itemSize.Height * _offsetYFactor, 0.0f);