wake-up-neo.com

Xamarin.Forms - Wie wird ein ActivityIndicator programmgesteuert in die Mitte eines StackLayouts eingeblendet

Ich möchte meinen ActivityIndicator in der Mitte meines Formulars überlagern, aber ich bin mir nicht ganz sicher, wie ich dieses Problem lösen kann. 

Ich mache das im Code und das nächste Beispiel, das ich gefunden habe, ist die Verwendung von XAML, die ein Gitter wie unten gezeigt verwendet: 

 <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>
25
Chad Bonthuys

Wenn Sie Probleme mit RelativeLayout haben, können Sie auch AbsoluteLayout verwenden, das in einem ähnlichen Kontext funktioniert. Beispielcode unten:

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

Wenn Sie ein vollständiges Funktionsbeispiel möchten, habe ich ein verfügbares @ https://github.com/teamtam/xamarin-forms-timesheet

22
TeamTam

antwort von accpetable, aber ich habe eine Erweiterung für alle Contentpage geschrieben. Ich denke es könnte schön sein.

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

Anmerkung: IsWorking muss Mitglied von ViewModel (implementierte INotifyProppertyChanged ) - Eigenschaft sein.

Erweiterungsseite ctor letzte Anweisung aufrufen.

this.AddProgressDisplay();
10
Nuri YILMAZ

Sie müssen ein absolutes Layout verwenden. Folgen Sie der folgenden Hierarchie des Layouts:

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

Damit wird die Aktivitätsanzeige in der Mitte eines Stack-Layouts eingeblendet.

6

Ja .. Sie sollten Ihr Stacklayout innerhalb des relativen Layouts einpacken. Ich habe das von Ihnen gegebene Beispiel bereits durchgearbeitet und meine Anforderung durch Formatieren meiner XAML als Code unten erfüllt

XAML-Code

<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> 
6
Femil Shajin

Hier ist eine etwas mehr anpassbare Version der Nuri YILMAZ-Version.

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

Sie können das Aktivitätskennzeichen auch im absoluten Layout verwenden. und binden Sie die isVisible-Eigenschaft des absoluten Layouts an isBusy. Unten ist mein Ansatz

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

Die Bindung in der cs-Datei sieht folgendermaßen aus

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

In CODE können Sie folgendes versuchen:

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

Bei einer Breite/Höhe des ActivityIndicator von 32/32 können Sie eine Größe auswählen, die Ihren Anforderungen entspricht, oder die Größe im Fluge berechnen.

Es scheint immer noch Fehler in RelateiveLayout zu geben, was gelegentlich sogar für lösbare Einschränkungen unerwartete Nullzeigerausnahmen auslöst

0
Sten Petrov