1. 程式人生 > >在UWP中頁面滑動導航欄置頂

在UWP中頁面滑動導航欄置頂

效果圖 路由 .html bject 完成 我們 end 鼠標滾輪 istview

原文:在UWP中頁面滑動導航欄置頂

最近在研究掌上英雄聯盟,主要是用來給自己看新聞,順便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的開發技術 [email protected]

在UWP中頁面滑動導航欄置頂