WPF如何实现类似iPhone界面切换的效果(转载)
2013-07-16 22:09
761 查看
WPF如何实现类似iPhone界面切换的效果 (version .1)
转自:http://blog.csdn.net/fallincloud/article/details/6968764在论坛上见到有人提出了这个问题(WPF实现点击横向切换界面)
我简单地做了个Sample。
效果图1:
效果图2:
设计思路
将这多个界面放入一个Orientation为Horizontal的StackPanel当中,点击Next时,里面所有控件执行TranslteTransform动画。实现
xaml
[html] view plaincopy<Window x:Class="WPFNavigation.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="400">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal"
x:Name="NavigationPanel"
Height="300"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType={x:Type Window}}, Path=ActualWidth }"
Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type StackPanel}}, Path=ActualHeight}"
Background="Blue" >
<TextBlock FontSize="36">Page1</TextBlock>
</Grid>
<Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType={x:Type Window}}, Path=ActualWidth }"
Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type StackPanel}}, Path=ActualHeight}"
Background="Violet">
<TextBlock FontSize="36">Page2</TextBlock>
</Grid>
<Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType={x:Type Window}}, Path=ActualWidth }"
Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type StackPanel}}, Path=ActualHeight}"
Background="Purple" >
<TextBlock FontSize="36">Page3</TextBlock>
</Grid>
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Horizontal" >
<Button Content="Previous" x:Name="ButtonPreviousPage" Click="ButtonPreviousPage_Click"></Button>
<Button Content="Next" x:Name="ButtonNextPage" Click="ButtonNextPage_Click"></Button>
</StackPanel>
</Grid>
</Window>
cs中
[csharp] view plaincopy/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private static readonly double COUNT_PAGE = 3;
private TranslateTransform NavigationPanelTranslateTransform;
public MainWindow()
{
InitializeComponent();
NavigationPanelTranslateTransform = new TranslateTransform();
this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
foreach (FrameworkElement fe in NavigationPanel.Children)
{
fe.RenderTransform = NavigationPanelTranslateTransform;
}
DeterminButtonStates();
}
private void DeterminButtonStates()
{
double currentTranX = NavigationPanelTranslateTransform.X;
if (currentTranX >= 0)
{
ButtonPreviousPage.IsEnabled = false;
}
else if (currentTranX <= -(COUNT_PAGE - 1) * this.ActualWidth)
{
ButtonNextPage.IsEnabled = false;
}
else
{
ButtonPreviousPage.IsEnabled = true;
ButtonNextPage.IsEnabled = true;
}
}
private void ButtonPreviousPage_Click(object sender, RoutedEventArgs e)
{
double currentTranX = NavigationPanelTranslateTransform.X;
DoubleAnimation da = new DoubleAnimation(currentTranX, currentTranX+this.ActualWidth, TimeSpan.FromMilliseconds(250));
da.Completed += (o1, e1) =>
{
DeterminButtonStates();
};
NavigationPanelTranslateTransform.BeginAnimation(TranslateTransform.XProperty, da);
}
private void ButtonNextPage_Click(object sender, RoutedEventArgs e)
{
double currentTranX = NavigationPanelTranslateTransform.X;
DoubleAnimation da = new DoubleAnimation(currentTranX, currentTranX - this.ActualWidth, TimeSpan.FromMilliseconds(250));
da.Completed += (o1, e1) =>
{
DeterminButtonStates();
};
NavigationPanelTranslateTransform.BeginAnimation(TranslateTransform.XProperty, da);
}
}
[b]WPF如何实现类似iPhone界面切换的效果 (version .2)[/b]
转自:http://blog.csdn.net/fallincloud/article/details/6969329
前面写了篇WPF如何实现类似iPhone界面切换的效果 (version .1)
现在又花了点时间重构了下,将动画的效果和Previous和Next这两个按钮的状态控制都封装了起来,效果依然和前面一样
不过重用性高了许多。使用方法如下:
XAML:
[html] view plaincopy<Window x:Class="WPFNavigation.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFNavigation"
Title="MainWindow" Height="350" Width="400">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<local:NavigationPanel Orientation="Horizontal"
x:Name="NavigationPanel"
Height="300"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType={x:Type Window}}, Path=ActualWidth }"
Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type local:NavigationPanel}}, Path=ActualHeight}"
Background="Blue" >
<TextBlock FontSize="36">Page1</TextBlock>
</Grid>
<Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType={x:Type Window}}, Path=ActualWidth }"
Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type local:NavigationPanel}}, Path=ActualHeight}"
Background="Violet">
<TextBlock FontSize="36">Page2</TextBlock>
</Grid>
<Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType={x:Type Window}}, Path=ActualWidth }"
Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type local:NavigationPanel}}, Path=ActualHeight}"
Background="Purple" >
<TextBlock FontSize="36">Page3</TextBlock>
</Grid>
</local:NavigationPanel>
<StackPanel Grid.Row="1" Orientation="Horizontal" >
<Button Content="Previous" x:Name="ButtonPreviousPage"
IsEnabled="{Binding ElementName=NavigationPanel, Path=PreviousIsValid, Mode=OneWay}"
Click="ButtonPreviousPage_Click"></Button>
<Button Content="Next" x:Name="ButtonNextPage" Click="ButtonNextPage_Click"
IsEnabled="{Binding ElementName=NavigationPanel, Path=NextIsValid, Mode=OneWay}"></Button>
</StackPanel>
</Grid>
</Window>
C#:
[csharp] view plaincopy
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ButtonPreviousPage_Click(object sender, RoutedEventArgs e)
{
NavigationPanel.Previous();
}
private void ButtonNextPage_Click(object sender, RoutedEventArgs e)
{
NavigationPanel.Next();
}
}
以上是用法,封装的NavigationPanel设计如下:
具体实现如下:
[csharp] view plaincopy
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
namespace WPFNavigation
{
public class NavigationPanel : StackPanel
{
public event EventHandler AnimationComplte;
private static double COUNT_OF_PAGE;
private TranslateTransform NavigationPanelTranslateTransform;
private static readonly TimeSpan DURATION = TimeSpan.FromMilliseconds(250);
public NavigationPanel():base()
{
this.Orientation = Orientation.Horizontal;
NavigationPanelTranslateTransform = new TranslateTransform();
this.Loaded += new RoutedEventHandler(NavigationPanel_Loaded);
}
void NavigationPanel_Loaded(object sender, RoutedEventArgs e)
{
COUNT_OF_PAGE = this.Children.Count;
CurrentIndex = 0;
foreach (FrameworkElement fe in this.Children)
{
fe.RenderTransform = NavigationPanelTranslateTransform;
}
}
public void Next()
{
AnimationChildren(true);
}
public void Previous()
{
AnimationChildren(false);
}
private bool ValidateNext()
{
return CurrentIndex < (COUNT_OF_PAGE - 1) && CurrentIndex >= 0;
}
private bool ValidatePrevious()
{
return CurrentIndex <= (COUNT_OF_PAGE - 1) && CurrentIndex > 0;
}
private bool ValidateCurrentIndex()
{
if (CurrentIndex > -1 && CurrentIndex < this.Children.Count)
{
return true;
}
return false;
}
private void AnimationChildren(bool forward)
{
double currentTranX = NavigationPanelTranslateTransform.X;
double nextTranX = currentTranX;
if (forward)
{
if (ValidateCurrentIndex())
{
nextTranX -= (this.Children[CurrentIndex] as FrameworkElement).ActualWidth;
}
}
else
{
if (ValidateCurrentIndex())
{
nextTranX += (this.Children[CurrentIndex] as FrameworkElement).ActualWidth;
}
}
DoubleAnimation da = new DoubleAnimation(currentTranX, nextTranX, DURATION);
da.Completed += (o1, e1) =>
{
CurrentIndex += forward ? 1 : -1;
if (AnimationComplte != null)
{
AnimationComplte(this, e1);
}
};
NavigationPanelTranslateTransform.BeginAnimation(TranslateTransform.XProperty, da);
}
#region CurrentIndex
/// <summary>
/// The <see cref="CurrentIndex" /> dependency property's name.
/// </summary>
public const string CurrentIndexPropertyName = "CurrentIndex";
/// <summary>
/// Gets or sets the value of the <see cref="CurrentIndex" />
/// property. This is a dependency property.
/// </summary>
public int CurrentIndex
{
get
{
return (int)GetValue(CurrentIndexProperty);
}
set
{
SetValue(CurrentIndexProperty, value);
}
}
/// <summary>
/// Identifies the <see cref="CurrentIndex" /> dependency property.
/// </summary>
public static readonly DependencyProperty CurrentIndexProperty = DependencyProperty.Register(
CurrentIndexPropertyName,
typeof(int),
typeof(NavigationPanel),
new UIPropertyMetadata(-1, OnCurrentIndexChanged));
private static void OnCurrentIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as NavigationPanel).OnCurrentIndexChanged((int)e.OldValue, (int)e.NewValue);
}
protected virtual void OnCurrentIndexChanged(int oldIndex, int newIndex)
{
NextIsValid = ValidateNext();
PreviousIsValid = ValidatePrevious();
}
#endregion // CurrentIndex
#region NextIsValid
/// <summary>
/// The <see cref="NextIsValid" /> dependency property's name.
/// </summary>
public const string NextIsValidPropertyName = "NextIsValid";
/// <summary>
/// Gets or sets the value of the <see cref="NextIsValid" />
/// property. This is a dependency property.
/// </summary>
public bool NextIsValid
{
get
{
return (bool)GetValue(NextIsValidProperty);
}
set
{
SetValue(NextIsValidProperty, value);
}
}
/// <summary>
/// Identifies the <see cref="NextIsValid" /> dependency property.
/// </summary>
public static readonly DependencyProperty NextIsValidProperty = DependencyProperty.Register(
NextIsValidPropertyName,
typeof(bool),
typeof(NavigationPanel),
new UIPropertyMetadata(false));
#endregion // NextIsValid
#region PreviousIsValid
/// <summary>
/// The <see cref="PreviousIsValid" /> dependency property's name.
/// </summary>
public const string PreviousIsValidPropertyName = "PreviousIsValid";
/// <summary>
/// Gets or sets the value of the <see cref="PreviousIsValid" />
/// property. This is a dependency property.
/// </summary>
public bool PreviousIsValid
{
get
{
return (bool)GetValue(PreviousIsValidProperty);
}
set
{
SetValue(PreviousIsValidProperty, value);
}
}
/// <summary>
/// Identifies the <see cref="PreviousIsValid" /> dependency property.
/// </summary>
public static readonly DependencyProperty PreviousIsValidProperty = DependencyProperty.Register(
PreviousIsValidPropertyName,
typeof(bool),
typeof(NavigationPanel),
new UIPropertyMetadata(false));
#endregion // PreviousIsValid
}
}
相关文章推荐
- 【请教问题】kanzi如何实现类似安卓手机桌面滑动切换界面效果?
- WPF好看的进度条实现浅谈(效果有点类似VS2012安装界面)
- ajax实例:如何使用json+ajax的方法实现类似前端特效tab切换效果
- 转载 37个Ajax和CSS实现的Tab选项卡切换效果界面
- WPF—QQ界面(二):QQ状态切换效果的实现
- Android应用中使用ViewPager实现类似QQ的界面切换效果
- WPF如何实现一款类似360安全卫士界面的程序?(共享源码!)
- 37个Ajax和CSS实现的Tab选项卡切换效果界面【转载】
- 如何实现类似锚链接的导航联动效果
- Android中实现仿微信界面切换平滑滑动效果
- Android实现通用的ActivityGroup(效果类似Android微博客户端主界面),强烈建议不要再使用TabActivity
- 如何在iOS 7中设置barTintColor实现类似网易和 Facebook 的 navigationBar 效果
- iOS开发之实现图片自动切换(类似android画廊效果)
- 如何使用TransitionDrawable实现背景切换渐变效果
- 【axure手机原型】Axure实现iPhone推动切换效果
- jQuery实现类似滑动门切换效果的层切换
- 37个Ajax和CSS实现的Tab选项卡切换效果界面
- iOS开发_iphone开发_iphone界面如何实现下拉列表
- iphone界面如何实现下拉列表2
- Android 实现多页界面左右滑动切换效果之入门+进阶 (ViewPager+PagerAdapter)