34

我想在我的表单中间覆盖我的 ActivityIndi​​cator 但我不完全确定我该怎么做,我假设我需要将我的堆栈布局包装在一个相对布局中?

我在代码中执行此操作,我发现的最接近的示例是使用 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>
4

7 回答 7

25

如果您在使用 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

于 2014-10-18T03:47:07.243 回答
19

有一个可以接受的答案,但我为所有内容页面写了一个扩展,并认为它可能会很好。

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;
}

备注:IsWorking必须是 ViewModel(实现INotifyPropertyChanged)属性的成员。

呼叫扩展页面 ctor 的最后一条语句。

this.AddProgressDisplay();
于 2016-08-26T08:58:15.777 回答
12

您需要使用绝对布局。遵循以下布局层次结构:

<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>

这样,活动指示器将覆盖在堆栈布局的中间。

于 2016-09-20T14:33:05.550 回答
6

是的,您应该将 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> 
于 2014-07-22T12:42:57.270 回答
1

这是 Nuri YILMAZ 版本的更可定制的版本。

public static void AddProgressDisplay(this ContentPage page, string isVisibleProperty = "IsBusy", string bgColor = "#1a1a1ab2")
{
    var content = page.Content;

    var grid = new Grid();
    grid.Children.Add(content);
    var gridProgress = new Grid { BackgroundColor = Color.FromHex(bgColor), 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, isVisibleProperty);
    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;
}
于 2018-12-13T12:29:48.463 回答
0

在代码中你可以试试这个:

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)));

假设 ActivityIndi​​cator 的宽度/高度为 32/32,您可以选择适合您需要的尺寸或即时计算尺寸。

RelateiveLayout 中似乎仍然存在错误,它有时会引发意外的空指针异常,即使对于可解决的约束也是如此

于 2014-07-22T14:24:31.703 回答
0

您还可以在绝对布局中使用活动指示器。并将绝对布局的 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);
于 2017-04-11T11:23:59.187 回答