UWP的一種下拉刷新實現

簡介

咱們最近實現了一個在UWP中使用的下拉刷新功能,以知足用戶的需求,由於這是下拉刷新是一種常見的操做方式,而UWP自己並不提供這一機制。git

經過下拉刷新這一機制,可讓移動端的界面設計變得更加簡單,更符合廣大用戶的使用習慣。github

 

NEW github連接:https://github.com/MS-UAP/PullToRefresh.UWPspa

該組件的nuget連接:https://www.nuget.org/packages/PullToRefresh.UWP設計

 

而且,咱們實現的這一下拉刷新功能,具備如下優勢:code

  • 支持自定義下拉頭部,包括及時顯示下拉進度,分辨率較高。
  • 用於ListView時,支持UI虛擬化和增量加載,不影響諸如ListView.Header等屬性。

 

基本使用

使用效果如圖:orm

只須要簡單的:blog

<pr:PullToRefreshBox x:Name="pr" RefreshInvoked="PullToRefreshBox_RefreshInvoked">
    <ListView x:Name="lv" ItemTemplate="{StaticResource ColorfulRectangle}" />
</pr:PullToRefreshBox>

這是默認的效果。用戶只須要訂閱 RefreshInvoked 事件便可。事件

該事件類型爲:TypedEventHandler<DependencyObject, object>,第一個參數senderPullToRefreshBoxContent,第二個參數老是nullip

 

更多設置

咱們的下拉刷新控件提供更多設置可供開發者自定義其表現。開發

  • double RefreshThreshold {get;set;} :設置觸發刷新的閾值,即有效下拉距離。
  • DataTemplate TopIndicatorTemplate {get;set;} :自定義下拉頭部模板。這是一個DataTemplate,其DataContext只是一個double值,表示相對於下拉閾值的百分比(能夠超過100%)。而該模板自己會決定可用的下拉大小。

 同時,咱們還提供了一個PullRefreshProgressControl控件,方便開發者進行簡單的頭部定製。

該控件提供兩個VisualState:Normal和ReleaseToRefresh,表示下拉過程當中的兩種狀態(未到達刷新閾值,和已到達閾值)。

經過定義PullRefreshProgressControl.Template可使用它(一樣也要設定一下PullToRefreshBox.TopIndicatorTemplate,而且對PullRefreshProgressControl.Progress屬性進行綁定)。

 

接下來爲你們展現一下簡單的定製效果:

相關代碼以下:

<Grid>
    <pr:PullToRefreshBox RefreshInvoked="pr_RefreshInvoked">
        <pr:PullToRefreshBox.TopIndicatorTemplate>
            <DataTemplate>
                <Grid Background="LightBlue"
                      Height="130"
                      Width="200">
                    <pr:PullRefreshProgressControl Progress="{Binding}"
                                                   HorizontalAlignment="Center"
                                                   VerticalAlignment="Bottom">
                        <pr:PullRefreshProgressControl.Template>
                            <ControlTemplate>
                                <Grid>
                                    <VisualStateManager.VisualStateGroups>
                                        <VisualStateGroup x:Name="VisualStateGroup">
                                            <VisualState x:Name="Normal" />
                                            <VisualState x:Name="ReleaseToRefresh">
                                                <Storyboard>
                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="txt" Storyboard.TargetProperty="Text">
                                                        <DiscreteObjectKeyFrame KeyTime="0" Value="釋放刷新" />
                                                    </ObjectAnimationUsingKeyFrames>
                                                </Storyboard>
                                            </VisualState>
                                        </VisualStateGroup>
                                    </VisualStateManager.VisualStateGroups>

                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="auto" />
                                        <RowDefinition Height="auto" />
                                    </Grid.RowDefinitions>

                                    <TextBlock x:Name="txt"
                                               Text="下拉刷新"
                                               Grid.Row="1"
                                               FontSize="20"
                                               HorizontalAlignment="Center" />
                                    <TextBlock Text="{Binding}"
                                               FontSize="24"
                                               Foreground="Gray"
                                               HorizontalAlignment="Center" />

                                </Grid>
                            </ControlTemplate>
                        </pr:PullRefreshProgressControl.Template>
                    </pr:PullRefreshProgressControl>

                </Grid>

            </DataTemplate>
        </pr:PullToRefreshBox.TopIndicatorTemplate>

        <ListView x:Name="ic">
            <ListView.ItemContainerStyle>
                <Style TargetType="ListViewItem">
                    <Setter Property="HorizontalAlignment" Value="Center" />
                </Style>
            </ListView.ItemContainerStyle>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Rectangle Width="100" Height="200">
                        <Rectangle.Fill>
                            <SolidColorBrush Color="{Binding}" />
                        </Rectangle.Fill>
                    </Rectangle>
                </DataTemplate>
            </ListView.ItemTemplate>

        </ListView>
    </pr:PullToRefreshBox>
</Grid>

 

若是想要更加複雜的效果,則須要徹底自定義PullToRefreshBox.TopIndicatorTemplate。

 

實現原理

採用外部嵌套ScrollViewer的方式實現。同時監控ScrollViewer的大小變化,以調整Content(即PullToRefreshBox.Content)的大小。

同時在下拉發生後,經過DirectManipulationCompleted事件,肯定鬆開手指的時刻,並將下拉頭部滾出ScrollViewer的可視區域。

在ScrollViewer.ViewChanged事件中計算下拉距離,以實現分辨率較高的進度綁定。

 

已知問題

  • 用於StackPanel,Canvas這類有無限大空間的控件 且不指定PullToRefreshBox的具體大小時,其大小會恆定不變,而不會隨Content大小變化而變化。

 

該組件的nuget連接:https://www.nuget.org/packages/PullToRefresh.UWP

若是你們在使用中遇到了什麼問題,但願能向咱們反饋,以使得咱們的實現變得更好。 

 

感謝 h82258652 提出的意見!

相關文章
相關標籤/搜索