2014-07-22 5 views
21

Ich möchte meinen ActivityIndicator mitten in meinem Formular überlagern, aber ich bin mir nicht ganz sicher, wie ich das anstellen kann, ich nehme an, dass ich das tun muss Umwickeln Sie mein Stack-Layout in einem relativen Layout?Xamarin.Forms - Wie man einen ActivityIndicator in der Mitte eines StackLayout programmgesteuert überlagert

ich tun dies in Code bin und das nächste Beispiel, das ich gefunden habe, ist XAML, die ein Gitter verwendet, wie unten zu sehen:

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

Antwort

22

Wenn Sie Probleme mit RelativeLayout haben, können Sie auch AbsoluteLayout verwenden, die 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 einen vollständigen Arbeits Beispiel möchte ich eine zur Verfügung gestellt haben @https://github.com/teamtam/xamarin-forms-timesheet

+1

Eine einfache Lösung, danke !! –

+0

Was wäre, wenn ich mein Stacklayout im Gitternetz eingepackt hätte? –

+0

Sollte theoretisch in Ordnung sein, obwohl ich Probleme mit verschachtelten Layouts zuvor erlebt habe, sobald sie beginnen, mehr als 2-3 tief zu bekommen. So würde Ihr Layoutstapel ungefähr so ​​aussehen, wie ich es mir vorstelle (Entschuldigung kann nicht scheinen, Kommentare zu formatieren): (1) AbsoluteLayout zum Laden des Indikators (2) Ihr GridLayout (3) Ihr StackLayout ... Ihr GridLayout wird an der gleiche Tiefe wie die Ladeanzeige – TeamTam

5

Ja .. Sie sollten Ihre stacklayout innen relativ Layout wickeln .. I bereits durch das Beispiel gegangen, die Sie gegeben haben, und meine Anforderung acheived durch meine XAML Formatierung wie unten Code

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

Danke, ist, dass ich nicht XAML bin mit meiner Seite aus dem Code aufgebaut ist, so möchte ich die gleichen Ergebnisse erzielen, aber programmatisch –

0

In CODE können Sie dies 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))); 

Breite/Höhe des ActivityIndicator von 32/32 Unter der Annahme, können Sie eine Größe wählen, die Ihren Bedürfnissen entspricht oder die Größe on the fly berechnen.

Es scheint immer noch Fehler in RelateiveLayout zu sein, wirft es unerwartete Null-Zeiger gelegentlich Ausnahmen, auch für auflösbar Zwänge

+1

Hallo Sten, Danke für die Antwort.Wenn ich versuche, Elemente zu dem relativen Layout gemäß Ihrer vorgeschlagenen Lösung oben hinzuzufügen, erhalte ich einen mehrdeutigen Anruffehler. Wie im folgenden Beitrag beschrieben, versuche ich derzeit, dies zu lösen, wie es scheint, um den Objektinitialisierer zu verwenden Kinder, müssen Sie Ihre Ausdrücke oder Einschränkungen übergeben, werde ich zurückkehren, sobald ich ein paar Dinge getestet habe http://StackOverflow.com/Questions/23963658/xamarin-forms-vertical-align-image-at- unten programmatisch –

4

accpetable Antwort, aber ich schrieb eine Erweiterungen für alle Content. Ich denke, es könnte nett 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; 
    } 

Bemerkung: IsWorking Mitglied Ansichtsmodell sein muss (implementiert INotifyProppertyChanged) Eigenschaft.

Anruferweiterung Seite ctor letzte Anweisung.

this.AddProgressDisplay(); 
+0

Sehr schön! Nicht sicher, warum es nicht mehr Ups gibt. – Helzgate

4

Sie müssen das absolute 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 der Aktivitätsindikator in der Mitte eines Stacklayouts eingeblendet.

0

Sie können den Aktivitätsindikator 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 in der cs-Datei Bindung sieht aus wie

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