33

我正在寻找有关在 iPhone 上创建幻灯片 ON/OFF 开关的 WPF 教程。

这是一个示例(“发送所有流量”选项)https://secure-tunnel.com/support/software_setup/iphone/images/iphone_vpn_settings.jpg

4

6 回答 6

92

我还没有看到关于这个确切问题的教程,但我想你可以从启动 Expression Blend 并在其上放置一个 CheckBox 开始。然后选择复选框,进入主菜单 - 对象 -> 编辑样式 -> 编辑副本

这将使 Blend 生成 CheckBox 的默认样式,因此您可以对其进行修改。看看那里的事情是如何运作的,你将能够取得一些成果。

基本上(除了颜色和画笔),您需要查看与 IsChecked 属性挂钩的触发器。例如,当 IsChecked 为 True 时,您将矩形移动到一侧,显示 ON 字并隐藏 OFF 字。要对此进行动画处理,您只需添加触发器输入和输出动画。

UPD:我花了 10-15 分钟来混合制作“原型”:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="CheckBoxIPhone.Window1"
    x:Name="Window"
    Title="Window1"
    Width="320" 
    Height="240" 
    FontFamily="Segoe UI" 
    FontSize="20" 
    WindowStartupLocation="CenterScreen"
    >

    <Window.Resources>
        <Style x:Key="CheckBoxStyle1" TargetType="{x:Type CheckBox}">
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
            <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type CheckBox}">
                        <ControlTemplate.Resources>
                            <Storyboard x:Key="OnChecking">
                                <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
                                    <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="25"/>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                            <Storyboard x:Key="OnUnchecking">
                                <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
                                    <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0"/>
                                </DoubleAnimationUsingKeyFrames>
                                <ThicknessAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(FrameworkElement.Margin)">
                                    <SplineThicknessKeyFrame KeyTime="00:00:00.3000000" Value="1,1,1,1"/>
                                </ThicknessAnimationUsingKeyFrames>
                            </Storyboard>
                        </ControlTemplate.Resources>

                        <DockPanel x:Name="dockPanel">
                            <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" ContentTemplate="{TemplateBinding ContentTemplate}" RecognizesAccessKey="True" VerticalAlignment="Center"/>
                            <Grid Margin="5,5,0,5" Width="50" Background="#FFC0CCD9">
                                <TextBlock Text="ON" TextWrapping="Wrap" FontWeight="Bold" FontSize="12" HorizontalAlignment="Right" Margin="0,0,3,0"/>
                                <TextBlock HorizontalAlignment="Left" Margin="2,0,0,0" FontSize="12" FontWeight="Bold" Text="OFF" TextWrapping="Wrap"/>
                                <Border HorizontalAlignment="Left" x:Name="slider" Width="23" BorderThickness="1,1,1,1" CornerRadius="3,3,3,3" RenderTransformOrigin="0.5,0.5" Margin="1,1,1,1">
                                    <Border.RenderTransform>
                                            <TransformGroup>
                                                <ScaleTransform ScaleX="1" ScaleY="1"/>
                                                <SkewTransform AngleX="0" AngleY="0"/>
                                                <RotateTransform Angle="0"/>
                                                <TranslateTransform X="0" Y="0"/>
                                            </TransformGroup>
                                        </Border.RenderTransform>
                                        <Border.BorderBrush>
                                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                                <GradientStop Color="#FFFFFFFF" Offset="0"/>
                                                <GradientStop Color="#FF4490FF" Offset="1"/>
                                            </LinearGradientBrush>
                                        </Border.BorderBrush>
                                        <Border.Background>
                                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                                <GradientStop Color="#FF8AB4FF" Offset="1"/>
                                                <GradientStop Color="#FFD1E2FF" Offset="0"/>
                                            </LinearGradientBrush>
                                        </Border.Background>
                                    </Border>
                                </Grid>
                        </DockPanel>

                        <ControlTemplate.Triggers>
                            <Trigger Property="IsChecked" Value="True">
                                <Trigger.ExitActions>
                                    <BeginStoryboard Storyboard="{StaticResource OnUnchecking}" x:Name="OnUnchecking_BeginStoryboard"/>
                                </Trigger.ExitActions>
                                <Trigger.EnterActions>
                                    <BeginStoryboard Storyboard="{StaticResource OnChecking}" x:Name="OnChecking_BeginStoryboard"/>
                                </Trigger.EnterActions>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

    <Grid x:Name="LayoutRoot">
        <CheckBox HorizontalAlignment="Center" Style="{DynamicResource CheckBoxStyle1}" VerticalAlignment="Center" Content="CheckBox"/>
    </Grid>
</Window>

如果您有兴趣,我还建议您阅读 WPF 中的样式和模板。

于 2009-05-14T21:24:16.643 回答
58

我根据 arcaut 的帖子创建了一些橙色和蓝色的样式。

截屏: 点击

我希望我的风格更接近 iOS 设备的 On/Off Switch 风格。这种风格的一个区别是,滑动动画只滑动开关而不是下面的指示器。也许如果我能找到一些时间,我会这样修改它。在那之前,我想分享我的结果。它并不完美,但这是代码。

<LinearGradientBrush x:Key="CheckedBlue" StartPoint="0,0" EndPoint="0,1">
  <GradientStop Color="#FF285AB3" Offset="0" />
  <GradientStop Color="#FF4184EC" Offset="0.5" />
  <GradientStop Color="#FF558BED" Offset="0.5" />
  <GradientStop Color="#FF7DACF0" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="CheckedOrange" StartPoint="0,0" EndPoint="0,1">
  <GradientStop Color="#FFCA6A13" Offset="0" />
  <GradientStop Color="#FFF67D0C" Offset="0.2" />
  <GradientStop Color="#FFFE7F0C" Offset="0.2" />
  <GradientStop Color="#FFFA8E12" Offset="0.5" />
  <GradientStop Color="#FFFF981D" Offset="0.5" />
  <GradientStop Color="#FFFCBC5A" Offset="1" />
</LinearGradientBrush>
<SolidColorBrush x:Key="CheckedOrangeBorder" Color="#FF8E4A1B" />
<SolidColorBrush x:Key="CheckedBlueBorder" Color="#FF143874" />
<Style x:Key="OrangeSwitchStyle" TargetType="{x:Type CheckBox}">
  <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
  <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type CheckBox}">
        <ControlTemplate.Resources>
          <Storyboard x:Key="OnChecking">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
              <SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="53" />
            </DoubleAnimationUsingKeyFrames>
          </Storyboard>
          <Storyboard x:Key="OnUnchecking">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
              <SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0" />
            </DoubleAnimationUsingKeyFrames>
          </Storyboard>
        </ControlTemplate.Resources>
        <DockPanel x:Name="dockPanel">
          <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" ContentTemplate="{TemplateBinding ContentTemplate}" RecognizesAccessKey="True" VerticalAlignment="Center" />
          <Grid>
            <Border x:Name="BackgroundBorder" BorderBrush="#FF939393" BorderThickness="1" CornerRadius="3" Height="27" Width="94">
              <Border.Background>
                <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                  <GradientStop Color="#FFB5B5B5" Offset="0" />
                  <GradientStop Color="#FFDEDEDE" Offset="0.1" />
                  <GradientStop Color="#FFEEEEEE" Offset="0.5" />
                  <GradientStop Color="#FFFAFAFA" Offset="0.5" />
                  <GradientStop Color="#FFFEFEFE" Offset="1" />
                </LinearGradientBrush>
              </Border.Background>
              <Grid>
                <Grid.ColumnDefinitions>
                  <ColumnDefinition /><ColumnDefinition />
                </Grid.ColumnDefinitions>
                <Ellipse x:Name="Off" Width="14" Height="14" Stroke="#FF7A7A7A" StrokeThickness="2" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" />
                <Line x:Name="On" X1="0" Y1="0" X2="0" Y2="14" Stroke="#FF7A7A7A" StrokeThickness="2" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" />
              </Grid>
            </Border>
            <Border BorderBrush="#FF939393" HorizontalAlignment="Left" x:Name="slider" Width="41" Height="27" BorderThickness="1" CornerRadius="3" RenderTransformOrigin="0.5,0.5" Margin="0">
              <Border.RenderTransform>
                <TransformGroup>
                  <ScaleTransform ScaleX="1" ScaleY="1" />
                  <SkewTransform AngleX="0" AngleY="0" />
                  <RotateTransform Angle="0" />
                  <TranslateTransform X="0" Y="0" />
                </TransformGroup>
              </Border.RenderTransform>
              <Border.Background>
                <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
                  <GradientStop Color="#FFF0F0F0" Offset="0" />
                  <GradientStop Color="#FFCDCDCD" Offset="0.1" />
                  <GradientStop Color="#FFFBFBFB" Offset="1" />
                </LinearGradientBrush>
              </Border.Background>
            </Border>
          </Grid>
        </DockPanel>
        <ControlTemplate.Triggers>
          <Trigger Property="IsChecked" Value="True">
            <Trigger.ExitActions>
              <BeginStoryboard Storyboard="{StaticResource OnUnchecking}" x:Name="OnUnchecking_BeginStoryboard" />
            </Trigger.ExitActions>
            <Trigger.EnterActions>
              <BeginStoryboard Storyboard="{StaticResource OnChecking}" x:Name="OnChecking_BeginStoryboard" />
            </Trigger.EnterActions>
            <Setter TargetName="On" Property="Stroke" Value="White" />
            <Setter TargetName="Off" Property="Stroke" Value="White" />
            <!-- Change Orange or Blue color here -->
            <Setter TargetName="BackgroundBorder" Property="Background" Value="{StaticResource CheckedOrange}" />
            <Setter TargetName="BackgroundBorder" Property="BorderBrush" Value="{StaticResource CheckedOrangeBorder}" />
          </Trigger>
          <Trigger Property="IsEnabled" Value="False">
            <!-- ToDo: Add Style for Isenabled == False -->
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>
于 2011-03-18T08:13:25.980 回答
12

一些开源的切换开关:

于 2015-05-20T07:00:54.323 回答
3

我刚刚发布了一个关于此的条目,它提供了适当的滑动动作、完全可配置性并且不需要固定大小(因为我在网上找不到任何提供类似解决方案的东西而感到恼火)。

你可以在这里找到它:http: //itsallaboutthexaml.blogspot.com/2012/01/variables-in-animation.html

知道回答这个问题已经很晚了,但希望它对未来的任何人都有帮助。

于 2012-01-02T22:00:36.460 回答
0

我喜欢arconaut的漂亮原型,我添加了一些代码来使边框变圆。

您必须从 Grid 声明中删除“Background”属性,并在 Grid 声明和第一个 TextBlock 声明之间添加以下行:

<Border
    x:Name="back"
    CornerRadius="3,3,3,3"
    BorderThickness="1"
    BorderBrush="#FFC0CCD9"
    >
    <Rectangle Fill="#FFC0CCD9"/>
</Border>
于 2010-10-20T13:23:22.087 回答
0

好吧,我开始着手完成同样的任务,但这些示例与生产代码相比有点不足。例如,如果您将文本放入控件(如 On/Off 或文本的本地化版本)会发生什么情况,答案是您必须定义控件的大小,因为在呈现控件后您无法修改动画或模板触发器。这为您提供了一种万能的解决方案,该解决方案不适用于本地化文本。

我的解决方案是使用控件的 Loaded 事件和 FrameworkElementFactory 类为控件动态创建模板。我不得不说这很复杂,但可以实现。简单地说,在您的代码中,按照描述创建一个模板,为您的开/关文本设置依赖属性,使用文本度量来确定控件的宽度、高度和动画值。

很抱歉,我无法发布解决方案,因为它现在属于 Avanquest。:(

在 SystemSuite 和 Fix-It 12 中查找它。

于 2012-05-01T03:02:39.310 回答