Xamarin.Formulaires - comment superposer une ActivityIndicator au milieu d'un StackLayout programmatically
je veux superposer mon ActivityIndicator au milieu de ma forme mais je ne suis pas entièrement sûr comment je peux faire cela, je suppose que je dois envelopper ma mise en page de la pile dans une mise en page relative ?
je le fais en code et l'exemple le plus proche que j'ai trouvé est en utilisant XAML qui utilise une grille comme vu ci-dessous:
<ScrollView BackgroundColor="#d3d6db">
<RelativeLayout
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<StackLayout Orientation="Vertical"
VerticalOptions="FillAndExpand"
Padding="10"
RelativeLayout.XConstraint="{ConstraintExpression Type=Constant, Constant=0}"
RelativeLayout.YConstraint="{ConstraintExpression Type=Constant, Constant=0}">
<Grid x:Name="SegmentGrid"
RowSpacing="10"
ColumnSpacing="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
</Grid>
<WebView BackgroundColor="White" VerticalOptions="FillAndExpand" Source="{Binding DescriptionHtml}" />
</StackLayout>
<ActivityIndicator IsVisible="{Binding IsBusy}"
IsRunning="{Binding IsBusy}"
Color="Black"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent,
Property=Height,
Factor=0.33}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent,
Property=Height,
Factor=0.33}" />
</RelativeLayout>
</ScrollView>
6 réponses
Si vous avez des problèmes avec RelativeLayout, vous pouvez également utiliser AbsoluteLayout qui fonctionne dans un contexte similaire. Exemple de code ci-dessous:
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);
Si vous voulez un travail complet exemple, j'ai fait un disponible @ https://github.com/teamtam/xamarin-forms-timesheet
réponse accpetable mais j'ai écrit une extension pour toute page de contenu. Je pense que Ça pourrait être sympa.
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;
}
Remarque: IsWorking doit être membre de ViewModel (implémenté INotifyProppertyChanged) propriété.
page d'extension de L'appel ctor dernier énoncé.
this.AddProgressDisplay();
Vous devez utiliser la disposition absolue. Suivre la hiérarchie suivante de la mise en page:
<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>
avec cela l'indicateur d'activité sera superposé au milieu d'une disposition de pile.
Oui.. Vous devriez envelopper votre stacklayout dans la disposition relative.. J'ai déjà passé en revue l'exemple que vous avez donné et j'ai reçu mon exigence en formatant mon XAML comme ci-dessous code
Code XAML
<RelativeLayout ...>
<StackLayout ...>
<ActivityIndicator IsRunning="false"
Color="Maroon"
BackgroundColor="Black"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent,
Property=Height,
Factor=0.33}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent,
Property=Height,
Factor=0.28}" />
</StackLayout>
</RelativeLayout>
Dans le CODE, vous pouvez essayer ceci:
RelativeLayout relativeLayout = new RelativeLayout ();
StackLayout stack = new StackLayout ();
ActivityIndicator indicator = new ActivityIndicator ();
relativeLayout.Children.Add (stack);
relativeLayout.Children.Add (indicator);
RelativeLayout.SetBoundsConstraint (stack, () => relativeLayout.Bounds);
RelativeLayout.SetBoundsConstraint (indicator,
BoundsConstraint.FromExpression (() =>
new Rectangle (relativeLayout.Width / 2 - 16, relativeLayout.Height / 2 - 16, 32, 32)));
en supposant la largeur / hauteur de l'indicateur D'activité de 32/32, vous pouvez choisir une taille qui correspond à vos besoins ou calculer la taille à la volée.
il semble encore y avoir des bugs dans RelateiveLayout, il lance des exceptions de pointeur null inattendues à l'occasion, même pour des contraintes solubles
Vous pouvez également utiliser l'indicateur d'activité à l'intérieur de la disposition absolue. et lient la propriété isVisible de absolute layout à isBusy. Ci-dessous mon approche
<AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" AbsoluteLayout.LayoutBounds="1, 1, 1, 1"
BackgroundColor="White" Opacity="0.5" AbsoluteLayout.LayoutFlags="All" x:Name="indicatorFrame" IsVisible="false">
<ActivityIndicator x:Name="indicator" IsVisible="true" IsRunning="true" IsEnabled="true"
HorizontalOptions="Center" VerticalOptions="Center" AbsoluteLayout.LayoutBounds="1, 1, 1, 1"
Color="Black" AbsoluteLayout.LayoutFlags="All"
/>
</AbsoluteLayout>
La liaison dans le fichier cs ressemble
indicator.BindingContext = this;
indicator.SetBinding(IsVisibleProperty, "IsBusy", BindingMode.OneWay);
indicator.SetBinding(ActivityIndicator.IsRunningProperty, "IsBusy", BindingMode.OneWay);
indicatorFrame.BindingContext = this;
indicatorFrame.SetBinding(IsVisibleProperty, "IsBusy", BindingMode.OneWay);