在 WP8 上更改按钮边框颜色时出现延迟

Posted

技术标签:

【中文标题】在 WP8 上更改按钮边框颜色时出现延迟【英文标题】:Lag when changing color of button border on WP8 【发布时间】:2014-05-25 16:33:29 【问题描述】:

我在一堆按钮上移动一个对象,当这个对象在一个按钮上时,我改变了边框的颜色。这没问题,我可以通过绑定、故事板或样式设置器/视觉状态来做到这一点。当我在我的模拟器上运行它时,它运行良好且流畅,但是当我在我的 Windows 手机上运行它时,当国家的边界​​发生变化时会有一个小的延迟。有没有办法避免这种情况?

1.代码示例

<Button x:Name="Button1" BorderThickness="0" BorderBrush="Transparent">
    <Button.Template>
        <ControlTemplate x:Name="Control">
            <Path x:Name="CountryUser" Style="StaticResource style_ColorButton" Data="Binding UserView.buttonData" Fill="StaticResource ButtonBackground">
                <Path.Resources>
                    <Storyboard x:Name="StoryBoard1">
                        <ColorAnimation Storyboard.TargetName="User" Storyboard.TargetProperty="(Stroke).(SolidColorBrush.Color)" To="Blue" Duration="0"/>
                    </Storyboard>
                </Path.Resources>
            </Path>
        </ControlTemplate> 
    </Button.Template>

和激活

foreach (UIElement x in ElementsAtPoint)

    f = x as FrameworkElement;
    if (f is Path)
    
        try
        
            h = f as Path;
            Storyboard sb = h.Resources["StoryBoard1"] as Storyboard;
            sb.Begin();
        
        catch
        
        

        break;
    

额外

在模拟器和实际设备之间想到的一个区别是触摸点的准确性。在模拟器中,您使用分辨率更高的鼠标。在您使用手指的设备上,精度要低得多,即毫米与像素。

我刚刚用一个简单的计数器和操作完成事件中的一个断点对此进行了测试。但在这两种情况下计数是相同的。而且它只尝试运行一次情节提要。

额外2

澄清我看到的滞后:

我正在拖动一个平滑地跟随手指的元素,当我进入一个新按钮时,我正在拖动的元素会停止一会儿。按钮颜色改变,元素再次移动。

当我在按钮改变颜色后返回时。当我在按钮之间移动时,元素会用我的手指平稳移动。

因此,故事板被激活时会有延迟,并且可以看出我拖动的元素无法跟随手指。

因此,我正在尝试寻找替代方法来更改手机上可能具有更好性能的颜色。因为它在模拟器上运行良好。

我在两种不同的 lumia 920 和一种 lumia 520 上进行了测试

2。代码示例

在 Shawn Kendrot 的帮助下使用 Visual State Manager,来自另一个问题:Using Dependency object for color animation WP8 复制如下:

<Style x:Key="ButtonStyle" TargetType="Button">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="BorderBrush" Value="StaticResource PhoneForegroundBrush"/>
    <Setter Property="Foreground" Value="StaticResource PhoneForegroundBrush"/>
    <Setter Property="BorderThickness" Value="StaticResource PhoneBorderThickness"/>
    <Setter Property="FontFamily" Value="StaticResource PhoneFontFamilySemiBold"/>
    <Setter Property="FontSize" Value="StaticResource PhoneFontSizeMedium"/>
    <Setter Property="Padding" Value="10,5,10,6"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Grid Background="Transparent">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal"/>
                            <VisualState x:Name="MouseOver">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="White"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="Orange"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Pressed">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="StaticResource PhoneButtonBasePressedForegroundBrush"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="StaticResource PhoneAccentBrush"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Disabled">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="StaticResource PhoneDisabledBrush"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ButtonBackground">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="StaticResource PhoneDisabledBrush"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Border x:Name="ButtonBackground" BorderBrush="TemplateBinding BorderBrush" BorderThickness="TemplateBinding BorderThickness" Background="TemplateBinding Background" CornerRadius="0" Margin="StaticResource PhoneTouchTargetOverhang">
                        <ContentControl x:Name="ContentContainer" ContentTemplate="TemplateBinding ContentTemplate" Content="TemplateBinding Content" Foreground="TemplateBinding Foreground" HorizontalContentAlignment="TemplateBinding HorizontalContentAlignment" Padding="TemplateBinding Padding" VerticalContentAlignment="TemplateBinding VerticalContentAlignment"/>
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

注意它有一个 MouseOver VisualState。然后分配样式并订阅事件处理程序

<Button Content="Drag over me" Style="StaticResource ButtonStyle"  MouseEnter="OnButtonMouseEnter" MouseLeave="OnButtonMouseLeave"/>

并在事件处理程序中改变视觉状态。

private void OnButtonMouseEnter(object sender, MouseEventArgs e)

    VisualStateManager.GoToState((Control)sender, "MouseOver", true);


private void OnButtonMouseLeave(object sender, MouseEventArgs e)

    VisualStateManager.GoToState((Control)sender, "Normal", true);

仍然有滞后,还有其他人有可以测试的解决方案吗?

额外

由于问题可能是低 fps,即当我想更改颜色时出现渲染问题,可以使用调度程序吗?

所以在我开始故事板的第一个代码示例中,我可以改为在视图中调用一个函数来利用调度程序?任何人都有这样做的想法,或者这是一个好主意吗?

感谢所有帮助,因为我不明白为什么我可以在屏幕上平滑移动对象但是当我想更改边框的颜色时,我可以看到它滞后:/

【问题讨论】:

如问题中所述,我尝试了许多解决方案但均未成功,并且共享按钮代码似乎不合适。 @AMR我的问题是针对可以使用什么方法来消除滞后。我查看了所有不同解决方案的内存使用情况,但没有任何实际影响。但是在模拟器上一切正常。 如果你不能提供代码,那么这个问题就不是 Stack Overflow 的话题了。该代码与本网站相关。 当您启动情节提要或类似的东西时是否触发了事件? @AMR 添加代码不是问题,如果相关的话。这里我添加了一个例子。我的问题不在于他们没有工作更多,而是他们落后了。所以我想知道人们在不将我的想法强加于他们的情况下可能会使用的方式。 @JTIM 这不是您的个人问答博客。当您在此处发布时,您正在创建其他人在遇到类似问题时可以参考的历史文档。需要您的确切代码的原因是可以识别和修复您的确切问题。两个人可能会遇到相同的问题,但一个人是因为他们设置了错误的属性,而另一个人正在使用已弃用的 DLL。如果没有您的确切代码,则无法做出这种区分,不仅无法修复,而且对未来的读者也无用 【参考方案1】:

我的应用中的动画存在性能问题,我经常通过在移动的元素上将 CacheMode 属性设置为 BitmapCache 来解决这些问题。

这个想法是,它指示框架对控件进行截图并将生成的位图存储在 GPU 的内存中,这样就不必在每一帧都重新绘制控件。

您可以查看这篇文章:CacheMode and why it matters 了解更多信息。

【讨论】:

是的,确实如此,我们已将其用于其他动画。也在这里尝试过,但这个问题没有成功。【参考方案2】:

运行附加到调试器时,您会获得哪些调试/性能信息?

让他们在 App 构造函数的末尾添加以下内容:

        // Show graphics profiling information while debugging.
        if (Debugger.IsAttached)
        
            // Display the current frame rate counters.
            Application.Current.Host.Settings.EnableFrameRateCounter = true;

            // Show the areas of the app that are being redrawn in each frame.
            //Application.Current.Host.Settings.EnableRedrawRegions = true;

            // Enable non-production analysis visualization mode,
            // which shows areas of a page that are handed off to GPU with a colored overlay.
            //Application.Current.Host.Settings.EnableCacheVisualization = true;

            // Prevent the screen from turning off while under the debugger by disabling
            // the application's idle detection.
            // Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run
            // and consume battery power when the user is not using the phone.
            PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
        

【讨论】:

它已启用,我有点不确定你想要什么数字。但是当滞后发生时,我有以下内容:030 030。我认为这是帧速率。只是移动项目时我也有同样的情况,因此似乎不是问题。最后一个数字是 01.4333,当滞后发生时下降到 01.4000。按顺序排列的数字是 030 030 022974 008 000 01.4333 这里有一篇关于 WP 帧率计数器的好帖子:jeff.wilcox.name/2010/07/counters 微软网站上应该也有官方的,但我现在找不到。在我的诺基亚 925 上,前两个数字都在 060 左右(这意味着渲染和 UI 线程上的 60 fps。如果这些数字下降(并变红),则可能是渲染问题。您的数字可能很低,因为低端硬件(?)其他性能指标(即来自 Visual Studio、调试菜单、“启动 Windows Phone 应用程序分析”)呢? 我的内存使用率很低,大约为 50 mb。我在上面测试过的设备是 920,它应该能够达到 60 fps。 Want issue可能是渲染问题的故障,它只在边框颜色变化期间发生。 我在我的问题中添加了使用 Dispatcher 的想法,因为你说我找到了这个链接,关于性能 [blogs.windows.com/windows_phone/b/wpdev/archive/2013/01/25/… 似乎有可能?

以上是关于在 WP8 上更改按钮边框颜色时出现延迟的主要内容,如果未能解决你的问题,请参考以下文章

如何更改圆形按钮上的边框颜色(Swift)

如何更改按钮的边框颜色并更改editText中下划线的颜色?

当我设置自定义边框或背景颜色时,为什么Firefox在选择箭头按钮上设置背景颜色?

在 Unity3D 中更改按钮的边框颜色

以另一种颜色更改选择选项时出现问题[重复]

在 Swift 3 中突出显示(或点击)按钮时如何更改 UIButton 边框颜色?