ãã ããããã§ã¯æšæºã³ã³ããŒãã³ãã«ã€ããŠã¯èª¬æããŸãããMicrosoftã«ã¯æµãªãã¶ã€ã³ïŒ Acrylic ã Reveal ã Connectedã¢ãã¡ãŒã·ã§ã³ãªã©ïŒãæäŸããŠããŸããããã¡ãããããã䜿çšããŠããŸãã ãã¹ãŠãã·ã³ãã«ã§æå¿«ã§ã-ããã¥ã¡ã³ããåãåã£ãŠäœ¿çšããŠãã ããã
ããããåéºã¯éåžžã人éé¢ãããšããããå§ãŸããŸãã ãããã£ãŠã1ã€ã®ã«ã¹ã¿ã ã³ã³ãããŒã«ãã©ã®ããã«å®è¡ãããã«ã€ããŠã話ãããæ¹ãããã§ãããã 以äžããã®1ã€ã§ãã
æµTheãªèšèšã·ã¹ãã ã®æ·±ããšåãã䜿çšãããšããèãæ¹ã§ãã äžå¿çãªèŠçŽ ã¯ãããã°ãä»ã®ãã¹ãŠã®èŠçŽ ããããããã«é«ããªã£ãŠããŸãã ããã¯ãã¹ã¯ããŒã«äžã«ãµã€ãºãšåœ±ãã¢ãã¡ãŒã·ã§ã³åããããšã§å®çŸãããŸãã
FlipViewã³ã³ãããŒã«ã¯ããã«ã¯æ¥ãŸããã§ããããªããªãã 圌ã¯ã次ã®èŠçŽ ãšåã®èŠçŽ ã®æçã衚瀺ããæ¹æ³ãç¥ããŸããïŒãè³ããšåŒã³ãŸãïŒã ãããŠã解決çãæ¢ãå§ããŸããã
æ¹æ³1. GridViewã䜿çšããã
è«ççãªè§£æ±ºçã¯ã GridViewã䜿çšããŠã¿ãããšã§ããã æ°Žå¹³ç·ã«ã¢ã€ãã ã䞊ã¹ãã«ã¯ãItemsPanelã»ãããšããŠèšå®ããŸãã
<ItemsStackPanel Orientation="Horizontal" />
çŸåšã®èŠçŽ ãäžå€®ã«é 眮ããã«ã¯ãGridViewãã³ãã¬ãŒãã®ScrollViewerããããã£ã䜿çšããŸãã
<ScrollViewer HorizontalSnapPointsType="MandatorySingle" HorizontalSnapPointsAlignment="Center" />
ãã®ãããªå®è£ ã®äŸã¯ãããšãã°ããã§èŠãããšãã§ããŸã ã
ãã¹ãŠã¯å€§äžå€«ã®ããã§ãããåé¡ããããŸãã
ã°ãªãããã¥ãŒ åé¡1.ç»é¢ã®å¹ å šäœã«ãããå¶åŸ¡ã®ã¹ã±ãŒãªã³ã°
ãã¶ã€ããŒãèšèšãããšãããã³ã³ãããŒã«ã¯ãŠã£ã³ããŠã®å¹ å šäœã«åºããå¿ èŠããããŸãã ããèªäœã¯åé¡ã§ã¯ãããŸããã ãã ããã³ã³ãããŒã«ã®ãµã€ãºãå€æŽããå Žåããã®ãã¹ãŠã®åïŒã¢ã€ãã ïŒã®ãµã€ãºãåæçã«å€æŽããå¿ èŠããããŸãã
- èŠçŽ ã®å¹
ã¯ãã³ã³ãããŒã«ã®å¹
ã®90ïŒ
ã«èšå®ããå¿
èŠããããŸãïŒãè³ãã®æ®ã10ïŒ
ïŒã
- èŠçŽ ã®é«ãã¯ãç»åã®å¹
ãšæ¯çã«åºã¥ããŠèšç®ããå¿
èŠããããŸãã
- åæã«ãå°ããªç»é¢å¹
ã§ã¯ãã¹ã±ãŒãªã³ã°åŸã«ç»åãå°ãããªããããªãããã«ãç»åãå·Šå³ã«ããªãã³ã°ããå¿
èŠããããŸãã
ããã«äœ¿çšã§ããGridViewã¯ãããŸããã UWPToolkitã®AdaptiveGridViewã³ã³ãããŒã«ã®å®è£ ã§è§£æ±ºçãèŠã€ããŸãã ã
- GridViewãç¶æ¿ããItemWidthãšItemHeightã®2ã€ã®ããããã£ãè¿œå ããŸãã
- SizeChangedã€ãã³ããã³ãã©ãŒã§ã¯ãGridViewã®å¹
ã«å¿ããŠãããã®ããããã£ãèšç®ããŸãã
- GridViewã®PrepareContainerForItemOverrideã¡ãœããããªãŒããŒã©ã€ãããŸãã ãŠãŒã¶ãŒã«è¡šç€ºãããåã«ãåItemContainerã«å¯ŸããŠåŒã³åºãããŸãã ãããŠãäœæããItemWidthãšItemHeightãžã®ãã€ã³ãã£ã³ã°ãåã¢ã€ãã ã«è¿œå ããŸãã
protected override void PrepareContainerForItemOverride(DependencyObject obj, object item) { base.PrepareContainerForItemOverride(obj, item); if (obj is FrameworkElement element) { var heightBinding = new Binding() { Source = this, Path = new PropertyPath("ItemHeight"), Mode = BindingMode.TwoWay }; var widthBinding = new Binding() { Source = this, Path = new PropertyPath("ItemWidth"), Mode = BindingMode.TwoWay }; element.SetBinding(HeightProperty, heightBinding); element.SetBinding(WidthProperty, widthBinding); } }
詳现ã«ã€ããŠã¯ã UWPToolkitã®ãœãŒã¹ã³ãŒããåç §ããŠãã ããã
ãã¹ãŠãåé¡ãªãããã«èŠããŸã ããã...
ã°ãªãããã¥ãŒ åé¡2.ã¢ã€ãã ã®ãµã€ãºãå€æŽãããšãçŸåšã®ã¢ã€ãã ãç¯å²å€ã«ãªã
ãã ããGridViewå ã®èŠçŽ ã®å¹ ãåçã«å€æŽãå§ãããšããã«ã次ã®åé¡ã«çŽé¢ããŸãã ãã®æç¹ã§ããŸã£ããç°ãªãèŠçŽ ãå¯èŠé åã«èœã¡å§ããŸãã ããã¯ãGridViewå ã®ScrollViewerã®HorizoâântalOffsetãå€æŽãããªããšããäºå®ã«ãããã®ã§ãã GridViewã¯ããã®ãããªãã£ãããç§ãã¡ã«ææ¡ããŠããŸããã
ãã®å¹æã¯ããŠã£ã³ããŠãæ倧åãããšãã«ç¹ã«é¡èã§ãïŒãµã€ãºãæ¥æ¿ã«å€åããããïŒã ãŸããåã«HorizoâântalOffsetã®å€ã倧ããå Žåã§ãã
ãã®åé¡ã¯ãGridViewã«ç®çã®èŠçŽ ãŸã§ã¹ã¯ããŒã«ããããã«äŸé Œããããšã§è§£æ±ºã§ããããã§ãã
private async void OnSizeChanged(object sender, SizeChangedEventArgs e) { ... await Task.Yield(); this.ScrollIntoView(getCurrentItem(), ScrollIntoViewAlignment.Default); }
ãããããããïŒ
- Task.YieldïŒïŒã䜿çšããªããšãããã¯æ©èœããŸããã ãããŠããã§-visualãèŠèŠççæ£ã«ã€ãªãã-ãªããªã ScrollIntoViewãå®è¡ãããåã«ãå¥ã®èŠçŽ ã衚瀺ãããŸãã
- ãŸããSnapPointsãæå¹ã«ãªã£ãŠããå Žåãäœããã®çç±ã§ScrollIntoViewã¯ååãšããŠæ£ããæ©èœããŸããã ãããã«åŒã£ããã£ãŠãããã®ããã«ã
ããã¯ãGridViewã®ãµã€ãºãå€æŽãããã³ã«ScrollViewerã®æ°ããHorizoâântalOffsetå€ãæåã§èšç®ããŠèšå®ããããšã§ã解決ã§ããŸãã
private void OnSizeChanged(object sender, SizeChangedEventArgs e) { ... var scrollViewer = this.FindDescendant<ScrollViewer>(); scrollViewer.ChangeView(calculateNewHorizontalOffset(...), 0, 1, true); }
ãã ããããã¯ãŠã£ã³ããŠã®æ®µéçãªãµã€ãºå€æŽã§ã®ã¿æ©èœããŸãã ãŠã£ã³ããŠãæ倧åãããšããããã¯ãã°ãã°ééã£ãçµæããããããŸãã ããããããã®çç±ã¯ãèšç®ããæ°ããHorizoâântalOffsetã®å€ã倧ããããŠExtentWidthïŒScrollViewerå ã®ã³ã³ãã³ãã®å¹ ïŒãè¶ ããŠããããã§ãã ãããŠä»¥æ¥ GridViewã¯UI-virtualizationã䜿çšããExtentWidth Item-sã®å¹ ãå€æŽããåŸã«èªåçã«åã«ãŠã³ããããªãå ŽåããããŸãã
äžè¬ã«ããã®åé¡ã«å¯Ÿããé©åãªè§£æ±ºçã¯èŠã€ãããŸããã§ããã
ããã§åæ¢ããŠã次ã®è§£æ±ºçã®æ€çŽ¢ãéå§ã§ããŸãã ãããããã®ã¢ãããŒãã®å¥ã®åé¡ã«ã€ããŠèª¬æããŸãã
ã°ãªãããã¥ãŒ åé¡3.ãã¹ããããScrollViewersã¯ãããŠã¹ã§ã®æ°Žå¹³ã¹ã¯ããŒã«ãäžæããŸã
ããŠã¹ãã€ãŒã«ãåžžã«åçŽã«ã¹ã¯ããŒã«ããããã«ããŸãã åžžã«ã åçŽã«ã
ãã ããGridViewããŒãžãæ°Žå¹³ã¹ã¯ããŒã«ã§é 眮ãããšããã®æ·±ãã«ããScrollViewerã¯ããŠã¹ãã€ãŒã«ã€ãã³ãããã£ããã£ãããã以äžã¹ãããããŸããã ãã®çµæãããŠã¹ã«ãŒãœã«ãã³ã³ãããŒã«ãªã¹ãã®äžã«ããå ŽåãããŠã¹ãã€ãŒã«ã¯ãã®äžãæ°Žå¹³ã¹ã¯ããŒã«ããŸãã ããã¯äžäŸ¿ã§ããããŠãŒã¶ãŒãæ··ä¹±ãããŸãã
ãã®åé¡ã«ã¯2ã€ã®è§£æ±ºçããããŸãã
- PointerWheelChangedã€ãã³ãããã£ããããŠããæ°Žå¹³ScrollViewerã«ãããããããã«å¿çããŠãåçŽScrollViewerã§ChangeViewïŒïŒãåŒã³åºããŸãã ããã§ã¹ãã€ã ããã¯æ©èœããŸãããããŠã¹ãã€ãŒã«ããã°ããå転ãããšèããé
ããªããŸãã ããã¯ç§ãã¡ã«ã¯åããªãã£ã-ã¿ããã¹ã¯ãªãŒã³ã䜿çšãããŸããªãŠãŒã¶ãŒã®ããã«ããŠã¹ã§ã¹ã¯ããŒã«ãå°ç¡ãã«ããããšã¯éžæè¢ã§ã¯ãããŸããã
-
HorizontalScrollMode="Disabled"
èšå®ããŸãã ããã¯åœ¹ç«ã¡ãŸãããããŠã¹ãã€ãŒã«ã ãã§ãªããã¿ããã¹ã¯ãªãŒã³ã®ã¹ã¯ããŒã«ãç¡å¹ã«ãªããŸãã
<GridView ScrollViewer.HorizontalScrollMode="Disabled" />
ã¿ããã¹ã¯ãªãŒã³ã倱ãããã¯ãããŸããã§ãããããè¯ã解決çãæ¢ãç¶ããŸããã
ãã¹2. UWPToolkitããã®ã«ã«ãŒã»ã«
次ã®ãœãªã¥ãŒã·ã§ã³ã¯ã UWPToolkitããã®ã«ã«ãŒã»ã«ã®å¶åŸ¡ã§ãã ã ãã¹ãŠã®åŽé¢ããéåžžã«èå³æ·±ããæçãªã³ã³ãããŒã«ã 誰ã§ããã®å®è£ ãå匷ããããšããå§ãããŸãã
圌ã¯ç§ãã¡ã®ããŒãºãããªãããã«ããŒããŠãããŸããã ããããæçµçã«ã¯é©åããŸããã§ããïŒ
- å¹
ãå€æŽãããšãã«èŠçŽ ã®ã¹ã±ãŒãªã³ã°ã¯ãããŸããïŒäžèšãåç
§ïŒã
- ããã¯è§£æ±ºå¯èœãªåé¡ã§ãã ãªããªã 圌ã¯ãªãŒãã³ãœãŒã¹ã§ãã ãŸããã¹ã±ãŒãªã³ã°ãè¿œå ããããšã¯é£ãããããŸããã
- ãŸãããªãŒãã³ãœãŒã¹ã®å®è£
ã«ãããã¹ã±ãŒãªã³ã°åŸã«çŸåšã®èŠçŽ ãã¹ã³ãŒãå
ã«ä¿æããåé¡ã解決ãããŸãã
- UIä»®æ³åã®æ¬ èœïŒ
- ã«ã«ãŒã»ã«ã¯ãItemsPanelã®ç¬èªã®å®è£ ã䜿çšããŸãã ãŸããUIä»®æ³åã®ãµããŒãã¯ãããŸããã
- ããã¯ç§ãã¡ã«ãšã£ãŠéåžžã«éèŠãªããšã§ãããªããªã ãªãŒãã¬ããã«ã¯éåžžã«å€ãã®è²©ä¿è³æãå«ããããšãã§ããããã¯ããŒãžã®èªã¿èŸŒã¿æéã«å€§ãã圱é¿ããŸãã
- ã¯ãããããããããå®è¡å¯èœã§ãã ããããããã¯ãã¯ãåçŽã«èŠããŸããã
- UIã¹ã¬ããïŒã¹ããŒãªãŒããŒããšæäœ*ã€ãã³ãïŒã§ã¢ãã¡ãŒã·ã§ã³ã䜿çšããŸããããã¯ãå®çŸ©äžãåžžã«ååã«æ»ããã§ã¯ãããŸããã
ããªãã¡ å¿ èŠã«å¿ããŠãã®ã³ã³ãããŒã«ãå®æãããã®ã«ããªãã®æéãè²»ããå¿ èŠãããããšãããããŸãïŒ1ã€ã®UIä»®æ³åã®äŸ¡å€ããããŸãïŒã åæã«ãåºåã§ã¯ãã¢ãã¡ãŒã·ã§ã³ãé ããªãå¯èœæ§ã®ããäœåãååŸããŸãã
äžè¬çã«ããã®ã¢ãããŒããæŸæ£ããããšã決å®ããŸããã æéãç¡é§ã«ãããªããè³¢æã«ãããããã§ãããã
æ¹æ³3.å®è£
ãã¿ããã®ã¿ãScrollViewerã®äœæ
ããŠã¹ãã€ãŒã«ãããã¹ãŠã®ã€ãã³ãããã£ããã£ãããããæšæºã®ScrollViewerã¯äœ¿çšããããªãããšãæãåºãããŠãã ããïŒäžèšã®ãGridViewãåé¡3ãã®ã»ã¯ã·ã§ã³ãåç §ïŒã
ã«ã«ãŒã»ã«ã®å®è£ ã¯å¥œãã§ã¯ãããŸããã UIã¹ããªãŒã ã§ã¢ãã¡ãŒã·ã§ã³ã䜿çšããUWPã¢ããªã±ãŒã·ã§ã³çšã®ã¢ãã¡ãŒã·ã§ã³ãäœæããããã®å¥œãŸããæ¹æ³ã¯ã Compositionã¢ãã¡ãŒã·ã§ã³ã§ãã ãã銎æã¿ã®ããã¹ããŒãªãŒããŒããšã®éãã¯ãå¥ã®ã³ã³ããžã·ã§ã³ã¹ããªãŒã ã§åäœãããããUIã¹ããªãŒã ãäœãã§ããžãŒãªå Žåã§ã60ãã¬ãŒã /ç§ãæäŸããããšã§ãã
ã¿ã¹ã¯ãå®è¡ããã«ã¯ãã¢ãã¡ãŒã·ã§ã³ã®ãœãŒã¹ãšããŠã¿ããå ¥åã䜿çšã§ããããã«ããã³ã³ããŒãã³ãã§ããInteractionTrackerãå¿ èŠã§ãã å®éãæåã«ãããªããã°ãªããªãããšã¯ãç»é¢äžã®æã®åãã«å¿ããŠUIèŠçŽ ãæ°Žå¹³ã«ç§»åããããšã§ãã å®éãã«ã¹ã¿ã ScrollViewerãå®è£ ããããšããå§ããªããã°ãªããŸããã ãããTouchOnlyScrollViewerãšåŒã³ãŸãããïŒ
public class TouchOnlyScrollerViewer : ContentControl { private Visual _thisVisual; private Compositor _compositor; private InteractionTracker _tracker; private VisualInteractionSource _interactionSource; private ExpressionAnimation _positionExpression; private InteractionTrackerOwner _interactionTrackerOwner; public double HorizontalOffset { get; private set; } public event Action<double> ViewChanging; public event Action<double> ViewChanged; public TouchOnlyScrollerViewer() { initInteractionTracker(); Loaded += onLoaded; PointerPressed += onPointerPressed; } private void initInteractionTracker() { // InteractionTracker VisualInteractionSource _thisVisual = ElementCompositionPreview.GetElementVisual(this); _compositor = _thisVisual.Compositor; _tracker = InteractionTracker.Create(_compositor); _interactionSource = VisualInteractionSource.Create(_thisVisual); _interactionSource.PositionXSourceMode = InteractionSourceMode.EnabledWithInertia; _tracker.InteractionSources.Add(_interactionSource); // Expression-, // touch- InteractionTracker _positionExpression = _compositor.CreateExpressionAnimation("-tracker.Position"); _positionExpression.SetReferenceParameter("tracker", _tracker); } private void onLoaded(object sender, RoutedEventArgs e) { // Offset UIElement- var visual = ElementCompositionPreview.GetElementVisual((UIElement)Content); visual.StartAnimation("Offset", _positionExpression); } private void onPointerPressed(object sender, PointerRoutedEventArgs e) { // touch- composition- if (e.Pointer.PointerDeviceType == PointerDeviceType.Touch) { try { _interactionSource.TryRedirectForManipulation(e.GetCurrentPoint(this)); } catch (Exception ex) { Debug.WriteLine("TryRedirectForManipulation: " + ex.ToString()); } } } }
ããã§ã¯ããã¹ãŠãMircosoftã®ããã¯ã«å³å¯ã«åŸã£ãŠããŸãã TryRedirectForManipulationåŒã³åºãã¯ããšãã©ãçªç¶ã®äŸå€ãã¹ããŒãããããtry-catchã§ã©ããããå¿ èŠãããå Žåãé€ããŸãã ããã¯éåžžã«ãŸãã«çºçãïŒã±ãŒã¹ãã±ãŒã¹ã®çŽ2-5ïŒ ïŒãçç±ãèŠã€ããããšãã§ããŸããã§ããã ãã€ã¯ããœããã®ããã¥ã¡ã³ããšå ¬åŒã®äŸã§ããã«ã€ããŠäœãèšãããŠããªãã®ã¯ãªãã§ãã-ç§ãã¡ã¯ç¥ããŸãã;ïŒ
ã¿ããã®ã¿ScrollViewerã HorizoâântalOffsetãšã€ãã³ãViewChangingããã³ViewChangedã圢æããŸã
ScrollViewerã«äŒŒãŠãããããHorizoâântalOffsetããããã£ãšViewChangingããã³ViewChangedã€ãã³ããå¿ èŠã§ãã InteractionTrackerã®ã³ãŒã«ããã¯ãåŠçããŠå®è£ ããŸãã ããããååŸããã«ã¯ãInteractionTrackerãäœæãããšãã«ããããã®ã³ãŒã«ããã¯ãåãåãIInteractionTrackerOwnerãå®è£ ãããªããžã§ã¯ããæå®ããå¿ èŠããããŸãã
_interactionTrackerOwner = new InteractionTrackerOwner(this); _tracker = InteractionTracker.CreateWithOwner(_compositor, _interactionTrackerOwner);
å®å šãæãããã«ãInteractionTrackerã®ç¶æ ãšã€ãã³ããå«ãããã¥ã¡ã³ãããåçãã³ããŒããŸãã
ViewChangedã€ãã³ãã¯ãã¢ã€ãã«ç¶æ ã«å ¥ããšã¹ããŒãããŸãã
IInteractionTrackerOwner.ValuesChangedãçºçãããšãViewChangingã€ãã³ããã¹ããŒãããŸãã
InteractionTrackerãã¢ã€ãã«ç¶æ ã®ãšãã«ValuesChangedãçºçããå¯èœæ§ãããããšãããã«èšããªããã°ãªããŸããã ããã¯ãInteractionTracker TryUpdatePositionãåŒã³åºããåŸã«çºçããŸãã ãããŠãããã¯UWPãã©ãããã©ãŒã ã®ãã°ã®ããã«èŠããŸãã
ãŸããããªãã¯ããã«ææ ¢ããªããã°ãªããŸããã 幞ããªããšã«ãããã¯é£ãããããŸãããValuesChangedã«å¿ããŠãçŸåšã®ç¶æ ã«å¿ããŠViewChangingãŸãã¯ValuesChangedã®ãããããç Žæ£ããŸãã
private class InteractionTrackerOwner : IInteractionTrackerOwner { private readonly TouchOnlyScrollerViewer _scrollViewer; public void ValuesChanged(InteractionTracker sender, InteractionTrackerValuesChangedArgs args) { // . . _scrollViewer.HorizontalOffset = args.Position.X; if (_interactionTrackerState != InteractionTrackerState.Idle) { _scrollViewer.ViewChanging?.Invoke(args.Position.X); } else { _scrollViewer.ViewChanged?.Invoke(args.Position.X); } } public void IdleStateEntered(InteractionTracker sender, InteractionTrackerIdleStateEnteredArgs args) { // _scrollViewer._tracker.Position. // Windows 14393 (Anniversary Update) - 0 _scrollViewer.ViewChanged?.Invoke(_scrollViewer.HorizontalOffset, requestType); } }
ã¿ããã®ã¿ScrollViewerã ãã€ã³ããã¹ãããããŠæ£ç¢ºã«1ã€ã®èŠçŽ ãã¹ã¯ããŒã«
1ã€ã®èŠçŽ ã§æ£ç¢ºã«ã¹ã¯ããŒã«ããããã«ããã°ããã解決çããããŸã-ã æ £æ§ä¿®æ£åã䜿çšããã¹ããããã€ã³ã ãã
ãã€ã³ãã¯ãã¿ããã¹ã¯ãªãŒã³ãã¹ã¯ã€ãããåŸã«ã¹ã¯ããŒã«ãåæ¢ãããã€ã³ããèšå®ããããšã§ãã ãããŠãæ®ãã®ããžãã¯ã¯InteractionTrackerã«ãã£ãŠååŸãããŸãã å®éãã¹ã¯ã€ãåŸã®åæ¢ãã¹ã ãŒãºã«ãåæã«å¿ èŠãªå Žæã§æ£ç¢ºã«çºçããããã«ãæžéçãå€æŽããŸãã
ç§ãã¡ã®å®è£ ã¯ã ããã¥ã¡ã³ãã®äŸã§èª¬æãããŠããå®è£ ãšãããã«ç°ãªããŸã ã ãŠãŒã¶ãŒããªãŒãã¬ãããããŸãã«ãéããããã£ããå Žåã§ããäžåºŠã«è€æ°ã®èŠçŽ ãã¹ã¯ããŒã«ãããããªãããã§ãã
ãããã£ãŠããå·Šãž1ã¹ããããããå³ãž1ã¹ããããããçŸåšã®äœçœ®ã«ãšã©ãŸãããšãã3ã€ã®ã¹ããããã€ã³ãã®ã¿ãè¿œå ããŸãã ãããŠãåã¹ã¯ããŒã«ã®åŸã«ããããæŽæ°ããŸãã
ãŸããã¹ã¯ããŒã«åŸã«æ¯åã¹ããããã€ã³ããåäœæããªãããã«ããããããã©ã¡ãŒã¿ãŒåå¯èœã«ããŸãã ãããè¡ãã«ã¯ã3ã€ã®ããããã£ã§PropertySetãéå§ããŸãã
_snapPointProps = _compositor.CreatePropertySet(); _snapPointProps.InsertScalar("offsetLeft", 0); _snapPointProps.InsertScalar("offsetCurrent", 0); _snapPointProps.InsertScalar("offsetRight", 0);
ãŸããConditionããã³RestingValueã®åŒã§ã¯ããã®PropertySetã®ããããã£ã䜿çšããŸãã
// « » var leftSnap = InteractionTrackerInertiaRestingValue.Create(_compositor); leftSnap.Condition = _compositor.CreateExpressionAnimation( "this.Target.NaturalRestingPosition.x < " + "props.offsetLeft * 0.25 + props.offsetCurrent * 0.75"); leftSnap.Condition.SetReferenceParameter("props", _snapPointProps); leftSnap.RestingValue = _compositor.CreateExpressionAnimation("props.offsetLeft"); leftSnap.RestingValue.SetReferenceParameter("props", _snapPointProps); // « » var currentSnap = InteractionTrackerInertiaRestingValue.Create(_compositor); currentSnap.Condition = _compositor.CreateExpressionAnimation( "this.Target.NaturalRestingPosition.x >= " + "props.offsetLeft * 0.25 + props.offsetCurrent * 0.75 && " + "this.Target.NaturalRestingPosition.x < " + "props.offsetCurrent * 0.75 + props.offsetRight * 0.25"); currentSnap.Condition.SetReferenceParameter("props", _snapPointProps); currentSnap.RestingValue = _compositor.CreateExpressionAnimation("props.offsetCurrent"); currentSnap.RestingValue.SetReferenceParameter("props", _snapPointProps); // « » var rightSnap = InteractionTrackerInertiaRestingValue.Create(_compositor); rightSnap.Condition = _compositor.CreateExpressionAnimation( "this.Target.NaturalRestingPosition.x >= " + "props.offsetCurrent * 0.75 + props.offsetRight * 0.25"); rightSnap.Condition.SetReferenceParameter("props", _snapPointProps); rightSnap.RestingValue = _compositor.CreateExpressionAnimation("props.offsetRight"); rightSnap.RestingValue.SetReferenceParameter("props", _snapPointProps); _tracker.ConfigurePositionXInertiaModifiers( new InteractionTrackerInertiaModifier[] { leftSnap, currentSnap, rightSnap }); }
ããã«ïŒ
- NaturalRestingPosition.Xã¯ãã¹ããããã€ã³ãããªãå Žåã«æ
£æ§ãçµäºãããªãã»ããã§ãã
- SnapPoint.RestingValue-SnapPoint.Conditionæ¡ä»¶ãæºãããããšãã«åæ¢ãèš±å¯ããããªãã»ããã
æåã«ãã¹ããããã€ã³ãéã®çãäžã®æ¡ä»¶ã«å¢çç·ãèšå®ããããšããŸãããããŠãŒã¶ãŒã¯äœããã®çç±ã§ãã¹ãŠã®ã¹ã¯ã€ãã次ã®èŠçŽ ã«ã¹ã¯ããŒã«ããããã§ã¯ãªãããšã«æ°ä»ããŸããã äžéšã®ã¹ã¯ã€ãã¯ååã«éããªããããŒã«ããã¯ããããŸããã
ãããã£ãŠãContitionã®åŒã§ã¯ã0.25ããã³0.75ã®ä¿æ°ã䜿çšããŠããããããé ããã¹ã¯ã€ãã§ã次ã®èŠçŽ ã«ã¹ã¯ããŒã«ããŸãã
次ã®èŠçŽ ã«ã¹ã¯ããŒã«ãããã³ã«ããã®ã¡ãœãããåŒã³åºããŠã¹ããããã€ã³ããã©ã¡ãŒã¿ãŒãæŽæ°ããŸãã
public void SetSnapPoints(double left, double current, double right) { _snapPointProps.InsertScalar("offsetLeft", (float)Math.Max(left, 0)); _snapPointProps.InsertScalar("offsetCurrent", (float)current); _snapPointProps.InsertScalar("offsetRight", (float)Math.Min(right, _tracker.MaxPosition.X)); }
UIä»®æ³åããã«
次ã®ã¹ãããã¯ãTouchOnlyScrollerViewerã«åºã¥ããŠæ¬æ ŒçãªItemsControlãæ§ç¯ããããšã§ããã
åèã®ããã UIä»®æ³åãšã¯ãããšãã°1000人ã®åäŸã§ã¯ãªããã³ã³ãããŒã«ãªã¹ããç»é¢ã«è¡šç€ºããããã®ã ããäœæããå Žåã§ãã ã¹ã¯ããŒã«ãããšãã«ããããåå©çšããæ°ããããŒã¿ãªããžã§ã¯ãã«ãã€ã³ãããŸãã ããã«ããããªã¹ãã«å€æ°ã®ã¢ã€ãã ãããå ŽåãããŒãžã®èªã¿èŸŒã¿æéãççž®ã§ããŸãã
ãªããªã çµå±ãUIä»®æ³åãå®è£ ããããªãã£ãã®ã§ãããã¡ãããæåã«ããããšããããšã¯ãæšæºã®ItemsStackPanelã䜿çšããããšã§ãã ã
ç§ãã¡ã®TouchOnlyScrollerViewerã§åœŒå¥³ã®åéãäœãããã£ãã æ®å¿µãªããããã®å éšæ§é ãŸãã¯ãœãŒã¹ã³ãŒãã«é¢ããããã¥ã¡ã³ããèŠã€ããããšã¯ã§ããŸããã§ããã ããããäžé£ã®å®éšã«ãããItemsStackPanelã¯èŠªèŠçŽ ã®ãªã¹ãå ã®ããžã¥ã¢ã«ããªãŒã§ScrollViewerãæ¢ãããšã瀺åãããŸããã ãããŠãã©ããããããããããªãŒããŒã©ã€ãããŠãæšæºã®ScrollViewerã®ä»£ããã«ãããç§ãã¡ã®ãã®ã«ãªãããã«ãèŠã€ããããŸããã
ããã ãããã£ãŠãUIä»®æ³åã䜿çšããããã«ã¯ãç¬ç«ããŠå®è¡ããå¿ èŠããããŸãã ãã®ãããã¯ã§èŠã€ãã£ãæé«ã®ãã®ã¯ã11幎åãšããæ©ãããã®ã·ãªãŒãºã®èšäºã§ããã1ã2ã3ã4ã§ãã 確ãã«ãããã¯WPFã«ã€ããŠã§ãããUWPã«ã€ããŠã§ã¯ãããŸããããã¢ã€ãã¢ãéåžžã«ããäŒããŠããŸãã ç§ãã¡ã¯ãããå©çšããŸããã
å®éã«ã¯ãã¢ã€ãã¢ã¯ç°¡åã§ãã
- ãã®ãããªããã«ã¯TouchOnlyScrollerViewerå
ã«åã蟌ãŸããViewChangingããã³ViewChangedã€ãã³ãã«ãµãã¹ã¯ã©ã€ãããŸãã
- ããã«ã¯ãéãããæ°ã®åUIèŠçŽ ãäœæããŸãã ç§ãã¡ã®å Žåãããã¯5ïŒäžå€®ã«1ã€ãå·Šå³ããçªãåºããè³ãã«2ã€ããè³ãã«ç¶ãèŠçŽ ã®ãã£ãã·ã¥ã«2ã€ïŒã§ãã
- UIèŠçŽ ã¯TouchOnlyScrollerViewer.HorizoâântalOffsetã«å¿ããŠé
眮ãããã¹ã¯ããŒã«ããããšãã«ç®çã®ããŒã¿ãªããžã§ã¯ãã«åã¢ã¿ãããããŸãã
å®è£ ã瀺ããŸããããªããªã ããªãè€éã§ããã ããããå¥ã®èšäºã®ãããã¯ã§ãã
ã¿ããå ¥åãã³ã³ããžã·ã§ã³ã¹ããªãŒã ã«ãªãã€ã¬ã¯ãããåŸã«å€±ãããã¿ããã€ãã³ããæ¢ããŠããŸã
ãŸãšãããšãå¥ã®èå³æ·±ãåé¡ãæããã«ãªããŸããã ã¿ããå ¥åãInteractionTrackerã«ãªãã€ã¬ã¯ããããŠããéã«ããŠãŒã¶ãŒãã³ã³ãããŒã«å ã®èŠçŽ ãã¿ããããå ŽåããããŸãã ããã¯ãæ £æ§ã¹ã¯ããŒã«ãçºçãããšãã«çºçããŸãã ãã®å ŽåãPointerPressedãPointerReleasedãããã³Tappedã€ãã³ãã¯çºçããŸããã ãããŠãããã¯å€§ãããªåé¡ã§ã¯ãããŸããã InteractionTrackerã®æ £æ§ã¯ããªãé·ãã§ãã ãŸããèŠèŠçãªã¹ã¯ããŒã«ãã»ãŒçµäºããå Žåã§ããå®éã«ã¯ãæåŸã®æ°ãã¯ã»ã«ã®é ãã¹ã¯ããŒã«ãçºçããå ŽåããããŸãã
ãã®çµæããŠãŒã¶ãŒã¯åæºããŠããŸã-圌ã¯ãéžæããæ ç»ã®ããŒãžãã¿ããã§éãããšãæåŸ ããŠããŸãã ããããããã¯èµ·ãããŸããã
ãããã£ãŠãInteractionTrackerããã®ã€ãã³ãã®ãã¢ã«ãã£ãŠã¿ãããèå¥ããŸãã
- 察話ç¶æ
ã«å
¥ãïŒæãç»é¢ã«è§ŠããïŒ;
- ãã®åŸãçŽã¡ã«ïŒ150ããªç§æªæºã§ïŒæ
£æ§ç¶æ
ã«ç§»è¡ããŸãïŒæã§ç»é¢ã解æŸããŸããïŒã åæã«ãã¹ã¯ããŒã«é床ã¯ãŒãã§ãªããã°ãªããŸããïŒããã§ãªããã°ãã¿ããã§ã¯ãªãã¹ã¯ã€ãã«ãªããŸãïŒã
public void InertiaStateEntered(InteractionTracker sender, InteractionTrackerInertiaStateEnteredArgs args) { if (_interactionTrackerState == InteractionTrackerState.Interacting && (DateTime.Now - _lastStateTime) < TimeSpan.FromMilliseconds(150) && Math.Abs(args.PositionVelocityInPixelsPerSecond.X) < 1 /* 1px/sec */) { _scrollViewer.TappedCustom?.Invoke(_scrollViewer.HorizontalOffset); } _interactionTrackerState = InteractionTrackerState.Inertia; _lastStateTime = DateTime.Now; }
åäœããŸãã ãã ããã¿ãããå®è£ ãããèŠçŽ ãèªèããããšã¯ã§ããŸããã ç§ãã¡ã®å Žåãããã¯éèŠã§ã¯ãããŸããã èŠçŽ ã¯ãTouchOnlyScrollViewerã®è¡šç€ºå¹ ã®ã»ãŒå šäœãå ããŸãã ãããã£ãŠãåçŽã«äžå¿ã«è¿ããã®ãéžæããŸãã ã»ãšãã©ã®å Žåãããã¯ãŸãã«ããªããå¿ èŠãšãããã®ã§ãã ãããŸã§ã®ãšãããã¹ã¯ããŒã«äžã«æã ã¿ãããããšééã£ãå Žæã«ã€ãªããããšã«æ°ã¥ããŠããããŸããã ããªãããããç¥ã£ãŠããŠãããã£ããããã®ã¯ããã»ã©ç°¡åã§ã¯ãããŸãã;ïŒ
äžè¬çãªã±ãŒã¹ã§ã¯ãããŸãããããã¯å®å šãªãœãªã¥ãŒã·ã§ã³ã§ã¯ãããŸããã å®å šã«å®è£ ããã«ã¯ãããããã¹ãããããããå¿ èŠããããŸãã ãããããããè¡ãæ¹æ³ã¯æ確ã§ã¯ãããŸããã ã¿ããã®åº§æšã¯äžæã§ã...
ããŒãã¹ äžéæ床ãã¹ã±ãŒã«ã圱ã®è¡šçŸã¢ãã¡ãŒã·ã§ã³ã æçµçã«çŸãããªãããã«
ãããŠæåŸã«ãã±ãŒãã®ãã§ãªãŒã¯ããããã¹ãŠã§ãã£ããã®ã§ãã ã¹ã¯ããŒã«ããªãããèŠçŽ ã®ãµã€ãºã圱ãéæ床ãå€æŽããŸãã äžå¿ã«ãããã®ããããã«çãäžãã£ãŠãããããªæèŠãäœãåºãããã
ãã®ããã«ã Expression-animationsã䜿çšããŸãã ãããã¯ã³ã³ããžã·ã§ã³ãµãã·ã¹ãã ã®äžéšã§ããããå¥ã®ã¹ã¬ããã§åäœãããããUIã¹ã¬ãããããžãŒã®ãšãã«é床ãäœäžããããšã¯ãããŸããã
ãããã¯ãã®ããã«äœæãããŸãã ããããã£ãã¢ãã¡ãŒã·ã§ã³åããããã«ããã®ããããã£ãä»ã®ããããã£ã«äŸåããããšãå®çŸ©ããåŒãå®çŸ©ããŸãã åŒã¯ããã¹ãæååãšããŠäžããããŸãã
圌ãã®é åã¯ããã§ãŒã³ã§é 眮ã§ããããšã§ãã ããã䜿çšããŸãã
ãã¹ãŠã®ã¢ãã¡ãŒã·ã§ã³ã®ãœãŒã¹ã¯ãInteractionTrackerããã®ãã¯ã»ã«åäœã®ãªãã»ããã§ãã UI- progress, 0 1. progress- .
, _progressExpression , :
- 0 â ;
- 1 â , , , :
_progressExpression = _compositor.CreateExpressionAnimation( "1 - " + "Clamp(Abs(tracker.Position.X - props.offsetWhenSelected), 0, props.maxDistance)" + " / props.maxDistance");
:
- Clamp(val, min, max) â . val min/max, min/max. â val.
- offsetWhenSelected â InteractionTracker-, ;
- maxDistance â , ;
- tracker â InteractionTracker.
Expression-:
_progressExpression.SetReferenceParameter("tracker", tracker); _props = _compositor.CreatePropertySet(); _props.InsertScalar("offsetWhenSelected", (float)offsetWhenSelected); _props.InsertScalar("maxDistance", getMaxDistanceParam()); _progressExpression.SetReferenceParameter("props", _props);
PropertySet progress, _progressExpression. , :
_progressProps = _compositor.CreatePropertySet(); _progressProps.InsertScalar("progress", 0f); _progressProps.StartAnimation("progress", _progressExpression);
progress «» ( Lerp ColorLerp). , Expression- .
:
_scaleExpression = _compositor.CreateExpressionAnimation( "Vector3(Lerp(earUnfocusScale, 1, props.progress), " + "Lerp(earUnfocusScale, 1, props.progress), 1)"); _scaleExpression.SetScalarParameter("earUnfocusScale", (float)_earUnfocusScale); _scaleExpression.SetReferenceParameter("props", _progressProps); _thisVisual.StartAnimation("Scale", _scaleExpression);
:
_shadowBlurRadiusExpression = _compositor.CreateExpressionAnimation( "Lerp(blur1, blur2, props.progress)"); _shadowBlurRadiusExpression.SetScalarParameter("blur1", ShadowBlurRadius1); _shadowBlurRadiusExpression.SetScalarParameter("blur2", ShadowBlurRadius2); _shadowBlurRadiusExpression.SetReferenceParameter("props", _progressProps); _dropShadow.StartAnimation("BlurRadius", _shadowBlurRadiusExpression);
:
_shadowColorExpression = _compositor.CreateExpressionAnimation( "ColorLerp(color1, color2, props.progress)")) _shadowColorExpression.SetColorParameter("color1", ShadowColor1); _shadowColorExpression.SetColorParameter("color2", ShadowColor2); _shadowColorExpression.SetReferenceParameter("props", _progressProps); _dropShadow.StartAnimation("Color", _shadowColorExpression);
.
ããã ãã§ã , , , , . fluent design :)
â , , .