前段时间我为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框架中有一个未实现的方法/属性阻止了我的计划。
也许有人看到或知道我不知道的事情。 谢谢你的帮助!
答案 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;
}
也许此解决方案可以帮助某人实施自己的叠加层