为ListBox中的列表项添加加载动画

来源:互联网 发布:枯枝败叶 知乎 编辑:程序博客网 时间:2024/04/28 23:35
 static public class ListAnimationsHelper    {        public static bool GetIsPivotAnimated(DependencyObject obj)        {            return (bool)obj.GetValue(IsPivotAnimatedProperty);        }        public static void SetIsPivotAnimated(DependencyObject obj, bool value)        {            obj.SetValue(IsPivotAnimatedProperty, value);        }        // Using a DependencyProperty as the backing store for IsPivotAnimated.  This enables animation, styling, binding, etc...        public static readonly DependencyProperty IsPivotAnimatedProperty =            DependencyProperty.RegisterAttached("IsPivotAnimated", typeof(bool), typeof(ListAnimationsHelper), new PropertyMetadata(false, OnIsPivotAnimatedPropertyChangedCallback));        private static void OnIsPivotAnimatedPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)        {            //初始化动画相关对象事件            ItemsControl list = d as ItemsControl;   //ListBox继承于ItemsControl            list.Loaded += (s2, e2) =>            {                Pivot pivot = GetParent<Pivot>(list);                int pivotIndex = pivot.Items.IndexOf(GetParent<PivotItem>(list));                //订阅Pivot控件的SelectionChanged事件, 发生SelectionChanged事件时候要触发动画                pivot.SelectionChanged += (s3, e3) =>                    {                        //如果不是该列表控件对应的Pivot控件页签就不触发动画的逻辑,因为SelectionChagned事件会被多次触发                        if (pivotIndex != pivot.SelectedIndex)                            return;                        var items = list.GetItemsInView().ToList();                        AddSlideAnimation(items);                    };                    var items2 = list.GetItemsInView().ToList();                    AddSlideAnimation(items2);            };        }        public static IEnumerable<FrameworkElement> GetItemsInView(this ItemsControl itemsControl)        {            VirtualizingStackPanel vsp = GetChild<VirtualizingStackPanel>(itemsControl);            int firstVisibleItem = (int)vsp.VerticalOffset;            int visibleItemCount = (int)vsp.ViewportHeight;            for (int index = firstVisibleItem; index <= firstVisibleItem + visibleItemCount + 1; index++)            {                var item = itemsControl.ItemContainerGenerator.ContainerFromIndex(index);                if (item == null)                    continue;                yield return item as FrameworkElement;            }        }        private  static void AddSlideAnimation(List<FrameworkElement> items)        {            for (int index = 0; index < items.Count; index++)            {                var lbi = items[index];                var animationTargets = lbi.Descendants().Where(p => ListAnimationsHelper.GetAnimationLevel(p) > -1);                foreach (FrameworkElement item in animationTargets)                {                    GetSlideAnimation(item, false).Begin();                }            }        }        public static int GetAnimationLevel(DependencyObject obj)        {            return (int)obj.GetValue(AnimationLevelProperty);        }        public static void SetAnimationLevel(DependencyObject obj, int value)        {            obj.SetValue(AnimationLevelProperty, value);        }        // Using a DependencyProperty as the backing store for AnimationLevel.  This enables animation, styling, binding, etc...        public static readonly DependencyProperty AnimationLevelProperty =            DependencyProperty.RegisterAttached("AnimationLevel", typeof(int), typeof(ListAnimationsHelper), new PropertyMetadata(null));        #region 操作可视化树        public static T GetParent<T>(DependencyObject item) where T:class        {            DependencyObject obj = VisualTreeHelper.GetParent(item);            while (obj != null)            {                if (obj is T)                    return obj as T;                obj = VisualTreeHelper.GetParent(obj);            }            return null;        }        public static T GetChild<T>(DependencyObject item) where T : class        {            var queue = new Queue<DependencyObject>();            queue.Enqueue(item);            while (queue.Count > 0)            {                DependencyObject current = queue.Dequeue();                for (int i = VisualTreeHelper.GetChildrenCount(current) - 1; 0 <= i; i--)                {                    var child = VisualTreeHelper.GetChild(current, i);                    var typeChild = child as T;                    if (typeChild != null)                    {                        return typeChild;                    }                    queue.Enqueue(child);                }            }            return null;        }        public static IEnumerable<DependencyObject> Descendants(this DependencyObject item)        {            var queue = new Queue<DependencyObject>();            queue.Enqueue(item);            while (queue.Count > 0)            {                DependencyObject current = queue.Dequeue();                for (int i = VisualTreeHelper.GetChildrenCount(current) - 1; 0 <= i; i--)                {                    var child = VisualTreeHelper.GetChild(current, i);                    if (child != null)                    {                        yield return child;                        queue.Enqueue(child);                    }                }            }        }        #endregion        private static DoubleAnimation CreateAnimation(double from, double to, double duration, string targetProperty, DependencyObject target)        {            var db = new DoubleAnimation();            db.To = to;            db.From = from;            db.EasingFunction = new SineEase();            db.Duration = TimeSpan.FromSeconds(duration);            Storyboard.SetTarget(db, target);            Storyboard.SetTargetProperty(db, new PropertyPath(targetProperty));            return db;        }        private static Storyboard GetSlideAnimation(FrameworkElement element, bool fromRight)        {            double from = fromRight ? 80 : -80;            Storyboard sb;            double delay = (ListAnimationsHelper.GetAnimationLevel(element)) * 0.1 + 0.1;            TranslateTransform trans = new TranslateTransform()            {                X = from,            };            element.RenderTransform = trans;            sb = new Storyboard();            sb.BeginTime = TimeSpan.FromSeconds(delay);            sb.Children.Add(CreateAnimation(from, 0, 0.8, "X", trans));            return sb;        }    }

0 0