Ксамарин.Формы-как наложить ActivityIndicator в середине StackLayout программно
Я хочу наложить свой ActivityIndicator в середине моей формы, но я не совсем уверен, как я могу это сделать, я предполагаю, что мне нужно обернуть мой макет стека в относительный макет ?
Я делаю это в коде, и ближайший пример, который я нашел, - это использование XAML, который использует сетку, как показано ниже:
<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 ответов:
Если у вас есть проблемы с RelativeLayout, вы также можете использовать AbsoluteLayout, который работает в аналогичном контексте. Пример кода ниже:
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);Если вам нужен полный рабочий пример, я сделал его доступным @ https://github.com/teamtam/xamarin-forms-timesheet
Приемлемый ответ, но я написал расширения для всех страниц контента. Я думаю, это было бы неплохо.
Замечание: IsWorking должен быть членом свойства ViewModel (implementedINotifyProppertyChanged ).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; }Вызов страницы расширения ctor последнее утверждение.
this.AddProgressDisplay();
Вам нужно использовать абсолютную компоновку. Следуйте следующей иерархии макета:
<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>При этом индикатор активности будет наложен в середине макета стека.
Да.. Вы должны обернуть свой stacklayout внутри относительной компоновки.. Я уже прошел через пример, который вы привели, и достиг моего требования, форматируя мой XAML, как показано ниже кода
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>
В коде вы можете попробовать следующее:
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)));Предполагая ширину / высоту индикатора ActivityIndicator 32/32, вы можете выбрать размер, который соответствует вашим потребностям, или вычислить размер на лету.
Похоже, что в RelateiveLayout все еще есть ошибки, он иногда выдает неожиданные исключения нулевого указателя, даже для разрешимых ограничений
Вы также можете использовать индикатор активности внутри абсолютного макета. и свяжите свойство isVisible абсолютной компоновки с isBusy. Ниже приведен мой подход
<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>Привязка в cs-файле выглядит как
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);
Comments