panorama控件平滑跳轉到指定的item


panorama控件是wp中最有特色的控件之一,它提供了wp獨有的全景視圖,但是在使用該控件的時候,我碰到了這么一個問題。我想在代碼中指定panorama的SelectedIndex,但是該屬性是只讀的,通過在網上尋找,最終還是沒有找到一個完美的解決方案,網上的解決方案大抵如下:

1.使用panorama.DefaultItem=panorama.Items[newIndex];

這個方法它只是將第index處的item放到了第一個位置,而且沒有過渡的動畫,不符合要求。

2.通過設置SelectedItemProperty這個依賴屬性來改變SelectedItem的值。

panorama.SetValue(Panorama.SelectedItemProperty, pan.Items[newIndex]);

但是就算這么設了,還是沒有滑動的動畫效果,具體請參考網友提供的代碼

為了得到一個完美的解決方案,樓主深入挖掘了panorama控件的動畫運作方式以及它的控件模板。最終搞定了這個問題,代碼比較多。下面是主要的一個函數

        /// <summary>
        /// 平滑過渡到指定的Item
        /// </summary>
        /// <param name="panorama"></param>
        /// <param name="index">指定的Item索引</param>
        /// <param name="duration">動畫時長</param>
        /// <param name="complated">動畫完成后需要執行的動作</param>
        public static void GoTo(this Panorama panorama, int index, Duration duration, Action complated = null)
        {
            if (panorama.Items.Count == 0)
                return;
            while (index < 0)
                index += panorama.Items.Count;
            while (index >= panorama.Items.Count)
                index -= panorama.Items.Count;
            if (index == panorama.SelectedIndex)
                return;

            var bgLayer = panorama.Descendants<PanningBackgroundLayer>().FirstOrDefault();
            var titleLayer = panorama.Descendants<PanningTitleLayer>().FirstOrDefault();
            var itemsLayer = panorama.Descendants<PanningLayer>().LastOrDefault();
            var panel = panorama.Descendants<PanoramaPanel>().FirstOrDefault();
            if (panel == null)
                return;

            var direction = -1;
            if (index > panorama.SelectedIndex)
            {
                var length1 = index - panorama.SelectedIndex;
                var length2 = panorama.Items.Count - length1;
                if (length2 < length1)
                    direction = 1;
            }
            else
            {
                var length1 = panorama.SelectedIndex - index;
                var length2 = panorama.Items.Count - length1;
                if (length1 <= length2)
                    direction = 1;
            }

            var currentOffset = -GetOffsetX(panel, panorama.SelectedIndex);
            var offset = -(int) GetOffsetX(panel, index);
            if (Math.Sign(offset - currentOffset) != Math.Sign(direction))
            {
                if (bgLayer != null)
                    bgLayer.Wraparound(direction);
                if (titleLayer != null)
                    titleLayer.Wraparound(direction);
                if (itemsLayer != null)
                    itemsLayer.Wraparound(direction);
            }
            panorama.SetValue(Panorama.SelectedItemProperty, panorama.Items[index]);
            UpdateItemPositions(panorama, panel);
            if (bgLayer != null)
                bgLayer.GoTo(offset, duration, null);
            if (titleLayer != null)
                titleLayer.GoTo(offset, duration, null);
            if (itemsLayer != null)
                itemsLayer.GoTo(offset, duration, complated);
        }

當想以動畫形式過渡到某個項時,直接如下使用即可:

panorama.GoTo(0, new Duration(TimeSpan.FromMilliseconds(800)));

為了實現最終的目的,還必須的用到LinqToTree這個利器。

全部的代碼可以在此處下載:http://vdisk.weibo.com/s/yVSnUWjPhIz8j

 注意:wp8中PanningLayer的GoTo函數只有兩個參數,只需要將下面幾行代碼更改一下即可使用

if (bgLayer != null)
    bgLayer.GoTo(offset, duration, null);
 if (titleLayer != null)
    titleLayer.GoTo(offset, duration, null);
 if (itemsLayer != null)
   itemsLayer.GoTo(offset, duration, complated);

 改為:

            if (bgLayer != null)
                bgLayer.GoTo(offset, duration);
            if (titleLayer != null)
                titleLayer.GoTo(offset, duration);
            if (itemsLayer != null)
                itemsLayer.GoTo(offset, duration);
            if (complated == null) 
                return;
            var timer = new DispatcherTimer {Interval = duration.TimeSpan};
            timer.Tick += (sender, e) =>
                {
                    complated();
                    timer.Stop(); 
                };
            timer.Start();

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM