Vraag Xamarin.Forms - Hoe u een ActivityIndicator in het midden van een StackLayout programmatisch overlapt


Ik wil mijn ActivityIndicator in het midden van mijn formulier plaatsen, maar ik weet niet precies hoe ik dit kan aanpakken. Ik neem aan dat ik mijn stapellay-out in een relatieve lay-out moet plaatsen?

Ik doe dit in code en het dichtstbijzijnde voorbeeld dat ik heb gevonden is het gebruik van XAML die een raster gebruikt zoals hieronder te zien is:

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

22
2017-07-22 10:58


oorsprong


antwoorden:


Als u problemen ondervindt met RelativeLayout, kunt u ook AbsoluteLayout gebruiken dat in een vergelijkbare context werkt. Voorbeeldcode hieronder:

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

Als je een volledig werkend voorbeeld wilt, heb ik er een beschikbaar gemaakt @ https://github.com/teamtam/xamarin-forms-timesheet 


22
2017-10-18 03:47



acceptabel antwoord, maar ik heb een extensie geschreven voor alle contentpagina's. Ik denk dat het leuk zou kunnen zijn.

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

Opmerking: Werkt moet lid zijn van ViewModel (geïmplementeerd INotifyProppertyChanged) eigendom.

Oproep-extensie pagina ctor laatste instructie.

this.AddProgressDisplay();

6
2017-08-26 08:58



U moet de absolute lay-out gebruiken. Volg de volgende hiërarchie van de lay-out:

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

Hiermee wordt de activiteitsindicator in het midden van een stapellay-out bedekt.


6
2017-09-20 14:33



Ja .. Je moet je stapel in relatieve lay-out inpakken. Ik heb het voorbeeld dat je hebt gegeven al doorgenomen en heb mijn vereiste bereikt door mijn XAML op te maken zoals hieronder staat

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> 

5
2017-07-22 14:24



In CODE kunt u dit proberen:

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

Uitgaande van de breedte / hoogte van de ActivityIndicator van 32/32, kunt u een formaat kiezen dat aan uw behoeften voldoet of het formaat tijdens de vlucht berekenen.

Er lijken nog steeds bugs in RelateiveLayout te zijn, het gooit soms onverwachte nul-wijzeruitzonderingen, zelfs voor oplosbare beperkingen


0
2018-04-11 11:23



U kunt de activiteitsindicator ook gebruiken in de absolute lay-out. en bind de eigenschap isVisible van absolute lay-out aan isBusy. Hieronder is mijn aanpak

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

De binding in het cs-bestand lijkt op

        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