您的位置:首页 > 其它

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

2014-09-10 15:53 246 查看
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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: