2014-07-22 14 views
21

Chcę umieścić mój ActivityIndicator w środku mojego formularza, ale nie jestem do końca pewien, jak mogę to zrobić, zakładam, że muszę zawijam układ stosu we względny układ?Xamarin.Forms - Jak nakładać ActivityIndicator w programie StackLayout programowo

Robię to w kodzie i najbliższy przykład znalazłem się przy użyciu XAML, który korzysta z sieci, jak widać poniżej:

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

Odpowiedz

22

Jeśli masz problemy z RelativeLayout, można również użyć AbsoluteLayout który działa w podobnym kontekście. Przykładowy kod poniżej:

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

Jeśli chcesz pełne pracy przykład, zrobiłem jedną dostępną @https://github.com/teamtam/xamarin-forms-timesheet

+1

Proste rozwiązanie, dziękuję !! –

+0

Co, gdybym miał mój stacklayout owinięty w gridlayout? –

+0

Teoretycznie powinny być w porządku, chociaż już wcześniej miałem problemy z układami zagnieżdżonymi, gdy zaczynają dostawać więcej niż 2-3 głębokości. Tak więc Twój układ może wyglądać mniej więcej tak, jak bym to sobie wyobrażał (przykro mi, nie może formatować komentarzy): (1) AbsoluteLayout dla wskaźnika ładowania (2) twojego GridLayout (3) twojego StackLayout ... twój GridLayout będzie na ta sama głębokość co wskaźnik ładowania – TeamTam

5

Tak .. Należy owinąć stacklayout wewnątrz układzie względnym .. I przeszły już na przykładzie którego dałeś i acheived moje wymaganie przez formatowanie mój XAML jak poniżej kod

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

Dzięki, Coś jest nie używam XAML moja strona jest zbudowana z kodu, więc chcę, aby osiągnąć takie same wyniki, ale programowo –

0

w kodzie można spróbować to:

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

Zakładając szerokość/wysokość ActivityIndicator od 32/32, można wybrać rozmiar, który pasuje do Twoich potrzeb lub obliczyć wielkość w locie.

Nadal wydaje się być błędy w RelateiveLayout, rzuca nieoczekiwane wyjątki pustego wskaźnika niekiedy nawet rozwiązywalnych ograniczeń

+1

Hi Sten, Dzięki za odpowiedź.Kiedy próbuję dodać elementy do względnego układu, jak na twoje proponowane rozwiązanie powyżej otrzymuję niejednoznaczny błąd połączenia .. Jak wskazano w poniższym wpisie obecnie próbuję rozwiązać ten problem, ponieważ wydaje się, Aby użyć inicjatora obiektu dla Dzieci, musisz podać swoje wyrażenia lub ograniczenia, powrócę, gdy przetestuję kilka rzeczy http://stackoverflow.com/questions/23963658/xamarin-forms-vertical-align-image-at- z dołu programowo –

4

Ładne, niewielkie odpowiedź ale napisałem rozszerzenia dla wszystkich contentpage. Myślę, że to mogłoby być miłe.

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

Uwaga: IsWorking musi być członkiem ViewModel (realizowane INotifyProppertyChanged) nieruchomości.

Ostatnia strona oświadczenia o rozszerzeniu strony połączenia.

this.AddProgressDisplay(); 
+0

Bardzo ładne! Nie wiem, dlaczego nie ma więcej głosów wstępnych. – Helzgate

4

Musisz użyć układu absolutnego. Zastosuj następującą hierarchię układu:

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

W ten sposób wskaźnik aktywności zostanie nałożony na środek układu stosu.

0

Możesz również użyć wskaźnika aktywności wewnątrz układu absolutnego. i zwiąż właściwość isVisible absolutnego układu do isBusy. Poniżej jest moje podejście

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

Wiązanie w pliku cs wygląda jak

 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); 
Powiązane problemy