上次在UWP中的消息提示框(二)中談到彈出框在虛擬導航欄的手機上被遮擋問題,今天接就著扯。 上次給用戶控制項指定的寬高都是Window.Current.Bounds的寬高,而這個獲取到的是包含應用程式視窗的高度和寬度(以有效(視圖)像素為單位)的 Rect 值,在手機上是狀態欄和虛擬導航欄的高度也算進 ...
上次在UWP中的消息提示框(二)中談到彈出框在虛擬導航欄的手機上被遮擋問題,今天接就著扯。
上次給用戶控制項指定的寬高都是Window.Current.Bounds的寬高,而這個獲取到的是包含應用程式視窗的高度和寬度(以有效(視圖)像素為單位)的 Rect 值,在手機上是狀態欄和虛擬導航欄的高度也算進去的,所以通過這個寬高去設置一些控制項的寬高是不那麼準確的。
其實還有另一個API:Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().VisibleBounds,VisibleBounds顧名思義是獲取視窗(應用程式視圖)的可見區,在手機上是不包含狀態欄和虛擬導航欄的高度,所以在一些彈窗需要在靠屏幕底部放置按鈕的需求里可能這個API更適合我們。
但是只給彈窗的寬高指定為Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().VisibleBounds獲取的寬高也還是有問題的,Popup在彈出的時候預設錨點是屏幕最左上角(不排除狀態欄),所以在狀態欄顯示的情況就會出現底部高度偏上的情況,還需要設置一個距上邊距為狀態欄高度的Margin。還有別忘記虛擬導航欄的手機可以隱藏、顯示虛擬導航欄,所以應該還需要訂閱VisibleBoundsChanged的事件
來看看代碼,在上次的代碼上做修改,需要在用戶控制項的構造和可見區的寬高變化時區指定寬高,所以寫成一個方法:
private void MeasurePopupSize() { this.Width = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().VisibleBounds.Width; double marginTop = 0; if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.UI.ViewManagement.StatusBar")) marginTop = Windows.UI.ViewManagement.StatusBar.GetForCurrentView().OccludedRect.Height; this.Height = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().VisibleBounds.Height; this.Margin = new Thickness(0, marginTop, 0, 0); }
構造改成:
private MessagePopupWindow() { this.InitializeComponent(); m_Popup = new Popup(); Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().VisibleBoundsChanged += (s,e)=> { MeasurePopupSize(); }; MeasurePopupSize(); m_Popup.Child = this; this.Loaded += MessagePopupWindow_Loaded; this.Unloaded += MessagePopupWindow_Unloaded; }
示例代碼也做了更新,歡迎圍觀 https://github.com/kkkeyboy/UWPPopup