日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

通通玩blend美工(6)下——仿iPhone滚动选择器的ListBox(交互逻辑)

發布時間:2023/12/20 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 通通玩blend美工(6)下——仿iPhone滚动选择器的ListBox(交互逻辑) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原文:通通玩blend美工(6)下——仿iPhone滾動選擇器的ListBox(交互邏輯)

?


?

  上一篇我們已經把界面畫出來了,這篇我們就來制作交互的邏輯吧。上一篇的電梯:

http://www.cnblogs.com/tong-tong/archive/2012/07/15/2586543.html

?   

回顧下效果:

頁面代碼如下:?      <TextBlock Text="{Binding SelectedItem.Content, ElementName=ListBox1}"/> <ListBox x:Name="ListBox1"SelectedIndex="2"><ListBoxItem Content="1"/><ListBoxItem Content="2"/><ListBoxItem Content="3"/><ListBoxItem Content="4"/><ListBoxItem Content="5"/><ListBoxItem Content="6"/><ListBoxItem Content="7"/><ListBoxItem Content="8"/><ListBoxItem Content="9"/><ListBoxItem Content="0"/></ListBox><TextBlock Text="選中內容:"/>

? 

?

1.交互性需求


我們需要實現一下幾個功能

  •   隨著鼠標的移動上下滾動。
  •   當放開鼠標后,自動對正。
  •   設置ListBox的SelectedIndex為但前玻璃塊下面的項。
  •   load時根據XAML中設置的SelectedIndex自動滾動到相應項。?
  • ?

    ?

    ?

    2.整體思路


    ?  首先我們最直觀看到的效果就是滾動,如何讓它滾動呢?我最開始的思路就是ListBox原生的滾動條,通過VisualTreeHelper.GetChild()獲取到ListBox模版里的scrollviewer運行時對象,然后Mousemove時通過myScrollViewer.ScrollToVerticalOffset(m_scrollOffset)方法來設置滾動的位置。經過嘗試這樣雖然可是實現第一點,跟隨鼠標上下滾動,但是沒有依賴項屬性來控制的話,就無法實現鼠標彈起后的自動對正動畫了,所以,這個思路果斷否決了。

    ?

      那如何才能解決動畫問題呢?我們來回顧一下ListBox的幾個常用模版樣式:

      Style:這個就是控制ListBox整體的外觀,上一篇我們幾乎所有的工作都是在改這個。

      ItemContainerStyle:顧名思義就是ListBox子項的樣子,每一項是顯示些什么內容呢?結構如何呢就通過這個來設置。

      ItemsPanel:再次顧名思義就是子項們的容器,我們都知道WPF的容器決定了它的children的布局方式。因為默認是StackPanel,所以我們的ListBox的子項通常看起來是一列或是一行。

      ItemTemplate:這個東西我只是了解一下,實戰中沒用到過,我也不是很了解什么效果是必須用它才能做出來的,有知道的朋友麻煩留言告訴我一聲。

    ?

      沒錯,或許你已經想到了,我們要用到的就是ItemsPanel,我們只要獲取到StackPanel的對象,然后設置他的RenderTransformTranslateTransform,這樣就是可以通過改變TranslateTransform.Y的依賴項來實現鼠標拖動上下滾動以及鼠標彈起后自動對正的動畫效果了。

    ?

    ?

    ?

    3.設計過程


    ?

    Step.1 跟隨鼠標滾吧~!

      首先我們要來獲取StackPanel運行時對象的實例。一開始我還糾結了半天怎么來獲取呢?后來突然想到一個比較另類的方法,就是StackPanel是可以添加Loaded事件的,只要在事件處理中獲取Sender就行了。

    Xaml:

    <StackPanel Background="#00000000" Height="Auto" Width="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Loaded="StackPanel_Loaded"/>

    CS:(這里順便獲取一下item的呈現高度,因為我要根據它計算出可偏移的范圍,防止飛出控件)

         StackPanel _Panel;//模版容器double Y;//鼠標Y軸坐標TranslateTransform _TTF;//容器偏移double itemHeight;//每個item的高度private void StackPanel_Loaded(object sender, RoutedEventArgs e){//添加偏移屬性_Panel = sender as StackPanel;_TTF = new TranslateTransform();_Panel.RenderTransform = _TTF;//獲取item的實際高度itemHeight = (ListBox1.ItemContainerGenerator.ContainerFromIndex(0) as ListBoxItem).ActualHeight;}

    ?

      OK,獲取到這個對象我們就可以添加Mousemove事件來根據鼠標位置來改變StackPanel?的Y軸位移了。

      首先我們給ListBox添加Mousemove事件和mousedown事件(WPF里我把這個事件加在StackPanel上是可以觸發事件的,而silverlight里這樣卻無論如何也觸發不了...)

    CS:

    private void VirtualizingStackPanel_MouseMove(object sender, MouseEventArgs e){if (isPress)//鼠標按下時才滾動 {double mouseOffset = e.GetPosition(this).Y - Y + _TTF.Y;//計算出當前已偏移的位置//在第一項和最后一項時就不能繼續偏移if (mouseOffset >= ListBox1.ActualHeight / 2 || mouseOffset <= ListBox1.ActualHeight / 2 - ListBox1.Items.Count * itemHeight){return;}_TTF.Y = mouseOffset; //偏移為鼠標位置減去之前的位置Y = e.GetPosition(this).Y;//記錄但前位置 }}private void VirtualizingStackPanel_MouseDown(object sender, MouseButtonEventArgs e){Y = e.GetPosition(this).Y;//記錄點擊的鼠標位置isPress = true;}

      這里我說明一下這個可移動范圍是怎么算出來的。如果已經看懂算法的博友可以跳過

      (我們要讓它在第0項到達控件的中間位置時就不能繼續向下滾,TranslateTransform.Y 為正時為向下偏移,初始狀態下StackPanel上邊框是和ListBox的上邊框重合的,這時TranslateTransform.Y的值為0。也就是說TranslateTransform.Y的最大值即為ListBox實際高度的一半。TranslateTransform.Y 為負時為向上偏移。可以偏移的程度為StackPanel下邊框到達ListBox的中間時。這個長度為StackPanel的高減去ListBox的一半高度。當然因為向上偏移,所以值為負。這里我當時可能是腦子進水了,我居然用每一個子項的高度來乘以子項的數量來獲取StackPanel的實際高度...如果還沒想通的朋友可以多實驗幾次上面做好的控件就明白了)。

      OK,這樣第一個功能就實現了。

    ?

    ?

    ?

    Step.2 獲取當前處于最中間的項為選中項

      當我們MouseUp的時候就可以決定選中項為最中間的項,同樣給ListBox添加MouseUp事件。

    CS:

    private void ListBox_MouseUp(object sender, MouseButtonEventArgs e){isPress = false;//計算出ListBox中心線覆蓋在第幾項double offset = (ListBox1.ActualHeight / 2 - _TTF.Y) / itemHeight;int selectIndex = (int)offset;//取整ListBox1.SelectedIndex = selectIndex;//設置當前選中項}

      算法說明:用StackPanel?的偏移位置減去ListBox高的一半即為相對于中心位置的偏移量,向上偏移為負。除以item的高度即為相對于中心位置偏移了幾項。如果結果為2.333那中心線肯定是覆蓋在第三項上了。因為ListBoxIndex索引是從0開始,所以直接取整就行了。

    ?

    ?

    ?

    Step.3 要會自動對正才顯得高端哦~

      所謂對正,即中心線和選中項的中心線重合。什么時候重合呢?即相對偏移項的小數點為0.5的時候。比如偏移了2.33項,當它繼續偏移為2.5的時候就重合了。所以算法就簡單了。我們只要讓動畫來偏移(0.5-0.333)*item的高度的距離就行了。在mouseUp事件里繼續添加動畫。

    CS:

    private void ListBox_MouseUp(object sender, MouseButtonEventArgs e){isPress = false;//計算出ListBox中心線覆蓋在第幾項double offset = (ListBox1.ActualHeight / 2 - _TTF.Y) / itemHeight;int selectIndex = (int)offset;//取整ListBox1.SelectedIndex = selectIndex;//設置當前選中項//計算出自動對正需要進行的偏移double changeOffset = (offset - (int)offset - 0.5) * itemHeight + _TTF.Y;Storyboard sb = new Storyboard();DoubleAnimation _DA = new DoubleAnimation();_DA.To = changeOffset;_DA.Duration = new Duration(TimeSpan.FromMilliseconds(300));sb.Children.Add(_DA);Storyboard.SetTarget(_DA, _TTF);Storyboard.SetTargetProperty(_DA, new PropertyPath("Y"));sb.Begin();//開始動畫}

    ?

    ?

    Step.4 Loaded時滾動到SelectedIndex項的位置

    ?  只要根據選中項計算出需要偏移的位置,然后再模擬一次MouseUp即可。在Loaded事件里面添加.....

    CS:

    private void StackPanel_Loaded(object sender, RoutedEventArgs e){//添加偏移屬性_Panel = sender as StackPanel;_TTF = new TranslateTransform();_Panel.RenderTransform = _TTF;//獲取item的實際高度itemHeight = (ListBox1.ItemContainerGenerator.ContainerFromIndex(0) as ListBoxItem).ActualHeight;if (ListBox1.SelectedIndex != -1)//更具初始設置的選中項把它置于最中間 {_TTF.Y = this.ActualHeight / 2 - (ListBox1.SelectedIndex+1) * itemHeight;}ListBox_MouseUp(null, null);}

    算法說明:用(SelectedIndex+1)*item的高度計算出偏移量。再減去ListBox高的一半計算出相對于中心線的偏移量。因為偏移是下正上負,取負值。本來可以直接偏移到相應位置。但是,出現點動畫效果才顯的牛X。所以就模擬了一下MouseUp。當然也可以重新寫動畫,實現0到目標偏移位置的滾動,這樣效果更好。

      做完收工。

    ?

    ?

    ?

    后記


      這個做完了以后怎么和先前說好的XAML的代碼有點不一樣啊??我原版做的是WPF的,我把各種事件處理都寫在ItemsPanelStackPanel里了,所以很簡潔,而移植到silverlight時發現這樣寫怎么都獲取不到鼠標事件,于是,就果斷把事件添加在ListBox里了。

      自從把11天梯積分打到1500分以后,一直作為路人的我,感到空前的寂寞。于是果斷轉戰“擼哦擼”,打了幾天,感覺不錯,特別是瑞茲的shift+QW QR QE...虐菜必備啊~~哈哈

    ?

    ?

    ?

    ?

      

    總結

    以上是生活随笔為你收集整理的通通玩blend美工(6)下——仿iPhone滚动选择器的ListBox(交互逻辑)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 国产区精品区 | 受虐m奴xxx在线观看 | 日韩人妻精品中文字幕 | 欧美日韩一区二区三区电影 | 怡红院成人av | 国产精品二区三区 | 美国一级大黄一片免费中文 | 国产精品免费久久久 | 国产福利一区二区三区视频 | 日韩av无码一区二区三区不卡 | jvid视频| 91视频一区二区三区 | 黄色私人影院 | jizz欧洲 | 国产高潮又爽又无遮挡又免费 | 色播在线视频 | av最新天堂 | www国产精品视频 | 日本a级无毛 | 成人h视频 | 无遮挡在线 | 天天干,天天爽 | 成人国产精品免费观看视频 | 夜夜春av| 日本成人免费网站 | 91精品国产乱码久久久张津瑜 | 国产成人精品在线视频 | 亚洲高清一区二区三区 | 久艹在线播放 | 少妇2做爰交换朴银狐 | 人人曰 | 欧美性受黑人性爽 | 亚洲777| 国产黄色一级大片 | 午夜精品一区二区在线观看 | 亚洲欧美日韩综合 | 久久久成人精品视频 | 男人操女人下面视频 | 99视频网| 亚洲少妇视频 | 久久精品人人爽 | 好男人www | 在线播放视频高清在线观看 | 国产一区二区亚洲 | 国产日本欧美一区二区 | 永久免费看成人av的动态图 | 黄大色黄大片女爽一次 | 久久密桃 | 欧美性理论片在线观看片免费 | 久久国产美女视频 | a级片一区二区 | 亚洲国产精品系列 | 农村搞破鞋视频大全 | 9.1成人看片免费版 日韩经典在线 | 久久在线免费视频 | 高跟肉丝丝袜呻吟啪啪网站av | 女生喷水视频 | 欧美一区二区三区公司 | 男人操女人动漫 | 麻豆久久久久久久 | 久在线视频 | 日本高清有码视频 | www.久久久 | 国产黄色在线 | 国产麻豆一区二区 | 中国极品少妇xxxx做受 | 亚洲成人精品在线播放 | 久操欧美 | 巨物撞击尤物少妇呻吟 | 国产美女www爽爽爽 www.国产毛片 | 久久av高潮av | 精品不卡在线 | 麻豆传媒网 | 亚洲免费视频观看 | 国产乱淫a∨片免费观看 | 欧美激情精品久久久久久免费 | 91成人精品国产刺激国语对白 | 日韩1024 | 日本黄色大片视频 | 日本久久高清视频 | 成人h动漫精品一区二区 | 精品麻豆 | 国产精品三区在线观看 | 欧美大片免费 | 亚洲欧美强伦一区二区 | 成人3d动漫一区二区三区 | 久久久久国产精品一区 | 手机看片日韩日韩 | 天天射狠狠干 | 蜜乳av一区 | 香蕉av一区二区三区 | 成人青青草 | 亚洲乱码视频在线观看 | 丝袜av在线播放 | 永久在线 | 亚洲无码精品一区二区三区 | 一区二区三区视频在线 | 欧美性爱精品在线 | 国产欧美日韩一区 |