첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.

728x90
반응형
728x170

TestProject.zip
0.02MB

▶ MainPage.xaml

<Page x:Class="TestProject.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    FontFamily="나눔고딕코딩"
    FontSize="16">
    <Grid>
        <Grid
            HorizontalAlignment="Center"
            VerticalAlignment="Center">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="50"   />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <ScrollViewer Name="scrollViewer" Grid.Column="0"
                Width="400"
                Height="300"
                ViewChanging="scrollViewer_ViewChanging">
                <muxc:ItemsRepeater Name="itemsRepeater">
                    <DataTemplate x:DataType="x:String">
                        <Button Content="{x:Bind}"
                            HorizontalAlignment="Stretch"
                            Background="{x:Bind}"
                            Foreground="{StaticResource SystemBaseHighColor}"
                            Loaded="button_Loaded"
                            GotFocus="button_GotFocusOrClick" 
                            Click="button_GotFocusOrClick" />
                    </DataTemplate>
                </muxc:ItemsRepeater>
            </ScrollViewer>
            <Rectangle x:Name="rectangle" Grid.Column="2"
                Stroke="{ThemeResource SystemControlForegroundBaseHighBrush}"
                Width="150"
                Height="150" />
        </Grid>
    </Grid>
</Page>

 

728x90

 

▶ MainPage.xaml.cs

using Microsoft.UI.Xaml.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Windows.Foundation;
using Windows.Graphics.Display;
using Windows.UI;
using Windows.UI.Composition;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Hosting;

namespace TestProject
{
    /// <summary>
    /// 메인 페이지
    /// </summary>
    public sealed partial class MainPage : Page
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 애니메이션 버튼 마진
        /// </summary>
        private Thickness AnimatedButtonMargin;

        /// <summary>
        /// 애니메이션 버튼 높이
        /// </summary>
        private double AnimatedButtonHeight;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainPage()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainPage()
        {
            InitializeComponent();

            #region 윈도우 크기를 설정한다.

            double width  = 800d;
            double height = 600d;

            double dpi = (double)DisplayInformation.GetForCurrentView().LogicalDpi;

            ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.PreferredLaunchViewSize;

            Size windowSize = new Size(width * 96d / dpi, height * 96d / dpi);

            ApplicationView.PreferredLaunchViewSize = windowSize;

            Window.Current.Activate();

            ApplicationView.GetForCurrentView().TryResizeView(windowSize);

            #endregion
            #region 윈도우 제목을 설정한다.

            ApplicationView.GetForCurrentView().Title = "ItemsRepeater 엘리먼트 : 애니메이션 스크롤 사용하기";

            #endregion

            this.itemsRepeater.ItemsSource = GetColorList();

            this.itemsRepeater.ElementPrepared += itemsRepeater_ElementPrepared;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private
        //////////////////////////////////////////////////////////////////////////////// Event

        #region 스크롤 뷰어 뷰 변경시 처리하기 - scrollViewer_ViewChanging(sender, e)

        /// <summary>
        /// 스크롤 뷰어 뷰 변경시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void scrollViewer_ViewChanging(object sender, ScrollViewerViewChangingEventArgs e)
        {
            Button button = GetSelectedItemFromViewport() as Button;

            this.rectangle.Fill = button.Background;
        }

        #endregion
        #region 항목 반복자 엘리먼트 준비시 처리하기 - itemsRepeater_ElementPrepared(sender, e)

        /// <summary>
        /// 항목 반복자 엘리먼트 준비시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void itemsRepeater_ElementPrepared(ItemsRepeater sender, ItemsRepeaterElementPreparedEventArgs e)
        {
            Visual itemVisual = ElementCompositionPreview.GetElementVisual(e.Element);

            Visual scrollViewerVisual = ElementCompositionPreview.GetElementVisual(this.scrollViewer);

            CompositionPropertySet scrollViwerPropertySet = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(this.scrollViewer);

            ExpressionAnimation scaleAnimation = scrollViwerPropertySet.Compositor.CreateExpressionAnimation();

            scaleAnimation.SetReferenceParameter("scrollViewerVisual"    , scrollViewerVisual    );
            scaleAnimation.SetReferenceParameter("scrollViwerPropertySet", scrollViwerPropertySet);
            scaleAnimation.SetReferenceParameter("itemVisual"            , itemVisual            );

            scaleAnimation.Expression = "1 - abs((scrollViewerVisual.Size.Y / 2 - scrollViwerPropertySet.Translation.Y) - " +
                                        "(itemVisual.Offset.Y + itemVisual.Size.Y / 2)) * (.25 / (scrollViewerVisual.Size.Y / 2))";

            itemVisual.StartAnimation("Scale.X", scaleAnimation);
            itemVisual.StartAnimation("Scale.Y", scaleAnimation);

            ExpressionAnimation centerPointAnimation = scrollViwerPropertySet.Compositor.CreateExpressionAnimation();

            centerPointAnimation.SetReferenceParameter("itemVisual", itemVisual);

            centerPointAnimation.Expression = "Vector3(itemVisual.Size.X / 2, itemVisual.Size.Y / 2, 0)";

            itemVisual.StartAnimation("CenterPoint", centerPointAnimation);
        }

        #endregion
        #region 버튼 로드시 처리하기 - button_Loaded(sender, e)

        /// <summary>
        /// 버튼 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void button_Loaded(object sender, RoutedEventArgs e)
        {
            Button button = sender as Button;

            AnimatedButtonMargin = button.Margin;
            AnimatedButtonHeight = button.ActualHeight;
        }

        #endregion
        #region 버튼 포커스 획득시/클릭시 처리하기 - button_GotFocusOrClick(sender, e)

        /// <summary>
        /// 버튼 포커스 획득시/클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void button_GotFocusOrClick(object sender, RoutedEventArgs e)
        {
            Button button = sender as Button;

            button.StartBringIntoView
            (
                new BringIntoViewOptions()
                {
                    VerticalAlignmentRatio = 0.5,
                    AnimationDesired       = true
                }
            );

            this.rectangle.Fill = button.Background;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////// Function

        #region 색상 리스트 구하기 - GetColorList()

        /// <summary>
        /// 색상 리스트 구하기
        /// </summary>
        /// <returns>색상 리스트</returns>
        private IList<string> GetColorList()
        {
            IList<string> colorList = (typeof(Colors).GetRuntimeProperties().Select(color => color.ToString())).ToList();

            for(int i = 0; i < colorList.Count(); i++)
            {
                colorList[i] = colorList[i].Substring(17);
            }

            return colorList;
        }

        #endregion
        #region 범위 내에서 뷰포트 중심점 구하기 - GetCenterPointOfViewportInExtent()

        /// <summary>
        /// 범위 내에서 뷰포트 중심점 구하기
        /// </summary>
        /// <returns>뷰포트 중심점</returns>
        private double GetCenterPointOfViewportInExtent()
        {
            return this.scrollViewer.VerticalOffset + this.scrollViewer.ViewportHeight / 2;
        }

        #endregion
        #region 뷰포트에서 선택 인덱스 구하기 - GetSelectedIndexFromViewport()

        /// <summary>
        /// 뷰포트에서 선택 인덱스 구하기
        /// </summary>
        /// <returns>선택 인덱스</returns>
        private int GetSelectedIndexFromViewport()
        {
            int selectedItemIndex = (int)Math.Floor(GetCenterPointOfViewportInExtent() / ((double)AnimatedButtonMargin.Top + AnimatedButtonHeight));

            selectedItemIndex %= this.itemsRepeater.ItemsSourceView.Count;

            return selectedItemIndex;
        }

        #endregion
        #region 뷰포트에서 선택 항목 구하기 - GetSelectedItemFromViewport()

        /// <summary>
        /// 뷰포트에서 선택 항목 구하기
        /// </summary>
        /// <returns>선택 항목</returns>
        private object GetSelectedItemFromViewport()
        {
            var selectedIndex = GetSelectedIndexFromViewport();

            var selectedElement = this.itemsRepeater.TryGetElement(selectedIndex) as Button;

            return selectedElement;
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요