最近在研究掌上英雄聯盟,主要是用來給自己看新聞,順便copy個界面改一下段位裝裝逼,可是在我copy的時候發現這個東西
當你滑動到一定距離的時候導航欄會置頂不動,這個特性在微博和淘寶都有,我看了@ms-uap的文章,淘寶的實現方式是改變頂部顯示欄的大小,我本來准備按照他那個思路去做的,但發現效果不理想,在滑動的時候,底部的界面也跟着在滑動,這樣使得很不友好,所以我准備自己實現一個
先上個最終效果圖吧,圖比較大,請耐心等待
思路大概是這樣的
將這個界面分為兩行
<Grid.RowDefinitions> <!--第一行固定大小,用於放置圖片和導航欄--> <RowDefinition Height="200"/> <RowDefinition/> </Grid.RowDefinitions>
然后放置我們的主要代碼,Scrollview里包含一個pivot控件,將這個控件的title加上header的高設置為第一行的高度
<ScrollViewer x:Name="scroll" ViewChanged="scroll_ViewChanged" Grid.Row="0" Grid.RowSpan="2"> <Pivot x:Name="pivot"> <Pivot.Title> <Grid Height="130"/> </Pivot.Title> <PivotItem> <StackPanel> <ListView > <x:Int32>1</x:Int32> <x:Int32>1</x:Int32> <x:Int32>1</x:Int32> <x:Int32>1</x:Int32> <x:Int32>1</x:Int32> <x:Int32>1</x:Int32> <x:Int32>1</x:Int32> <x:Int32>1</x:Int32> <x:Int32>1</x:Int32> <x:Int32>1</x:Int32> <x:Int32>1</x:Int32> <x:Int32>1</x:Int32> <x:Int32>1</x:Int32> <x:Int32>1</x:Int32> <x:Int32>1</x:Int32> <x:Int32>1</x:Int32> <x:Int32>1</x:Int32> <x:Int32>1</x:Int32> </ListView> </StackPanel> </PivotItem> <PivotItem> <StackPanel> <ListView > <x:Int32>2</x:Int32> <x:Int32>2</x:Int32> <x:Int32>2</x:Int32> <x:Int32>2</x:Int32> <x:Int32>2</x:Int32> <x:Int32>2</x:Int32> <x:Int32>2</x:Int32> <x:Int32>2</x:Int32> <x:Int32>2</x:Int32> <x:Int32>2</x:Int32> <x:Int32>2</x:Int32> <x:Int32>2</x:Int32> <x:Int32>2</x:Int32> <x:Int32>2</x:Int32> <x:Int32>2</x:Int32> <x:Int32>2</x:Int32> <x:Int32>2</x:Int32> <x:Int32>2</x:Int32> </ListView> </StackPanel> </PivotItem> <PivotItem> <StackPanel> <ListView > <x:Int32>3</x:Int32> <x:Int32>3</x:Int32> <x:Int32>3</x:Int32> <x:Int32>3</x:Int32> <x:Int32>3</x:Int32> <x:Int32>3</x:Int32> <x:Int32>3</x:Int32> <x:Int32>3</x:Int32> <x:Int32>3</x:Int32> <x:Int32>3</x:Int32> <x:Int32>3</x:Int32> <x:Int32>3</x:Int32> <x:Int32>3</x:Int32> <x:Int32>3</x:Int32> <x:Int32>3</x:Int32> <x:Int32>3</x:Int32> <x:Int32>3</x:Int32> <x:Int32>3</x:Int32> </ListView> </StackPanel> </PivotItem> </Pivot> </ScrollViewer>
這樣,整個ScrollViewer占據了整個屏幕,然后我們來添加導航欄和他上面該顯示的內容
<Grid x:Name="header" Grid.Row="0"> <Grid.RowDefinitions> <RowDefinition Height="150"/> <RowDefinition/> </Grid.RowDefinitions> <!--圖片--> <Grid Background="Green"> </Grid> <!--導航欄 使用listbox綁定到pivot上--> <ListBox Grid.Row="1" x:Name="listBox" Height="50" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Background="#FFEAEAEA" SelectedIndex="{Binding ElementName=pivot, Path=SelectedIndex, Mode=TwoWay}" > <ListBox.Items> <TextBlock Text="戰績"/> <TextBlock Text="能力"/> <TextBlock Text="資產"/> </ListBox.Items> <ListBox.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal"></StackPanel> </ItemsPanelTemplate> </ListBox.ItemsPanel> </ListBox> </Grid>
這里同樣是將其設置為兩行,第一行用於顯示其他內容,此處我就用一個Green色的Grid來代替了,然后第二行才是我們的重點,導航欄,這里我使用了ListBox綁定到pivot的selectedindex來實現,當pivot切換的時候,listbox的selecteditem也跟着切換,那這個時候就有疑問了,為什么不直接用pivot的Header來作為導航欄呢,因為當你把pivot套在scrollview里面是,這個header和title會一起跟着滾動的。
到這里,整個程序差不多快完成了,
回到后台代碼,定義一個用於header平移變換的全局變量
TranslateTransform
private TranslateTransform _tt;
在界面初始化完成后初始化變量
public MainPage() { this.InitializeComponent(); //初始化平移對象 _tt = header.RenderTransform as TranslateTransform; if (_tt == null) { header.RenderTransform = _tt = new TranslateTransform(); } }
然后就是這整個頁面的行為了,我們給ScrllViewer控件添加一個ViewChanged時間
//當scrollview 滾動時改變header的位置,使其往上移動 private void scroll_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e) { //當滾動條到達導航欄時,停止移動 if (scroll.VerticalOffset >= 150) { _tt.Y = -150; } else { _tt.Y = -scroll.VerticalOffset; } }
在事件處理函數中改變header的位置使其往上移動,此時pivot控件也是一起跟着滑動,不過他的Header和Title的高度和導航欄的高度一致,所以會給人一種沒有滑動的感覺。然后我們運行程序,發現鼠標滾輪在pivot里滾動的時候,sccrollview並沒有反應,
那怎么辦,這里我采用了路由事件來解決
在頁面初始化之后,給pivot注冊鼠標滾輪的路由事件
public MainPage() { this.InitializeComponent(); //給pivot注冊 鼠標滾輪路由事件,否則鼠標滾輪的滑動 會變成切換pivotitem pivot.AddHandler(PointerWheelChangedEvent, new PointerEventHandler(OnChanged), true); //初始化平移對象 _tt = header.RenderTransform as TranslateTransform; if (_tt == null) { header.RenderTransform = _tt = new TranslateTransform(); } }
然后添加處理函數
private void OnChanged(object sender, PointerRoutedEventArgs e) { //判斷鼠標滾動方向 if (e.GetCurrentPoint(pivot).Properties.MouseWheelDelta < 0) { scroll.ChangeView(0, scroll.VerticalOffset + 75, 1); } else { scroll.ChangeView(0, scroll.VerticalOffset - 75, 1); } e.Handled = true; }
到這里我們的頁面就完成了,上一個gif圖展示
第一次寫分享,寫的不好請多多見諒
github源碼地址:https://github.com/hei12138/FixedToHead
歡迎一起交流uwp的開發技術 1329698854@qq.com,