/// <summary> /// Scroll to a selected index (with animation or not) /// </summary> internal void ScrollToSelectedIndex(PickerSelectorItem selectedItem, TimeSpan duration) { if (!templateApplied) { return; } var centerTopOffset = (this.ActualHeight / 2d) - (itemHeight) / 2d; var deltaOffset = centerTopOffset - selectedItem.GetVerticalPosition(); if (Double.IsInfinity(deltaOffset) || Double.IsNaN(deltaOffset)) { return; } if (duration == TimeSpan.Zero) { this.sliderVertical.Value += deltaOffset; } else { this.UpdatePositionsWithAnimationAsync(selectedItem, deltaOffset, duration); } }
/// <summary> /// When manipulation is completed, go to the closest item /// </summary> private void OnManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e) { PickerSelectorItem middleItem = GetMiddleItem(); // get rect if (middleItem == null) { return; } // animate and scroll to this.ScrollToSelectedIndex(middleItem, animationDuration); }
/// <summary> /// Translate items to a new offset /// </summary> private void UpdatePosition(Int32 startIndex, Int32 endIndex, Double offset) { for (Int32 i = startIndex; i < endIndex; i++) { PickerSelectorItem loopListItem = this.Children[i] as PickerSelectorItem; if (loopListItem == null) { continue; } TranslateTransform translateTransform = loopListItem.GetTranslateTransform(); translateTransform.Y = offset; } }
/// <summary> /// Updating with an animation (after a tap) /// </summary> private void UpdatePositionsWithAnimationAsync(PickerSelectorItem selectedItem, Double delta, TimeSpan duration) { animationSnap.From = selectedItem.GetTranslateTransform().Y; animationSnap.To = selectedItem.GetTranslateTransform().Y + delta; animationSnap.Duration = duration; animationSnap.EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseInOut }; sliderVertical.ValueChanged -= OnVerticalOffsetChanged; sliderVertical.Value = selectedItem.GetTranslateTransform().Y; sliderVertical.ValueChanged += OnVerticalOffsetChanged; this.storyboard.Completed += (sender, o) => { if (SelectedItemChanged != null) { SelectedItemChanged(this, selectedItem); } }; this.storyboard.RunAsync(); }
/// <summary> /// Updating with an animation (after a tap) /// </summary> private void UpdatePositionsWithAnimationAsync(PickerSelectorItem selectedItem, Double delta, TimeSpan duration) { if (Orientation == Orientation.Vertical) { animationSnap.From = selectedItem.GetTranslateTransform().Y; animationSnap.To = selectedItem.GetTranslateTransform().Y + delta; } else { animationSnap.From = selectedItem.GetTranslateTransform().X; animationSnap.To = selectedItem.GetTranslateTransform().X + delta; } animationSnap.Duration = duration; animationSnap.EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseInOut }; internalSlider.ValueChanged -= OnOffsetChanged; internalSlider.Value = Orientation == Orientation.Vertical ? selectedItem.GetTranslateTransform().Y : selectedItem.GetTranslateTransform().X; internalSlider.ValueChanged += OnOffsetChanged; this.storyboard.Completed += (sender, o) => { if (SelectedItemChanged != null) { SelectedItemChanged(this, selectedItem); } }; this.storyboard.RunAsync(); }
/// <summary> /// Scroll to a selected index (with animation or not) /// </summary> internal void ScrollToSelectedIndex(PickerSelectorItem selectedItem, TimeSpan duration) { if (!templateApplied) return; var centerTopOffset = Orientation == Orientation.Vertical ? (this.ActualHeight / 2d) - (itemHeight) / 2d : (this.ActualWidth / 2d) - (itemWidth) / 2d; var deltaOffset = centerTopOffset - (Orientation == Orientation.Vertical ? selectedItem.GetVerticalPosition() : selectedItem.GetHorizontalPosition()); if (Double.IsInfinity(deltaOffset) || Double.IsNaN(deltaOffset)) return; if (duration == TimeSpan.Zero) this.internalSlider.Value += deltaOffset; else this.UpdatePositionsWithAnimationAsync(selectedItem, deltaOffset, duration); }
/// <summary> /// Arrange all items /// </summary> protected override Size ArrangeOverride(Size finalSize) { // Clip to ensure items dont override container this.Clip = new RectangleGeometry { Rect = new Rect(0, 0, finalSize.Width, finalSize.Height) }; if (this.Children == null || this.Children.Count == 0) { var size = base.ArrangeOverride(finalSize); var width = double.IsInfinity(size.Width) ? 400 : size.Width; var height = double.IsInfinity(size.Height) ? 800 : size.Height; return(new Size(width, height)); } Double positionTop = 0d; Double positionLeft = 0d; PickerSelectorItem selectedItem = null; // Must Create looping items count foreach (PickerSelectorItem item in this.Children) { if (item == null) { continue; } Size desiredSize = item.DesiredSize; if (double.IsNaN(desiredSize.Width) || double.IsNaN(desiredSize.Height)) { continue; } item.RectPosition = new Rect(positionLeft, positionTop, desiredSize.Width, desiredSize.Height); item.Arrange(item.RectPosition); if (item.IsSelected) { selectedItem = item; } positionTop += desiredSize.Height; } templateApplied = true; if (selectedItem != null) { this.UpdatePositions(sliderVertical.Value); this.ScrollToSelectedIndex(selectedItem, TimeSpan.Zero); //if (!isFirstLayoutPassed) //{ // this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, // () => this.ScrollToSelectedIndex(selectedItem, TimeSpan.Zero)); //} //else //{ //} } return(finalSize); }