Windows Phone 实现类似“微博”下拉刷新效果
请看新版本代码:
http://www.cnblogs.com/jinzhao/archive/2012/02/27/2370424.html
在我的O7上跑了下张善友写的博客园阅读APP,有很多体验上的想法,一时技痒想实现下拉刷新的效果。
如果要实现下拉的效果就需要三个状态,见下图:
第一种状态(提示下拉可以更新博客园新闻):
第二种状态(提示下拉的幅度已够可以释放进入更新操作)
第三种状态(提示正在更新,更新完毕回到第一个状态)
上面这个效果为了方便独立到一个UserControl中,代码如下:
XAML:
<UserControl x:Class="sdkRSSReaderCS.LoadingBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
d:DesignHeight="480" d:DesignWidth="480">
<Grid x:Name="LayoutRoot">
<StackPanel Orientation="Horizontal">
<Grid Margin="8,0,0,0" Width="50" Height="50">
<Image x:Name="PulldownArrow" Width="50" Height="50" Source="/sdkRSSReaderCS;component/images/pulldown_arrow.png">
<Image.RenderTransform>
<RotateTransform x:Name="FlipTransform" CenterX="25" CenterY="25" Angle="180"/>
</Image.RenderTransform>
<Image.Resources>
<Storyboard x:Name="FlipDown">
<DoubleAnimation Storyboard.TargetName="FlipTransform"
Storyboard.TargetProperty="Angle"
From="0" To="180" Duration="0:0:0.2"/>
</Storyboard>
<Storyboard x:Name="FlipUp">
<DoubleAnimation Storyboard.TargetName="FlipTransform"
Storyboard.TargetProperty="Angle"
From="180" To="0" Duration="0:0:0.2"/>
</Storyboard>
</Image.Resources>
</Image>
<Image x:Name="SpinningBall" Source="/sdkRSSReaderCS;component/images/spinning_ball.png" Width="36" Height="36">
<Image.RenderTransform>
<RotateTransform x:Name="SpinTransform" CenterX="18" CenterY="18"/>
</Image.RenderTransform>
<Image.Resources>
<Storyboard x:Name="Spin">
<DoubleAnimation Storyboard.TargetName="SpinTransform"
Storyboard.TargetProperty="Angle"
From="0" To="360" Duration="0:0:1"
RepeatBehavior="Forever"/>
</Storyboard>
</Image.Resources>
</Image>
</Grid>
<TextBlock x:Name="TextBlock" Margin="10,0,0,0"
VerticalAlignment="Center" FontSize="26"
Style="{StaticResource PhoneTextExtraLargeStyle}"
Foreground="{StaticResource PhoneAccentBrush}" />
</StackPanel>
</Grid>
</UserControl>
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
d:DesignHeight="480" d:DesignWidth="480">
<Grid x:Name="LayoutRoot">
<StackPanel Orientation="Horizontal">
<Grid Margin="8,0,0,0" Width="50" Height="50">
<Image x:Name="PulldownArrow" Width="50" Height="50" Source="/sdkRSSReaderCS;component/images/pulldown_arrow.png">
<Image.RenderTransform>
<RotateTransform x:Name="FlipTransform" CenterX="25" CenterY="25" Angle="180"/>
</Image.RenderTransform>
<Image.Resources>
<Storyboard x:Name="FlipDown">
<DoubleAnimation Storyboard.TargetName="FlipTransform"
Storyboard.TargetProperty="Angle"
From="0" To="180" Duration="0:0:0.2"/>
</Storyboard>
<Storyboard x:Name="FlipUp">
<DoubleAnimation Storyboard.TargetName="FlipTransform"
Storyboard.TargetProperty="Angle"
From="180" To="0" Duration="0:0:0.2"/>
</Storyboard>
</Image.Resources>
</Image>
<Image x:Name="SpinningBall" Source="/sdkRSSReaderCS;component/images/spinning_ball.png" Width="36" Height="36">
<Image.RenderTransform>
<RotateTransform x:Name="SpinTransform" CenterX="18" CenterY="18"/>
</Image.RenderTransform>
<Image.Resources>
<Storyboard x:Name="Spin">
<DoubleAnimation Storyboard.TargetName="SpinTransform"
Storyboard.TargetProperty="Angle"
From="0" To="360" Duration="0:0:1"
RepeatBehavior="Forever"/>
</Storyboard>
</Image.Resources>
</Image>
</Grid>
<TextBlock x:Name="TextBlock" Margin="10,0,0,0"
VerticalAlignment="Center" FontSize="26"
Style="{StaticResource PhoneTextExtraLargeStyle}"
Foreground="{StaticResource PhoneAccentBrush}" />
</StackPanel>
</Grid>
</UserControl>
Cs代码:
public partial class LoadingBox : UserControl
{
private string arrow;
public static readonly DependencyProperty BusyProperty = DependencyProperty.Register("Busy", typeof(bool), typeof(LoadingBox), new PropertyMetadata(false));
public LoadingBox()
{
InitializeComponent();
}
// Properties
public string Arrow
{
get
{
return this.arrow;
}
set
{
if (this.arrow == null)
{
if (value == "Invisible")
this.PulldownArrow.Visibility = Visibility.Collapsed;
else if (value == "Up")
{
this.FlipTransform.Angle = 0.0;
this.PulldownArrow.Visibility = Visibility.Visible;
}
else if (value == "Down")
{
this.FlipTransform.Angle = 180.0;
this.PulldownArrow.Visibility = Visibility.Visible;
}
}
else if (value == "Invisible")
this.PulldownArrow.Visibility = Visibility.Collapsed;
else if (value == "Up")
{
if (this.arrow == "Invisible")
{
this.FlipTransform.Angle = 0.0;
this.PulldownArrow.Visibility = Visibility.Visible;
}
else if (this.arrow == "Down") this.FlipUp.Begin();
}
else if (value == "Down")
{
if (this.arrow == "Invisible")
{
this.FlipTransform.Angle = 180.0;
this.PulldownArrow.Visibility = Visibility.Visible;
}
else if (this.arrow == "Up") this.FlipDown.Begin();
}
this.arrow = value;
}
}
public bool Busy
{
get
{
return (bool)base.GetValue(BusyProperty);
}
set
{
base.SetValue(BusyProperty, value);
if (value)
{
this.Arrow = "Invisible";
this.SpinningBall.Visibility = Visibility.Visible;
this.Spin.Begin();
}
else
{
this.SpinningBall.Visibility = Visibility.Collapsed;
this.Spin.Stop();
}
}
}
public string Text
{
get
{
return this.TextBlock.Text;
}
set
{
this.TextBlock.Text = value;
}
}
}
{
private string arrow;
public static readonly DependencyProperty BusyProperty = DependencyProperty.Register("Busy", typeof(bool), typeof(LoadingBox), new PropertyMetadata(false));
public LoadingBox()
{
InitializeComponent();
}
// Properties
public string Arrow
{
get
{
return this.arrow;
}
set
{
if (this.arrow == null)
{
if (value == "Invisible")
this.PulldownArrow.Visibility = Visibility.Collapsed;
else if (value == "Up")
{
this.FlipTransform.Angle = 0.0;
this.PulldownArrow.Visibility = Visibility.Visible;
}
else if (value == "Down")
{
this.FlipTransform.Angle = 180.0;
this.PulldownArrow.Visibility = Visibility.Visible;
}
}
else if (value == "Invisible")
this.PulldownArrow.Visibility = Visibility.Collapsed;
else if (value == "Up")
{
if (this.arrow == "Invisible")
{
this.FlipTransform.Angle = 0.0;
this.PulldownArrow.Visibility = Visibility.Visible;
}
else if (this.arrow == "Down") this.FlipUp.Begin();
}
else if (value == "Down")
{
if (this.arrow == "Invisible")
{
this.FlipTransform.Angle = 180.0;
this.PulldownArrow.Visibility = Visibility.Visible;
}
else if (this.arrow == "Up") this.FlipDown.Begin();
}
this.arrow = value;
}
}
public bool Busy
{
get
{
return (bool)base.GetValue(BusyProperty);
}
set
{
base.SetValue(BusyProperty, value);
if (value)
{
this.Arrow = "Invisible";
this.SpinningBall.Visibility = Visibility.Visible;
this.Spin.Begin();
}
else
{
this.SpinningBall.Visibility = Visibility.Collapsed;
this.Spin.Stop();
}
}
}
public string Text
{
get
{
return this.TextBlock.Text;
}
set
{
this.TextBlock.Text = value;
}
}
}
下面是在引用的页面中的计算代码(里面的偏移量需要再具体引用的地方修改来适应相应的窗体和动作幅度):
#region ScrollView
private void NewsScrollViewer_Loaded(object sender, RoutedEventArgs e)
{
this.newsScrollViewer = sender as ScrollViewer;
}
private void ScrollViewer_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
{
this.actualOffset = this.startOffset + this.startPoint - e.ManipulationOrigin.Y;
if (this.actualOffset < -100 && !headLoadingBox.Busy)
{
Update();
}
if (this.actualOffset + 250 > this.newsScrollViewer.ScrollableHeight && !tailLoadingBox.Busy)
{
NextPage();
}
}
private void ScrollViewer_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
{
this.startOffset = this.newsScrollViewer.VerticalOffset;
this.startPoint = e.ManipulationOrigin.Y;
}
private void ScrollViewer_MouseEnter(object sender, MouseEventArgs e)
{
//this.startRelativePoint = e.GetPosition(this.TopPlaceholder).Y;
}
private void ScrollViewer_MouseMove(object sender, MouseEventArgs e)
{
this.actualOffset = this.startOffset + this.startRelativePoint - e.GetPosition(this.TopPlaceholder).Y;
if (actualOffset < -100)
{
this.headLoadingBox.Arrow = "Up";
this.headLoadingBox.Text = "松开就可以更新!";
}
if (this.actualOffset + 250 > this.newsScrollViewer.ScrollableHeight && !tailLoadingBox.Busy)
{
this.tailLoadingBox.Arrow = "Down";
this.tailLoadingBox.Text = "松开就可以更新!";
}
}
private void NewsScrollViewer_Loaded(object sender, RoutedEventArgs e)
{
this.newsScrollViewer = sender as ScrollViewer;
}
private void ScrollViewer_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
{
this.actualOffset = this.startOffset + this.startPoint - e.ManipulationOrigin.Y;
if (this.actualOffset < -100 && !headLoadingBox.Busy)
{
Update();
}
if (this.actualOffset + 250 > this.newsScrollViewer.ScrollableHeight && !tailLoadingBox.Busy)
{
NextPage();
}
}
private void ScrollViewer_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
{
this.startOffset = this.newsScrollViewer.VerticalOffset;
this.startPoint = e.ManipulationOrigin.Y;
}
private void ScrollViewer_MouseEnter(object sender, MouseEventArgs e)
{
//this.startRelativePoint = e.GetPosition(this.TopPlaceholder).Y;
}
private void ScrollViewer_MouseMove(object sender, MouseEventArgs e)
{
this.actualOffset = this.startOffset + this.startRelativePoint - e.GetPosition(this.TopPlaceholder).Y;
if (actualOffset < -100)
{
this.headLoadingBox.Arrow = "Up";
this.headLoadingBox.Text = "松开就可以更新!";
}
if (this.actualOffset + 250 > this.newsScrollViewer.ScrollableHeight && !tailLoadingBox.Busy)
{
this.tailLoadingBox.Arrow = "Down";
this.tailLoadingBox.Text = "松开就可以更新!";
}
}
有不明白的问题请留言,需要代码的请留邮箱。
作者:today4king
出处:https://www.cnblogs.com/jinzhao/archive/2011/12/23/2299887.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
分类:
学习笔记
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
2008-12-23 《Asp.Net 2.0 揭秘》读书笔记(一)
2008-12-23 gmail的相关参数
2008-12-23 奋发、奋发、奋发