windows Dotnet Maui自定义控件自动淡入媒体元素

py49o6xq  于 2023-03-31  发布在  Windows
关注(0)|答案(1)|浏览(182)

我希望添加一个自定义的ImageButton自动隐藏后,在Dotnet毛伊岛MediaElement页面几秒钟的能力。我宁愿直接添加控制媒体元素控件,但会很高兴与任何一个结果。我试图找出一种方法来隐藏控件使用IsBusy和IsNotBusy与计时器,但我有零的运气到目前为止。这里是项目的相关代码。
示例:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    x:Class="NerdNewsNavigator2.View.LivePage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
    xmlns:viewmodel="clr-namespace:NerdNewsNavigator2.ViewModel"
    Title=""
    x:DataType="viewmodel:LiveViewModel"
    BackgroundColor="Black"
    Loaded="ContentPage_Loaded"
    Shell.NavBarIsVisible="False"
    Unloaded="ContentPage_Unloaded">

    <Shell.BackButtonBehavior>
        <BackButtonBehavior IsEnabled="True" IsVisible="False" />
    </Shell.BackButtonBehavior>

    <Grid>
        <toolkit:MediaElement
            x:Name="mediaElement"
            ShouldAutoPlay="True"
            ShouldShowPlaybackControls="True" />
        <ImageButton
            x:Name="btnFullScreen"
            Grid.Row="0"
            Margin="10"
            Clicked="BtnFullScreen_Clicked"
            HeightRequest="40"
            HorizontalOptions="End"
            IsVisible="{OnPlatform Android=true,
                                   iOS=false,
                                   WinUI=true,
                                   MacCatalyst=true}"
            Source="iconfullscreen.png"
            VerticalOptions="Start"
            WidthRequest="40">
            <ImageButton.Behaviors>
                <toolkit:IconTintColorBehavior TintColor="White" />
            </ImageButton.Behaviors>
        </ImageButton>
    </Grid>

</ContentPage>

政务司司长:

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.Maui.Controls.PlatformConfiguration;
using Application = Microsoft.Maui.Controls.Application;
using Platform = Microsoft.Maui.ApplicationModel.Platform;

#if ANDROID
using Views = AndroidX.Core.View;
#endif

#if WINDOWS
using Microsoft.UI;
using Microsoft.UI.Windowing;
using WinRT;
using Microsoft.Maui.Controls;
#endif

namespace NerdNewsNavigator2.View;

/// <summary>
/// A class that manages watching Live video from twit.tv podcasting network
/// </summary>
public partial class LivePage : ContentPage
{
    private bool _fullScreen = false;
    /// <summary>
    /// Initializes a new instance of <see cref="LivePage"/> class.
    /// </summary>
    /// <param name="liveViewModel">This classes <see cref="ViewModel"/> from <see cref="LiveViewModel"/></param>
    public LivePage(LiveViewModel liveViewModel)
    {
        InitializeComponent();
        BindingContext = liveViewModel;
    }

    private void BtnFullScreen_Clicked(object sender, EventArgs e)
    {
        if (_fullScreen)
        {
            _fullScreen = false;
            RestoreScreen();
        }
        else
        {
            SetFullScreen();
            _fullScreen = true;
        }
    }

    /// <summary>
    /// Method overrides <see cref="OnDisappearing"/> to stop playback when leaving a page.
    /// </summary>
    protected override void OnDisappearing()
    {
        mediaElement.Stop();
        mediaElement.ShouldKeepScreenOn = false;
    }
    #region Load/Unload Events
#nullable enable

    /// <summary>
    /// Manages unload event from <see cref="mediaElement"/> after it is unloaded.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public void ContentPage_Unloaded(object? sender, EventArgs e)
    {
        if (sender is null)
        {
            return;
        }
        mediaElement.Handler?.DisconnectHandler();
    }
    /// <summary>
    /// Method Loads Video after page has finished being rendered.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ContentPage_Loaded(object? sender, EventArgs e)
    {
        if (sender is null)
        {
            return;
        }

        _ = LoadVideo();
    }

    /// <summary>
    /// Method returns 720P URL for <see cref="mediaElement"/> to Play.
    /// </summary>
    /// <param name="m3UString"></param>
    /// <returns></returns>
    public static string ParseM3UPLaylist(string m3UString)
    {
        var masterPlaylist = MasterPlaylist.LoadFromText(m3UString);
        var list = masterPlaylist.Streams.ToList();
        return list.ElementAt(list.FindIndex(x => x.Resolution.Height == 720)).Uri;
    }

    /// <summary>
    /// Method returns the Live stream M3U Url from youtube ID.
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    public static async Task<string> GetM3U_Url(string url)
    {
        var content = string.Empty;
        var client = new HttpClient();
        var youtube = new YoutubeClient();
        var result = await youtube.Videos.Streams.GetHttpLiveStreamUrlAsync(url);
        var response = await client.GetAsync(result);
        if (response.IsSuccessStatusCode)
        {
            content = await response.Content.ReadAsStringAsync();
        }

        return content;
    }
    /// <summary>
    /// Method Starts <see cref="MediaElement"/> Playback.
    /// </summary>
    /// <returns></returns>
    private async Task LoadVideo()
    {
        var m3u = await LivePage.GetM3U_Url("F2NreNEmMy4");
        mediaElement.Source = LivePage.ParseM3UPLaylist(m3u);
        mediaElement.Play();
    }

#nullable disable

    #endregion

#if WINDOWS
    /// <summary>
    /// Method is required for switching Full Screen Mode for Windows
    /// </summary>
    private static Microsoft.UI.Windowing.AppWindow GetAppWindow(MauiWinUIWindow window)
    {
        var handle = WinRT.Interop.WindowNative.GetWindowHandle(window);
        var id = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(handle);
        var appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(id);
        return appWindow;
    }
#endif

#nullable enable
    /// <summary>
    /// Method toggles Full Screen Off
    /// </summary>
    public void RestoreScreen()
    {
#if WINDOWS
        var window = GetParentWindow().Handler.PlatformView as MauiWinUIWindow;
        if (window is not null)
        {
            var appWindow = GetAppWindow(window);

            switch (appWindow.Presenter)
            {
                case Microsoft.UI.Windowing.OverlappedPresenter overlappedPresenter:
                    if (overlappedPresenter.State == Microsoft.UI.Windowing.OverlappedPresenterState.Maximized)
                    {
                        overlappedPresenter.SetBorderAndTitleBar(true, true);
                        overlappedPresenter.Restore();
                    }
                    break;
            }
        }
#endif

#if ANDROID
        var activity = Platform.CurrentActivity;

        if (activity == null || activity.Window == null) return;

        Views.WindowCompat.SetDecorFitsSystemWindows(activity.Window, false);
        var windowInsetsControllerCompat = Views.WindowCompat.GetInsetsController(activity.Window, activity.Window.DecorView);
        var types = Views.WindowInsetsCompat.Type.StatusBars() |
                    Views.WindowInsetsCompat.Type.NavigationBars();
        windowInsetsControllerCompat.Show(types);
      
#endif
    }

    /// <summary>
    /// Method toggles Full Screen On
    /// </summary>

    private void SetFullScreen()
    {

#if ANDROID
        var activity = Platform.CurrentActivity;

        if (activity == null || activity.Window == null) return;

        Views.WindowCompat.SetDecorFitsSystemWindows(activity.Window, false);
        var windowInsetsControllerCompat = Views.WindowCompat.GetInsetsController(activity.Window, activity.Window.DecorView);
        var types = Views.WindowInsetsCompat.Type.StatusBars() |
                    Views.WindowInsetsCompat.Type.NavigationBars();

        windowInsetsControllerCompat.SystemBarsBehavior = Views.WindowInsetsControllerCompat.BehaviorShowBarsBySwipe;
        windowInsetsControllerCompat.Hide(types);
#endif

#if WINDOWS
        var window = GetParentWindow().Handler.PlatformView as MauiWinUIWindow;
        if (window is not null)
        {
            var appWindow = GetAppWindow(window);
            switch (appWindow.Presenter)
            {
                case Microsoft.UI.Windowing.OverlappedPresenter overlappedPresenter:
                    overlappedPresenter.SetBorderAndTitleBar(false, false);
                    overlappedPresenter.Maximize();
                    break;
            }
        }
#endif
    }

#nullable disable
}

在app.xaml.cs中还有其他代码可以使其正常工作。

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Application = Microsoft.Maui.Controls.Application;
using Platform = Microsoft.Maui.ApplicationModel.Platform;

#if WINDOWS
using Microsoft.UI;
using Microsoft.UI.Windowing;
using WinRT;
using Microsoft.Maui.Controls;
#endif
namespace NerdNewsNavigator2;

/// <summary>
/// A class that acts as a manager for <see cref="Application"/>
/// </summary>
public partial class App : Application
{
    /// <summary>
    /// This applications Dependancy Injection for <see cref="PositionDataBase"/> class.
    /// </summary>
    public static PositionDataBase PositionData { get; private set; }

    /// <summary>
    /// Initializes a new instance of the <see cref="App"/> class.
    /// </summary>
    /// <param name="positionDataBase"></param>
    public App(PositionDataBase positionDataBase)
    {
        InitializeComponent();
        MainPage = new AppShell();

        // Database Dependancy Injection START
        PositionData = positionDataBase;
        // Database Dependancy Injection END

        LogController.InitializeNavigation(
            page => MainPage!.Navigation.PushModalAsync(page),
            () => MainPage!.Navigation.PopModalAsync());
    }

#nullable enable

    /// <summary>
    /// A method to override the default <see cref="Window"/> behavior.
    /// </summary>
    /// <param name="activationState"></param>
    /// <returns></returns>
    protected override Window CreateWindow(IActivationState? activationState)
    {
        var window = base.CreateWindow(activationState);
        window.Created += (s, e) =>
        {
            //NOTE: Change this to fetch the value true/false according to your app logic.
            SetFullScreen(s, e);
        };
        window.Resumed += (s, e) =>
        {
            SetFullScreen(s, e);
        };

        return window;
    }

    /// <summary>
    /// Method to set Full Screen status.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="eventArgs"></param>
    private static void SetFullScreen(object? sender, EventArgs eventArgs)
    {
        if (sender != null)
        {

#if WINDOWS
            var currentWindow = sender.As<Window>();
            var uiWindow = currentWindow.Handler.PlatformView.As<MauiWinUIWindow>();
            var handle = WinRT.Interop.WindowNative.GetWindowHandle(uiWindow);
            var id = Win32Interop.GetWindowIdFromWindow(handle);
            var appWindow = AppWindow.GetFromWindowId(id);
            switch (appWindow.Presenter)
            {
                case OverlappedPresenter overlappedPresenter:
                    uiWindow.ExtendsContentIntoTitleBar = false;
                    {
                        overlappedPresenter.SetBorderAndTitleBar(true, true);
                        overlappedPresenter.Restore();
                    }
                    break;
            }
#endif
        }
    }

#nullable disable
}

这是一个重复的代码很多,我不喜欢,但它的工作,我会弄清楚这一点后.如果我删除了全屏代码在App.xaml.cs的网页,我有无法正确加载.
控制设置全屏打开和关闭的Android和Windows。我想让它要么自动隐藏或直接添加到Maui媒体元素控件直接在酒吧。

oxcyiej7

oxcyiej71#

好吧,我想通了!它结束了,我需要使用指针移动命令时,使用指针手势识别器,而不是指针移动。这是很简单的,我想通了。示例LivePage.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    x:Class="ControlsTest.View.LivePage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
    xmlns:vm="clr-namespace:ControlsTest.ViewModels"
    Title=""
    x:DataType="vm:LiveViewModel"
    BackgroundColor="Black"
    Loaded="ContentPage_Loaded"
    Shell.NavBarIsVisible="False"
    Unloaded="ContentPage_Unloaded">

    <Shell.BackButtonBehavior>
        <BackButtonBehavior IsEnabled="True" IsVisible="False" />
    </Shell.BackButtonBehavior>

    <Grid>
        <Grid.GestureRecognizers>
            <PointerGestureRecognizer PointerMovedCommand="{Binding Source={RelativeSource AncestorType={x:Type vm:LiveViewModel}}, Path=MovedCommand}" />
        </Grid.GestureRecognizers>
        <toolkit:MediaElement
            x:Name="mediaElement"
            ShouldAutoPlay="True"
            ShouldShowPlaybackControls="True" />
        <ImageButton
            x:Name="btnFullScreen"
            Grid.Row="0"
            Margin="10"
            Clicked="BtnFullScreen_Clicked"
            HeightRequest="40"
            HorizontalOptions="End"
            IsVisible="{Binding Source={RelativeSource AncestorType={x:Type vm:BaseViewModel}}, Path=IsBusy}"
            Source="iconfullscreen.png"
            VerticalOptions="Start"
            WidthRequest="40">
            <ImageButton.Behaviors>
                <toolkit:IconTintColorBehavior TintColor="White" />
            </ImageButton.Behaviors>
        </ImageButton>
    </Grid>

</ContentPage>

LivePage.xaml.cs

using Microsoft.Maui.Controls.PlatformConfiguration;
using Application = Microsoft.Maui.Controls.Application;
using Platform = Microsoft.Maui.ApplicationModel.Platform;

#if ANDROID
using Views = AndroidX.Core.View;
#endif

#if WINDOWS
using Microsoft.UI;
using Microsoft.UI.Windowing;
using WinRT;
using Microsoft.Maui.Controls;
#endif

namespace ControlsTest.View;

public partial class LivePage : ContentPage
{
    private bool _fullScreen = false;

    /// <summary>
    /// Initializes a new instance of <see cref="LivePage"/> class.
    /// </summary>
    /// <param name="LiveViewModel">This classes <see cref="ViewModel"/> from <see cref="LiveViewModel"/></param>
    public LivePage(LiveViewModel viewModel)
    {
        InitializeComponent();
        BindingContext = viewModel;
       
    }

    private void BtnFullScreen_Clicked(object sender, EventArgs e)
    {
        if (_fullScreen)
        {
            _fullScreen = false;
            RestoreScreen();
        }
        else
        {
            SetFullScreen();
            _fullScreen = true;
        }
    }

    /// <summary>
    /// Method overrides <see cref="OnDisappearing"/> to stop playback when leaving a page.
    /// </summary>
    protected override void OnDisappearing()
    {
        mediaElement.Stop();
        mediaElement.ShouldKeepScreenOn = false;
    }
    #region Load/Unload Events
#nullable enable

    /// <summary>
    /// Manages unload event from <see cref="mediaElement"/> after it is unloaded.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public void ContentPage_Unloaded(object? sender, EventArgs e)
    {
        if (sender is null)
        {
            return;
        }
        mediaElement.Handler?.DisconnectHandler();
    }
    /// <summary>
    /// Method Loads Video after page has finished being rendered.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ContentPage_Loaded(object? sender, EventArgs e)
    {
        if (sender is null)
        {
            return;
        }

        _ = LoadVideo();
    }

    /// <summary>
    /// Method returns 720P URL for <see cref="mediaElement"/> to Play.
    /// </summary>
    /// <param name="m3UString"></param>
    /// <returns></returns>
    public static string ParseM3UPLaylist(string m3UString)
    {
        var masterPlaylist = MasterPlaylist.LoadFromText(m3UString);
        var list = masterPlaylist.Streams.ToList();
        return list.ElementAt(list.FindIndex(x => x.Resolution.Height == 720)).Uri;
    }

    /// <summary>
    /// Method returns the Live stream M3U Url from youtube ID.
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    public static async Task<string> GetM3U_Url(string url)
    {
        var content = string.Empty;
        var client = new HttpClient();
        var youtube = new YoutubeClient();
        var result = await youtube.Videos.Streams.GetHttpLiveStreamUrlAsync(url);
        var response = await client.GetAsync(result);
        if (response.IsSuccessStatusCode)
        {
            content = await response.Content.ReadAsStringAsync();
        }

        return content;
    }
    /// <summary>
    /// Method Starts <see cref="MediaElement"/> Playback.
    /// </summary>
    /// <returns></returns>
    private async Task LoadVideo()
    {
        var m3u = await LivePage.GetM3U_Url("F2NreNEmMy4");
        mediaElement.Source = LivePage.ParseM3UPLaylist(m3u);
        mediaElement.Play();
    }

#nullable disable

    #endregion

#if WINDOWS
    /// <summary>
    /// Method is required for switching Full Screen Mode for Windows
    /// </summary>
    private static Microsoft.UI.Windowing.AppWindow GetAppWindow(MauiWinUIWindow window)
    {
        var handle = WinRT.Interop.WindowNative.GetWindowHandle(window);
        var id = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(handle);
        var appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(id);
        return appWindow;
    }
#endif

#nullable enable
    /// <summary>
    /// Method toggles Full Screen Off
    /// </summary>
    public void RestoreScreen()
    {
#if WINDOWS
        var window = GetParentWindow().Handler.PlatformView as MauiWinUIWindow;
        if (window is not null)
        {
            var appWindow = GetAppWindow(window);

            switch (appWindow.Presenter)
            {
                case Microsoft.UI.Windowing.OverlappedPresenter overlappedPresenter:
                    if (overlappedPresenter.State == Microsoft.UI.Windowing.OverlappedPresenterState.Maximized)
                    {
                        overlappedPresenter.SetBorderAndTitleBar(true, true);
                        overlappedPresenter.Restore();
                    }
                    break;
            }
        }
#endif

#if ANDROID
        var activity = Platform.CurrentActivity;

        if (activity == null || activity.Window == null) return;

        Views.WindowCompat.SetDecorFitsSystemWindows(activity.Window, false);
        var windowInsetsControllerCompat = Views.WindowCompat.GetInsetsController(activity.Window, activity.Window.DecorView);
        var types = Views.WindowInsetsCompat.Type.StatusBars() |
                    Views.WindowInsetsCompat.Type.NavigationBars();
        windowInsetsControllerCompat.Show(types);
      
#endif
    }

    /// <summary>
    /// Method toggles Full Screen On
    /// </summary>

    private void SetFullScreen()
    {

#if ANDROID
        var activity = Platform.CurrentActivity;

        if (activity == null || activity.Window == null) return;

        Views.WindowCompat.SetDecorFitsSystemWindows(activity.Window, false);
        var windowInsetsControllerCompat = Views.WindowCompat.GetInsetsController(activity.Window, activity.Window.DecorView);
        var types = Views.WindowInsetsCompat.Type.StatusBars() |
                    Views.WindowInsetsCompat.Type.NavigationBars();

        windowInsetsControllerCompat.SystemBarsBehavior = Views.WindowInsetsControllerCompat.BehaviorShowBarsBySwipe;
        windowInsetsControllerCompat.Hide(types);
#endif

#if WINDOWS
        var window = GetParentWindow().Handler.PlatformView as MauiWinUIWindow;
        if (window is not null)
        {
            var appWindow = GetAppWindow(window);
            switch (appWindow.Presenter)
            {
                case Microsoft.UI.Windowing.OverlappedPresenter overlappedPresenter:
                    overlappedPresenter.SetBorderAndTitleBar(false, false);
                    overlappedPresenter.Maximize();
                    break;
            }
        }
#endif
    }

#nullable disable
}

LiveViewModel.cs

namespace ControlsTest.ViewModels;

public partial class LiveViewModel : BaseViewModel
{
    public LiveViewModel()
    {

    }
    /// <summary>
    /// A Method that passes a Url <see cref="string"/> to <see cref="TabletShowPage"/>
    /// </summary>
    /// <param name="url">A Url <see cref="string"/></param>
    /// <returns></returns>
    [RelayCommand]
    public async Task Moved()
    {
        Debug.WriteLine($"Isbusy status: {IsBusy}", IsBusy);
        if (!IsBusy)
        {
            await Waiting();
        }

    }
}

BaseViewModel.cs

namespace ControlsTest.ViewModels;

public partial class BaseViewModel : ObservableObject
{
    /// <summary>
    /// A <see cref="bool"/> instance managed by this class. 
    /// </summary>
    private bool _isBusy;

    /// <summary>
    /// A <see cref="bool"/> instance managed by this class.
    /// </summary>
    public bool IsBusy
    {
        get => _isBusy;
        set
        {
            if (SetProperty(ref _isBusy, value))
            {
                OnPropertyChanged(nameof(IsNotBusy));
            }
        }
    }

    /// <summary>
    /// A <see cref="bool"/> instance managed by this class.
    /// </summary>
    public bool IsNotBusy => !IsBusy;
    public BaseViewModel() {  }
    public async Task Waiting()
    {
        IsBusy = true;
        await Task.Delay(4000);
        IsBusy = false;
    }
}

App.xaml.cs:这是windows全屏工作所必需的!!!

using Application = Microsoft.Maui.Controls.Application;
using Platform = Microsoft.Maui.ApplicationModel.Platform;

#if WINDOWS
using Microsoft.UI;
using Microsoft.UI.Windowing;
using WinRT;
using Microsoft.Maui.Controls;
#endif

namespace ControlsTest;

public partial class App : Application
{
    public App()
    {
        InitializeComponent();

        MainPage = new AppShell();
    }

#nullable enable

    /// <summary>
    /// A method to override the default <see cref="Window"/> behavior.
    /// </summary>
    /// <param name="activationState"></param>
    /// <returns></returns>
    protected override Window CreateWindow(IActivationState? activationState)
    {
        var window = base.CreateWindow(activationState);
        window.Created += (s, e) =>
        {
            //NOTE: Change this to fetch the value true/false according to your app logic.
            SetFullScreen(s, e);
        };
        window.Resumed += (s, e) =>
        {
            SetFullScreen(s, e);
        };

        return window;
    }

    /// <summary>
    /// Method to set Full Screen status.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="eventArgs"></param>
    private static void SetFullScreen(object? sender, EventArgs eventArgs)
    {
        if (sender != null)
        {

#if WINDOWS
            var currentWindow = sender.As<Window>();
            var uiWindow = currentWindow.Handler.PlatformView.As<MauiWinUIWindow>();
            var handle = WinRT.Interop.WindowNative.GetWindowHandle(uiWindow);
            var id = Win32Interop.GetWindowIdFromWindow(handle);
            var appWindow = AppWindow.GetFromWindowId(id);
            switch (appWindow.Presenter)
            {
                case OverlappedPresenter overlappedPresenter:
                    uiWindow.ExtendsContentIntoTitleBar = false;
                    {
                        overlappedPresenter.SetBorderAndTitleBar(true, true);
                        overlappedPresenter.Restore();
                    }
                    break;
            }
#endif
        }
    }

#nullable disable
}

我相信有一个更好更简单的方法来做到这一点,但这工作,我现在使用它,直到有人想出一个更好的方法。

相关问题