WPF如何实现类似iPhone界面切换的效果(转载)

WPF如何实现类似iPhone界面切换的效果 (version .1)

转自:http://blog.csdn.net/fallincloud/article/details/6968764

在论坛上见到有人提出了这个问题(WPF实现点击横向切换界面

我简单地做了个Sample。

效果图1:

WPF如何实现类似iPhone界面切换的效果(转载)

效果图2:

WPF如何实现类似iPhone界面切换的效果(转载)

设计思路

将这多个界面放入一个Orientation为Horizontal的StackPanel当中,点击Next时,里面所有控件执行TranslteTransform动画。

实现

xaml

  1. <Window x:Class="WPFNavigation.MainWindow"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. Title="MainWindow" Height="350" Width="400">
  5. <Grid>
  6. <Grid.RowDefinitions>
  7. <RowDefinition Height="*"></RowDefinition>
  8. <RowDefinition Height="Auto"></RowDefinition>
  9. </Grid.RowDefinitions>
  10. <StackPanel Orientation="Horizontal"
  11. x:Name="NavigationPanel"
  12. Height="300"
  13. HorizontalAlignment="Left"
  14. VerticalAlignment="Top">
  15. <Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType={x:Type Window}}, Path=ActualWidth }"
  16. Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type StackPanel}}, Path=ActualHeight}"
  17. Background="Blue" >
  18. <TextBlock FontSize="36">Page1</TextBlock>
  19. </Grid>
  20. <Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType={x:Type Window}}, Path=ActualWidth }"
  21. Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type StackPanel}}, Path=ActualHeight}"
  22. Background="Violet">
  23. <TextBlock FontSize="36">Page2</TextBlock>
  24. </Grid>
  25. <Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType={x:Type Window}}, Path=ActualWidth }"
  26. Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type StackPanel}}, Path=ActualHeight}"
  27. Background="Purple" >
  28. <TextBlock FontSize="36">Page3</TextBlock>
  29. </Grid>
  30. </StackPanel>
  31. <StackPanel Grid.Row="1"  Orientation="Horizontal" >
  32. <Button Content="Previous" x:Name="ButtonPreviousPage" Click="ButtonPreviousPage_Click"></Button>
  33. <Button Content="Next" x:Name="ButtonNextPage" Click="ButtonNextPage_Click"></Button>
  34. </StackPanel>
  35. </Grid>
  36. </Window>

cs中

    1. /// <summary>
    2. /// Interaction logic for MainWindow.xaml
    3. /// </summary>
    4. public partial class MainWindow : Window
    5. {
    6. private static readonly double COUNT_PAGE = 3;
    7. private TranslateTransform NavigationPanelTranslateTransform;
    8. public MainWindow()
    9. {
    10. InitializeComponent();
    11. NavigationPanelTranslateTransform = new TranslateTransform();
    12. this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
    13. }
    14. void MainWindow_Loaded(object sender, RoutedEventArgs e)
    15. {
    16. foreach (FrameworkElement fe in NavigationPanel.Children)
    17. {
    18. fe.RenderTransform = NavigationPanelTranslateTransform;
    19. }
    20. DeterminButtonStates();
    21. }
    22. private void DeterminButtonStates()
    23. {
    24. double currentTranX = NavigationPanelTranslateTransform.X;
    25. if (currentTranX >= 0)
    26. {
    27. ButtonPreviousPage.IsEnabled = false;
    28. }
    29. else if (currentTranX <= -(COUNT_PAGE - 1) * this.ActualWidth)
    30. {
    31. ButtonNextPage.IsEnabled = false;
    32. }
    33. else
    34. {
    35. ButtonPreviousPage.IsEnabled = true;
    36. ButtonNextPage.IsEnabled = true;
    37. }
    38. }
    39. private void ButtonPreviousPage_Click(object sender, RoutedEventArgs e)
    40. {
    41. double currentTranX = NavigationPanelTranslateTransform.X;
    42. DoubleAnimation da = new DoubleAnimation(currentTranX, currentTranX+this.ActualWidth, TimeSpan.FromMilliseconds(250));
    43. da.Completed += (o1, e1) =>
    44. {
    45. DeterminButtonStates();
    46. };
    47. NavigationPanelTranslateTransform.BeginAnimation(TranslateTransform.XProperty, da);
    48. }
    49. private void ButtonNextPage_Click(object sender, RoutedEventArgs e)
    50. {
    51. double currentTranX = NavigationPanelTranslateTransform.X;
    52. DoubleAnimation da = new DoubleAnimation(currentTranX, currentTranX - this.ActualWidth, TimeSpan.FromMilliseconds(250));
    53. da.Completed += (o1, e1) =>
    54. {
    55. DeterminButtonStates();
    56. };
    57. NavigationPanelTranslateTransform.BeginAnimation(TranslateTransform.XProperty, da);
    58. }
    59. }

WPF如何实现类似iPhone界面切换的效果 (version .2)

转自:http://blog.csdn.net/fallincloud/article/details/6969329

前面写了篇WPF如何实现类似iPhone界面切换的效果 (version .1)

现在又花了点时间重构了下,将动画的效果和Previous和Next这两个按钮的状态控制都封装了起来,效果依然和前面一样

不过重用性高了许多。使用方法如下:

XAML:

  1. <Window x:Class="WPFNavigation.MainWindow"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:local="clr-namespace:WPFNavigation"
  5. Title="MainWindow" Height="350" Width="400">
  6. <Grid>
  7. <Grid.RowDefinitions>
  8. <RowDefinition Height="*"></RowDefinition>
  9. <RowDefinition Height="Auto"></RowDefinition>
  10. </Grid.RowDefinitions>
  11. <local:NavigationPanel Orientation="Horizontal"
  12. x:Name="NavigationPanel"
  13. Height="300"
  14. HorizontalAlignment="Left"
  15. VerticalAlignment="Top">
  16. <Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType={x:Type Window}}, Path=ActualWidth }"
  17. Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type local:NavigationPanel}}, Path=ActualHeight}"
  18. Background="Blue" >
  19. <TextBlock FontSize="36">Page1</TextBlock>
  20. </Grid>
  21. <Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType={x:Type Window}}, Path=ActualWidth }"
  22. Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type local:NavigationPanel}}, Path=ActualHeight}"
  23. Background="Violet">
  24. <TextBlock FontSize="36">Page2</TextBlock>
  25. </Grid>
  26. <Grid Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType={x:Type Window}}, Path=ActualWidth }"
  27. Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type local:NavigationPanel}}, Path=ActualHeight}"
  28. Background="Purple" >
  29. <TextBlock FontSize="36">Page3</TextBlock>
  30. </Grid>
  31. </local:NavigationPanel>
  32. <StackPanel Grid.Row="1"  Orientation="Horizontal" >
  33. <Button Content="Previous" x:Name="ButtonPreviousPage"
  34. IsEnabled="{Binding ElementName=NavigationPanel, Path=PreviousIsValid, Mode=OneWay}"
  35. Click="ButtonPreviousPage_Click"></Button>
  36. <Button Content="Next" x:Name="ButtonNextPage" Click="ButtonNextPage_Click"
  37. IsEnabled="{Binding ElementName=NavigationPanel, Path=NextIsValid, Mode=OneWay}"></Button>
  38. </StackPanel>
  39. </Grid>
  40. </Window>

C#:

  1. /// <summary>
  2. /// Interaction logic for MainWindow.xaml
  3. /// </summary>
  4. public partial class MainWindow : Window
  5. {
  6. public MainWindow()
  7. {
  8. InitializeComponent();
  9. }
  10. private void ButtonPreviousPage_Click(object sender, RoutedEventArgs e)
  11. {
  12. NavigationPanel.Previous();
  13. }
  14. private void ButtonNextPage_Click(object sender, RoutedEventArgs e)
  15. {
  16. NavigationPanel.Next();
  17. }
  18. }

以上是用法,封装的NavigationPanel设计如下:

WPF如何实现类似iPhone界面切换的效果(转载)

具体实现如下:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Windows;
  6. using System.Windows.Controls;
  7. using System.Windows.Data;
  8. using System.Windows.Documents;
  9. using System.Windows.Input;
  10. using System.Windows.Media;
  11. using System.Windows.Media.Imaging;
  12. using System.Windows.Navigation;
  13. using System.Windows.Shapes;
  14. using System.Windows.Media.Animation;
  15. namespace WPFNavigation
  16. {
  17. public class NavigationPanel : StackPanel
  18. {
  19. public event EventHandler AnimationComplte;
  20. private static double COUNT_OF_PAGE;
  21. private TranslateTransform NavigationPanelTranslateTransform;
  22. private static readonly TimeSpan DURATION = TimeSpan.FromMilliseconds(250);
  23. public NavigationPanel():base()
  24. {
  25. this.Orientation = Orientation.Horizontal;
  26. NavigationPanelTranslateTransform = new TranslateTransform();
  27. this.Loaded += new RoutedEventHandler(NavigationPanel_Loaded);
  28. }
  29. void NavigationPanel_Loaded(object sender, RoutedEventArgs e)
  30. {
  31. COUNT_OF_PAGE = this.Children.Count;
  32. CurrentIndex = 0;
  33. foreach (FrameworkElement fe in this.Children)
  34. {
  35. fe.RenderTransform = NavigationPanelTranslateTransform;
  36. }
  37. }
  38. public void Next()
  39. {
  40. AnimationChildren(true);
  41. }
  42. public void Previous()
  43. {
  44. AnimationChildren(false);
  45. }
  46. private bool ValidateNext()
  47. {
  48. return CurrentIndex < (COUNT_OF_PAGE - 1) && CurrentIndex >= 0;
  49. }
  50. private bool ValidatePrevious()
  51. {
  52. return CurrentIndex <= (COUNT_OF_PAGE - 1) && CurrentIndex > 0;
  53. }
  54. private bool ValidateCurrentIndex()
  55. {
  56. if (CurrentIndex > -1 && CurrentIndex < this.Children.Count)
  57. {
  58. return true;
  59. }
  60. return false;
  61. }
  62. private  void AnimationChildren(bool forward)
  63. {
  64. double currentTranX = NavigationPanelTranslateTransform.X;
  65. double nextTranX = currentTranX;
  66. if (forward)
  67. {
  68. if (ValidateCurrentIndex())
  69. {
  70. nextTranX -= (this.Children[CurrentIndex] as FrameworkElement).ActualWidth;
  71. }
  72. }
  73. else
  74. {
  75. if (ValidateCurrentIndex())
  76. {
  77. nextTranX += (this.Children[CurrentIndex] as FrameworkElement).ActualWidth;
  78. }
  79. }
  80. DoubleAnimation da = new DoubleAnimation(currentTranX, nextTranX, DURATION);
  81. da.Completed += (o1, e1) =>
  82. {
  83. CurrentIndex += forward ? 1 : -1;
  84. if (AnimationComplte != null)
  85. {
  86. AnimationComplte(this, e1);
  87. }
  88. };
  89. NavigationPanelTranslateTransform.BeginAnimation(TranslateTransform.XProperty, da);
  90. }
  91. #region CurrentIndex
  92. /// <summary>
  93. /// The <see cref="CurrentIndex" /> dependency property's name.
  94. /// </summary>
  95. public const string CurrentIndexPropertyName = "CurrentIndex";
  96. /// <summary>
  97. /// Gets or sets the value of the <see cref="CurrentIndex" />
  98. /// property. This is a dependency property.
  99. /// </summary>
  100. public int CurrentIndex
  101. {
  102. get
  103. {
  104. return (int)GetValue(CurrentIndexProperty);
  105. }
  106. set
  107. {
  108. SetValue(CurrentIndexProperty, value);
  109. }
  110. }
  111. /// <summary>
  112. /// Identifies the <see cref="CurrentIndex" /> dependency property.
  113. /// </summary>
  114. public static readonly DependencyProperty CurrentIndexProperty = DependencyProperty.Register(
  115. CurrentIndexPropertyName,
  116. typeof(int),
  117. typeof(NavigationPanel),
  118. new UIPropertyMetadata(-1, OnCurrentIndexChanged));
  119. private static void OnCurrentIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  120. {
  121. (d as NavigationPanel).OnCurrentIndexChanged((int)e.OldValue, (int)e.NewValue);
  122. }
  123. protected virtual void OnCurrentIndexChanged(int oldIndex, int newIndex)
  124. {
  125. NextIsValid = ValidateNext();
  126. PreviousIsValid = ValidatePrevious();
  127. }
  128. #endregion // CurrentIndex
  129. #region NextIsValid
  130. /// <summary>
  131. /// The <see cref="NextIsValid" /> dependency property's name.
  132. /// </summary>
  133. public const string NextIsValidPropertyName = "NextIsValid";
  134. /// <summary>
  135. /// Gets or sets the value of the <see cref="NextIsValid" />
  136. /// property. This is a dependency property.
  137. /// </summary>
  138. public bool NextIsValid
  139. {
  140. get
  141. {
  142. return (bool)GetValue(NextIsValidProperty);
  143. }
  144. set
  145. {
  146. SetValue(NextIsValidProperty, value);
  147. }
  148. }
  149. /// <summary>
  150. /// Identifies the <see cref="NextIsValid" /> dependency property.
  151. /// </summary>
  152. public static readonly DependencyProperty NextIsValidProperty = DependencyProperty.Register(
  153. NextIsValidPropertyName,
  154. typeof(bool),
  155. typeof(NavigationPanel),
  156. new UIPropertyMetadata(false));
  157. #endregion // NextIsValid
  158. #region PreviousIsValid
  159. /// <summary>
  160. /// The <see cref="PreviousIsValid" /> dependency property's name.
  161. /// </summary>
  162. public const string PreviousIsValidPropertyName = "PreviousIsValid";
  163. /// <summary>
  164. /// Gets or sets the value of the <see cref="PreviousIsValid" />
  165. /// property. This is a dependency property.
  166. /// </summary>
  167. public bool PreviousIsValid
  168. {
  169. get
  170. {
  171. return (bool)GetValue(PreviousIsValidProperty);
  172. }
  173. set
  174. {
  175. SetValue(PreviousIsValidProperty, value);
  176. }
  177. }
  178. /// <summary>
  179. /// Identifies the <see cref="PreviousIsValid" /> dependency property.
  180. /// </summary>
  181. public static readonly DependencyProperty PreviousIsValidProperty = DependencyProperty.Register(
  182. PreviousIsValidPropertyName,
  183. typeof(bool),
  184. typeof(NavigationPanel),
  185. new UIPropertyMetadata(false));
  186. #endregion // PreviousIsValid
  187. }
  188. }
上一篇:图片压缩上传 Android


下一篇:C++设计模式-Bridge桥接模式