Xamarin.Forms.Mac - 加载叠加错误

时间:2018-02-16 17:41:06

标签: xamarin xamarin.forms

前段时间我为Xamarin.Forms创建了一个小库,里面有自定义的ContentPage。这个类里面有一个Loading Overlay方法:

    public async Task ShowLoadingOverlayAsync(string loadingMessage)
    {
        // If there is already an Overlay
        if (LoadingOverlay != null)
        {
            // Update the Text
            await UpdateLoadingOverlayAsync(loadingMessage);
            return;
        }

        // Store the actual content
        var CashedContentView = TheView.Content;

        // Create a Grid to show the actual view and the overlay
        var grid = new Grid();

        // Add the actual view
        grid.Children.Add(CashedContentView);

        // Create the Overlay
        LoadingOverlay = new StandardLoadingOverlay();
        LoadingOverlay.Content.Opacity = opacity;
        LoadingOverlay.LoadingText = loadingMessage;

        // Add the Overlay to the grid
        grid.Children.Add(LoadingOverlay.Content);

        // Set the Grid as the Content
        TheView.Content = grid;
    }

此方法只是在实际视图之上显示LoadingOverlay。有关详细信息,请查看代码,我评论了最重要的操作,以便您更好地理解。

我的Page.xaml看起来像这样:

<?xml version="1.0" encoding="UTF-8"?>
<mvvm:BaseContentPage 
xmlns="http://xamarin.com/schemas/2014/forms" 
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
x:Class="Lama.Forms.Source.UI.Pages.LoginPages.LoginPage"
xmlns:mvvm="clr-namespace:SharpLibrary.Forms.Source.MVVM;assembly=SharpLibrary.Forms"
xmlns:ccEntries="clr-namespace:SharpLibrary.Forms.Source.CustomControls.Entries;assembly=SharpLibrary.Forms"
xmlns:ccLabels="clr-namespace:Gorilla.Forms.Source.UI.CustomControls.Labels"
BackgroundColor="Black"
>
<ContentPage.Content>
    <RelativeLayout
        VerticalOptions="FillAndExpand" 
        HorizontalOptions="FillAndExpand"
        >

        <!-- <Image Style="{StaticResource StandardBackgroundImage}" /> -->
        <ScrollView
            RelativeLayout.WidthConstraint = "{ConstraintExpression Type=RelativeToParent, Property=Width}"
            RelativeLayout.HeightConstraint = "{ConstraintExpression Type=RelativeToParent, Property=Height}" 
            >
            <Frame BackgroundColor="Transparent" HasShadow="false" Padding="0">

            <StackLayout  
                Margin="0, 200, 0, 0"
                VerticalOptions="Center"
                    HorizontalOptions="Center"
                    WidthRequest="400">

                <ccEntries:IconedRoundedEntry x:Name="txtEmail"
                    Text="{Binding Email, Mode=TwoWay}"
                    Icon="{Binding EmailIcon}"
                    TextColor="White"
                    Placeholder="Email"
                    HorizontalOptions="FillAndExpand"
                    BackgroundColor="{StaticResource LamaStandardColor1}"
                    />

                <ccEntries:IconedRoundedEntry x:Name="txtPassword"
                    Text="{Binding Password, Mode=TwoWay}"
                    Icon="{Binding PasswordIcon}"
                    TextColor="White"
                    Placeholder="Password"
                    IsPassword="True"
                    HorizontalOptions="FillAndExpand"
                    BackgroundColor="{StaticResource LamaStandardColor1}"
                    />

                <Button Style="{StaticResource RedButton}" x:Name="btnLogin"
                    Text="LOGIN" 
                    Margin="0,30,0,0" 
                    Command="{Binding LoginCommand}" />

                <Label Text="No Account yet? Register now" TextColor="White" HorizontalOptions="Center">
                    <Label.GestureRecognizers>
                        <TapGestureRecognizer Command="{Binding CreateAccountCommand}"/>
                    </Label.GestureRecognizers>
                </Label>

                </StackLayout>
            </Frame>
        </ScrollView>
    </RelativeLayout>
</ContentPage.Content>
</mvvm:BaseContentPage>

因此,详细信息中,Method存储实际内容,创建网格,添加存储的内容,最后在顶部显示LoadingOverlay。 这非常适合作为Xamarin.Forms.iOS应用程序,但是当我运行与Xamarin.Forms.Mac项目完全相同的代码时,存储的内容会在显示加载叠加时消失。

确定有一个HideLoadingOverlay方法,其中LoadingOverlay消失,存储的内容再次作为主内容返回..这在iOS和MacOS上按预期工作。

所以我的猜测是,Xamarin.Forms.MacOS框架中有一个未实现的方法/属性阻止了我的计划。

也许有人看到或知道我不知道的事情。 谢谢你的帮助!

1 个答案:

答案 0 :(得分:0)

所以我终于找到了一种更好的方法来实现加载叠加。

首先:WWW的远端飞机建议做上述&#34; Hack&#34;实现这样的Overlay,但我的解决方案更高效,更高效,更容易理解。我也发现使用&#34;坏&#34;方式,并在您的视图中有一个更大的图像,例如作为标题的iamge,每当Overlay出现重新加载图像时它都会尝试。这导致完全滞后的UI和恼人的加载时间。在我的解决方案中,这个案例完全被删除了。

我的方式需要实际视图来包含容器。因为我希望我的所有视图能够显示Overlay,所以我创建了一个Templated ContentPage和BaseViewModel,但为了简单起见,我将展示它没有基类。

注意:我将Views包装在RelativeLayout中,因此很容易让View填满整个屏幕。

首先,将容器添加到您的视图

<!-- This is the Content of your View -->
<Grid .../>

<!-- The empty Content for the Loading Overlay -->
<ContentView x:Name="CvOverlayContainer" BackgroundColor="Transparent" IsVisible="false"
    RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent,Property=Width,Factor=1,Constant=0}"
    RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent,Property=Height,Factor=1,Constant=0}"/>

注意: OverlayContainer必须是隐身的,否则它会预先假定手势被识别

接下来,ViewModel需要一个可用于显示/隐藏LoadingOverlay的对象:

public ContentView LoadingOverlayContainer { get; set; }

在我们的View的Code-Behind文件中设置ViewModel时,将初始化此ContentView:

// Set the ViewModel
ViewModel = new MainPageViewModel(this)
{
    LoadingOverlayContainer =  CvOverlayContainer
};

最后我们现在可以显示Overlay:

public async Task ShowLoadingOverlayAsync(string loadingMessage)
    {
        // If there is already an Overlay
        if (LoadingOverlay != null)
        {
            // Update the Text
            await UpdateLoadingOverlayAsync(loadingMessage);
            return;
        }

        // Create the Overlay
        LoadingOverlay = new StandardLoadingOverlay();

        LoadingOverlayContainer.IsVisible = true;
        LoadingOverlayContainer.Content = LoadingOverlay.Content;
    }

    public async Task UpdateLoadingOverlayAsync(string loadingMessage)
    {
        if (LoadingOverlay != null)
        {
            LoadingOverlay.LoadingText = loadingMessage;
        }
    }

    public async Task HideLoadingOverlayAsync()
    {
        if (LoadingOverlay == null)
        {
            return;
        }

        // Fade out the Overlay
        await LoadingOverlay.Content.FadeTo(0, 300);

        // Release the Memory
        LoadingOverlay = null;

        // Set the Container as invisible again, so that the UI is recognizable for gestures
        LoadingOverlayContainer.IsVisible = false;

    }

也许此解决方案可以帮助某人实施自己的叠加层