Xamarin.Forms - How to overlay an ActivityIndicator in the middle of a StackLayout programmatically
If you have problems with RelativeLayout, you can also use AbsoluteLayout which works in a similar context. Sample code below:
var overlay = new AbsoluteLayout();
var content = new StackLayout();
var loadingIndicator = new ActivityIndicator();
AbsoluteLayout.SetLayoutFlags(content, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds(content, new Rectangle(0f, 0f, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
AbsoluteLayout.SetLayoutFlags(loadingIndicator, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds(loadingIndicator, new Rectangle(0.5, 0.5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
overlay.Children.Add(content);
overlay.Children.Add(loadingIndicator);
If you would like a full working example, I have made one available @ https://github.com/teamtam/xamarin-forms-timesheet
There's an acceptable answer but I wrote an extensions for all contentpage and think it could be nice.
public static void AddProgressDisplay (this ContentPage page)
{
var content = page.Content;
var grid = new Grid();
grid.Children.Add(content);
var gridProgress = new Grid { BackgroundColor = Color.FromHex("#64FFE0B2"), Padding = new Thickness(50) };
gridProgress.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
gridProgress.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) });
gridProgress.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
gridProgress.SetBinding(VisualElement.IsVisibleProperty, "IsWorking");
var activity = new ActivityIndicator
{
IsEnabled = true,
IsVisible = true,
HorizontalOptions = LayoutOptions.FillAndExpand,
IsRunning = true
};
gridProgress.Children.Add(activity, 0, 1);
grid.Children.Add(gridProgress);
page.Content = grid;
}
Remark: IsWorking must be member of ViewModel (implemented INotifyPropertyChanged) property.
Call extension page ctor last statement.
this.AddProgressDisplay();
You need to use absolute layout. Follow the following hierarchy of the layout:
<AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<StackLayout AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1">
<!--< Your control design goes here >-->
</StackLayout>
<StackLayout IsVisible="{Binding IsBusy}" Padding="12"
AbsoluteLayout.LayoutFlags="PositionProportional"
AbsoluteLayout.LayoutBounds="0.5,0.5,-1,-1">
<ActivityIndicator IsRunning="{Binding IsBusy}" Color ="#80000000"/>
<Label Text="Loading..." HorizontalOptions="Center" TextColor="White"/>
</StackLayout>
</AbsoluteLayout>
With this the activity indicator will be overlaid in the middle of a stack layout.