簡體   English   中英

以編程方式使用計時器滾動ScrollViewer變得不穩定

[英]Programmatically scrolling a ScrollViewer with a timer becomes jerky

ScrollViewer動畫ScrollViewer似乎是一項常見任務。 我使用計時器實現它,類似於此處的方法。 這種方法效果很好,非常流暢,看起來很完美。

但是,現在我的ScrollViewer包含的對象的復雜性和數量增加了,動畫看起來非常不穩定。 我發現這很奇怪,因為如果我手動滾動它會正常工作。

    public void ShiftLeft(int speed = 11)
    {
        CustomTimer timer = new CustomTimer(); //DispatchTimer with "life"
        timer.Interval = new TimeSpan(0, 0, 0, 0, 5);
        timer.Tick += ((sender, e) =>
        {
            scrollViewer1.ScrollToHorizontalOffset(
                scrollViewer1.HorizontalOffset - (scrollViewer1.ScrollableWidth / (gridColumnCount - 3) / speed));
            if (scrollViewer1.HorizontalOffset == 0) //cant scroll any more
                ((CustomTimer)sender).Stop();
            ((CustomTimer)sender).life++;
            if (((CustomTimer)sender).life >= speed) //reached destination
                ((CustomTimer)sender).Stop();
        });
        timer.Start();
    }

我的方法有問題導致這種奇怪的抽搐嗎? 知道怎么解決嗎?

CompositionTarget.Rendering將更適合動畫的內容,因為每次幀渲染時它都會觸發。 嘗試這樣的事情:

    public void Shift(ScrollViewer target, double speed = 11, double distance = 20)
    {
        double startOffset = target.HorizontalOffset;
        double destinationOffset = target.HorizontalOffset + distance;

        if (destinationOffset < 0)
        {
            destinationOffset = 0;
            distance = target.HorizontalOffset;
        }

        if (destinationOffset > target.ScrollableWidth)
        {
            destinationOffset = target.ScrollableWidth;
            distance = target.ScrollableWidth - target.HorizontalOffset;
        }

        double animationTime = distance / speed;
        DateTime startTime = DateTime.Now;

        EventHandler renderHandler = null;

        renderHandler = (sender, args) =>
        {
            double elapsed = (DateTime.Now - startTime).TotalSeconds;

            if (elapsed >= animationTime)
            {
                target.ScrollToHorizontalOffset(destinationOffset);
                CompositionTarget.Rendering -= renderHandler;
            }

            target.ScrollToHorizontalOffset(startOffset + (elapsed * speed));
        };

        CompositionTarget.Rendering += renderHandler;
    }

編輯:添加范圍檢查

使用負距離值向左滾動。

編輯2:

您可能希望使用此CompositionTargetEx實現而不是CompositionTarget ,因為它只會在渲染線程實際繪制新幀時觸發:

https://stackoverflow.com/a/16334423/612510

編輯3:

由於您使用的是WPF(而不是像我更習慣的Silverlight),您可以使用Stopwatch類來測量經過的秒數而不是我的DateTime.Now方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM