用UWP實現一個和win10設置頁面類似的布局


不知道有人注意過Win10中的設置頁面的布局沒?那個頁面會根據不同的窗口寬度來調節顯示的內容,甚至來后退按鈕的操作在不同的寬度也是不同的,看圖:

 

是不是有點cool呢,這篇文章,我們就來做一個類似的布局。

首先將我們需要展示出來的東西都添加到頁面上,頁面如下:

 1     <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
 2         <Grid.RowDefinitions>
 3             <RowDefinition Height="30"></RowDefinition>
 4             <RowDefinition Height="*"></RowDefinition>
 5         </Grid.RowDefinitions>
 6 
 7         <!--大標題,后退按鈕-->
 8         <StackPanel Grid.Row="0" Orientation="Horizontal" x:Name="fullPanel">
 9             <Button Content="Back" x:Name="full_back" Click="full_back_Click"></Button>
10             <TextBlock Margin="10, 0, 0, 0">這是一個大標題</TextBlock>
11         </StackPanel>
12 
13 
14         <!--副標題,后退按鈕,只在desktop上寬度小於500時顯示-->
15         <StackPanel Grid.Row="0" Orientation="Horizontal" x:Name="detailPanel" >
16             <Button x:Name="detail_back" Content="Back" Click="detail_back_Click"></Button>
17             <TextBlock Margin="10, 0, 0, 0">這是一個副標題</TextBlock>
18         </StackPanel>
19 
20         <!--內容-->
21         <RelativePanel Grid.Row="1">
22             <!--左半部分的list-->
23             <ListView x:Name="left" IsItemClickEnabled="True" ItemClick="left_ItemClick" SelectedIndex="-1">
24                 <ListView.ItemTemplate>
25                     <DataTemplate>
26                         <StackPanel Margin="10">
27                             <TextBlock>
28                                 <Run Text="Item: "></Run>
29                                 <Run Text="{Binding}"></Run>
30                             </TextBlock>
31                         </StackPanel>
32                     </DataTemplate>
33                 </ListView.ItemTemplate>
34             </ListView>
35 
36             <!--右半部份的詳細信息-->
37             <Grid x:Name="right" >
38                 <StackPanel>
39                     <TextBlock>隊長,別開槍。。</TextBlock>
40                     <TextBlock  >
41                         <Run Text="Item:"></Run>
42                         <Run Text="{Binding SelectedItem, ElementName=left}" Foreground="Red"></Run>
43                     </TextBlock>
44                 </StackPanel>
45             </Grid>
46         </RelativePanel>
47     </Grid>

后台綁定測試數據:

1         private void MainPage_Loaded(object sender, RoutedEventArgs e)
2         {
3             this.left.ItemsSource = Enumerable.Range(1, 10).ToList();
4         }

運行起來看看效果,有點亂啊,不急,我們慢慢調。

這個頁面中,我們准備在窗口寬度小於500時顯示窄布局,大於500時顯示寬布局,下面就是我們的VisualState發揮作用的時候了。我們先創建一個VisualStateGroup,只用來針對窗口大小來調整布局,暫時先忽略掉mobile,詳細說明請看注釋。

 1         <VisualStateManager.VisualStateGroups>
 2             <!--這個group里的VisualState只針對窗口寬度調整布局,不涉及設備-->
 3             <VisualStateGroup x:Name="windowSize">
 4                 <!--寬屏設置-->
 5                 <VisualState x:Name="wide">
 6                     <VisualState.StateTriggers>
 7                         <!--大於等於501就算寬屏了。。-->
 8                         <AdaptiveTrigger MinWindowWidth="501"></AdaptiveTrigger>
 9                     </VisualState.StateTriggers>
10                     <VisualState.Setters>
11                         <!--這里進行寬屏下的設置-->
12                         <!--隱藏副標題-->
13                         <Setter Target="detailPanel.Visibility" Value="Collapsed"></Setter>
14 
15                         <!--顯示大標題,雖然大標題默認是顯示的,但是因為我們以后會通過code修改顯示屬性,所以這里要重置才行-->
16                         <Setter Target="fullPanel.Visibility" Value="Visible"></Setter>
17 
18                         <!--顯示右側內容-->
19                         <Setter Target="right.Visibility" Value="Visible"></Setter>
20 
21                         <!--寬屏時,右側內容應該是在list的右側-->
22                         <Setter Target="right.(RelativePanel.RightOf)" Value="left"></Setter>
23 
24                         <!--顯示左側內容-->
25                         <Setter Target="left.Visibility" Value="Visible"></Setter>
26                     </VisualState.Setters>
27                 </VisualState>
28 
29                 <!--窄屏設置-->
30                 <VisualState x:Name="narrow">
31                     <VisualState.StateTriggers>
32                         <!--0-500都是小窗口-->
33                         <AdaptiveTrigger MinWindowWidth="0"></AdaptiveTrigger>
34 
35                     </VisualState.StateTriggers>
36                     <VisualState.Setters>
37                         <!--默認顯示副標題-->
38                         <Setter Target="detailPanel.Visibility" Value="Visible"></Setter>
39 
40                         <!--隱藏大標題,點擊副標題的后退才顯示-->
41                         <Setter Target="fullPanel.Visibility" Value="Collapsed"></Setter>
42 
43                         <!--顯示右側內容,點擊副標題后退之后隱藏-->
44                         <Setter Target="right.Visibility" Value="Visible"></Setter>
45 
46                         <!--隱藏左側內容-->
47                         <Setter Target="left.Visibility" Value="Collapsed"></Setter>
48                     </VisualState.Setters>
49                 </VisualState>
50             </VisualStateGroup>
51         </VisualStateManager.VisualStateGroups>

運行起來看看是不是效果要好很多了呢,現在調整窗口的寬度,是不是有點意思了呢?

但是后退按鈕還是沒有效果,這里我們需要使用code去控制了,但是這個很簡單,因為我們在不同的布局下,使用的是不同的button,這樣的好處是不需要用code去判斷窗口狀態。這里我們只貼上后台代碼,同樣很簡單。

 1         private void full_back_Click(object sender, RoutedEventArgs e)
 2         {
 3             // 對於我們的頁面來說,full_back按鈕是應該隱藏的,因為沒有上一層頁面
 4             // 所以這里我們忽略掉,但是按鈕還是留着,你可以自己來做個隱藏的邏輯
 5         }
 6 
 7         private void detail_back_Click(object sender, RoutedEventArgs e)
 8         {            
 9             // 這里就是為什么我們在VisualState里重新設置屬性的原因
10 
11             // 顯示左側的list
12             // 隱藏右側內容
13             this.left.Visibility = Visibility.Visible;
14             this.right.Visibility = Visibility.Collapsed;
15 
16             // 隱藏副標題
17             // 顯示主標題
18             this.fullPanel.Visibility = Visibility.Visible;
19             this.detailPanel.Visibility = Visibility.Collapsed;
20         }
21 
22         private void left_ItemClick(object sender, ItemClickEventArgs e)
23         {
24             // 這里我們需要判斷下,是否需要切換隱藏
25             if (this.ActualWidth <= 500)
26             {
27                 // 顯示左側的list
28                 // 隱藏右側內容
29                 this.left.Visibility = Visibility.Collapsed;
30                 this.right.Visibility = Visibility.Visible;
31 
32                 // 隱藏副標題
33                 // 顯示主標題
34                 this.fullPanel.Visibility = Visibility.Collapsed;
35                 this.detailPanel.Visibility = Visibility.Visible;
36             }
37         }

到這里的話,我們的這個頁面的行為和設置已經有點像了!

到這里我們這個頁面的基本功能就算是差不多了,然后來完善下細節(其實還是有個小問題,狀態的切換還是和設置有些區別的)。 

1. 窗口寬度大於500的時候,直接給他一個固定的寬度,讓list能寬一些。

2.  窗口寬度小於500的時候,把list撐滿整個頁面。這里我們需要說下RelativePanel的一個特性(應該是特性吧。。),它內部的控件是不會自動拉伸撐滿內部空間的,即使你用了HorizontalAlignment/VerticalAlignment,連Grid都不行!!我們需要使用RelativePanel.AlignXXXX這一系列屬性,根據需要來拉伸。

在我們的頁面中,我們需要在窄屏下上下左右都對齊,來撐滿頁面。

1                         <!--拉伸左側list,撐滿頁面-->
2                         <Setter Target="left.(RelativePanel.AlignRightWithPanel)" Value="True"></Setter>
3                         <Setter Target="left.(RelativePanel.AlignBottomWithPanel)" Value="True"></Setter>
4                         <Setter Target="left.(RelativePanel.AlignLeftWithPanel)" Value="True"></Setter>
5                         <Setter Target="left.(RelativePanel.AlignTopWithPanel)" Value="True"></Setter>

最后的效果!

 

這篇文章的例子只是一個很簡單布局,如果你准備實現復雜一些的功能的話,可以考慮把右側的Grid換成Frame,然后通過左側的ListItem導航到不同的頁面,來顯示不同的內容。


免責聲明!

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



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