溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

[UWP]用畫(huà)中畫(huà)模式(CompactOverlay Mode)讓用總在最前端顯示

發(fā)布時(shí)間:2020-05-27 19:14:15 來(lái)源:網(wǎng)絡(luò) 閱讀:183 作者:sq5dfdd690add48 欄目:編程語(yǔ)言

1. 什么是,以及怎么用畫(huà)中畫(huà)

Windows 10 Creators Update以后UWP提供了一個(gè)新的視圖模式CompactOverlay,中文翻譯成 緊湊的覆蓋層?反正大部分時(shí)間我們都會(huì)稱(chēng)它為畫(huà)中畫(huà)模式。

[UWP]用畫(huà)中畫(huà)模式(CompactOverlay Mode)讓用總在最前端顯示

上圖中右上角即為進(jìn)入畫(huà)中畫(huà)模式的微軟“電影和電視”應(yīng)用。

可以調(diào)用ApplicationView.TryEnterViewModeAsync函數(shù)進(jìn)入或退出CompactOverlayer模式:

//進(jìn)入CompactOverlay模式
await ApplicationView.GetForCurrentView().TryEnterViewModeAsync(ApplicationViewMode.CompactOverlay);

//返回默認(rèn)模式
await ApplicationView.GetForCurrentView().TryEnterViewModeAsync(ApplicationViewMode.Default);

還可以使用ViewModePreferences控制進(jìn)入CompactOverlay時(shí)窗口的大小:

//進(jìn)入CompactOverlay模式并將窗體設(shè)置為 200 x 200 像素
var preferences = ViewModePreferences.CreateDefault(ApplicationViewMode.CompactOverlay);
preferences.CustomSize = new Windows.Foundation.Size(200, 200);
await ApplicationView.GetForCurrentView().TryEnterViewModeAsync(ApplicationViewMode.CompactOverlay, preferences);

//返回默認(rèn)模式
var preferences = ViewModePreferences.CreateDefault(ApplicationViewMode.Default);
await ApplicationView.GetForCurrentView().TryEnterViewModeAsync(ApplicationViewMode.Default, preferences);

進(jìn)入CompactOverlay模式后,窗體首先縮小并移動(dòng)到屏幕右上方,并且有以下行為:

? 窗口置于頂層;
? 最大化、最小化按鈕消失;
? 標(biāo)題欄會(huì)在失去焦點(diǎn)并且鼠標(biāo)離開(kāi)后幾秒鐘消失;
? 使用`Window.Current.SetTitleBar`設(shè)置為標(biāo)題欄元素的內(nèi)容也會(huì)在鼠標(biāo)離開(kāi)后消失;
? 可以改變窗口大小,但只能在 150 x 150 到 500 x 500 之間改變;
? 雖然標(biāo)題欄消失,但左下右三個(gè)邊框仍在;

因?yàn)槌叽缬邢拗?,所以超過(guò) 150 x 150 到 500 x 500 這個(gè)范圍的ViewModePreferences.CustomSize不會(huì)生效,會(huì)取最接近范圍的值。例如使用 700 x 500 會(huì)出現(xiàn) 500 x 500 的窗口。

[UWP]用畫(huà)中畫(huà)模式(CompactOverlay Mode)讓用總在最前端顯示

2. 通過(guò)自定義StateTrigger響應(yīng)畫(huà)中畫(huà)模式

上一篇文章介紹過(guò)如何使用AdaptiveTrigger實(shí)現(xiàn)響應(yīng)式布局,CompactOverlay的情況更加極端,畢竟有可能從1920 x 1050突然變成150 x 150。為了應(yīng)對(duì)這種情況,我自定義了一個(gè)StateTrigger,根據(jù)ApplicationView.ViewMode的值判斷是否激活當(dāng)前的State。這個(gè)類(lèi)繼承自StateTriggerBase,在監(jiān)視的FrameworkElement的SizeChanged事件中調(diào)用SetActive改變State的激活狀態(tài)。具體代碼及使用方式如下:

public class IsCompactOverlayModeTrigger : StateTriggerBase
{
    private FrameworkElement _targetElement;

    public FrameworkElement TargetElement
    {
        get
        {
            return _targetElement;
        }
        set
        {
            if (_targetElement != null)
            {
                _targetElement.SizeChanged -= OnSizeChanged;
            }
            _targetElement = value;
            _targetElement.SizeChanged += OnSizeChanged;
        }
    }

    private void OnSizeChanged(object sender, SizeChangedEventArgs e)
    {
        var view = ApplicationView.GetForCurrentView();
        SetActive(view.ViewMode == ApplicationViewMode.CompactOverlay);
    }
}
<VisualStateManager.VisualStateGroups>
    <VisualStateGroup>
        <VisualState>
            <VisualState.StateTriggers>
                <helpers:IsCompactOverlayModeTrigger TargetElement="{x:Bind}" />
            </VisualState.StateTriggers>
            <VisualState.Setters>
                <Setter Target="CompactView.Opacity"
                        Value="1" />
                <Setter Target="CompactView.IsHitTestVisible"
                        Value="True" />
                <Setter Target="NormalView.Opacity"
                        Value="0" />
                <Setter Target="NormalView.IsHitTestVisible"
                        Value="False" />
            </VisualState.Setters>
        </VisualState>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

雖然前一篇文章介紹了使用Visibility改變視圖,但使用了ImplicitAnimation的話(huà)改變Visibility會(huì)觸發(fā)動(dòng)畫(huà),所以有時(shí)我會(huì)使用Opacity和IsHitTestVisible來(lái)顯示/隱藏UI元素。

3. 或者索性導(dǎo)航到新的頁(yè)面

使用 StateTrigger畢竟還是有些繁瑣,大部分情況下需要用到畫(huà)中畫(huà)模式的應(yīng)用,CompactOverlay的視圖都是固定的那幾個(gè),所以可以直接導(dǎo)航到一個(gè)新頁(yè)面。

private async void OnEnterDefault(object sender, RoutedEventArgs e)
{
    var preferences = ViewModePreferences.CreateDefault(ApplicationViewMode.Default);
    await ApplicationView.GetForCurrentView().TryEnterViewModeAsync(ApplicationViewMode.Default, preferences);
}

private async void OnEnterCompactOverlay(object sender, RoutedEventArgs e)
{
    var preferences = ViewModePreferences.CreateDefault(ApplicationViewMode.CompactOverlay);
    preferences.CustomSize = new Windows.Foundation.Size(150, 150);
    await ApplicationView.GetForCurrentView().TryEnterViewModeAsync(ApplicationViewMode.CompactOverlay, preferences);
    Frame.Navigate(typeof(CompactPage), null, new SuppressNavigationTransitionInfo());
}

這時(shí)候記得要使用SuppressNavigationTransitionInfo暫停導(dǎo)航的過(guò)渡動(dòng)畫(huà),否則會(huì)很難看。

4. 結(jié)語(yǔ)

CompactOverlay mode – aka Picture-in-Picture

上面這篇文章還給出了更多有用的代碼:如何判斷是否支持CompactOverlay及如何在多視圖模式下使用。但我沒(méi)有用到就不再贅述了,有興趣可以參考這個(gè)文章。

畫(huà)中畫(huà)模式對(duì)我的番茄鐘應(yīng)用很重要。雖然我很喜歡在第二個(gè)屏幕上使用番茄鐘,一來(lái)不占用我的工作區(qū)域,二來(lái)可以提醒別人我正在專(zhuān)注工作不要打擾,但對(duì)很多只有一個(gè)屏幕的用戶(hù)來(lái)說(shuō)畫(huà)中畫(huà)模式更加實(shí)用。關(guān)于畫(huà)中畫(huà)模式的更多信息可以參考下面給出的網(wǎng)站。

5. 參考

ApplicationView Class (Windows.UI.ViewManagement) - Windows UWP applications Microsoft Docs

ApplicationViewMode Enum (Windows.UI.ViewManagement) - Windows UWP applications Microsoft Docs

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI