2014-07-22 19 views
21

Voglio sovrapporre il mio ActivityIndicator nel mezzo del mio modulo ma non sono del tutto sicuro di come posso fare questo, presumo di aver bisogno di avvolgere il mio layout di stack in un layout relativo?Xamarin.Forms - Come sovrapporre un ActivityIndicator nel mezzo di uno StackLayout a livello di programmazione

sto facendo questo nel codice e l'esempio più vicino che ho trovato è utilizzare XAML che utilizza una griglia come si vede qui sotto:

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

risposta

22

Se avete problemi con RelativeLayout, è anche possibile utilizzare AbsoluteLayout che lavora in un contesto simile. Il codice di esempio qui di seguito:

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

Se volete un esempio di lavoro pieno, ho fatto uno disponibile @https://github.com/teamtam/xamarin-forms-timesheet

+1

Una soluzione semplice, grazie !! –

+0

Cosa succede se il mio stacklayout è stato spostato in griglia? –

+0

In teoria dovrebbe andare bene, anche se ho già riscontrato problemi con i layout nidificati una volta che iniziano a diventare più profondi di 2-3. Quindi il tuo stack di layout sarebbe simile a questo, immagino (non mi sembra possibile formattare commenti): (1) AbsoluteLayout per indicatore di caricamento (2) tuo GridLayout (3) tuo StackLayout ... il tuo GridLayout sarà al stessa profondità dell'indicatore di caricamento – TeamTam

5

Sì .. Si dovrebbe avvolgere la stackLayout all'interno di layout relativa .. Ho sono già passati attraverso l'esempio che avete dato e acheived mia richiesta formattando il mio XAML come sottostante codice

codice 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

Grazie, cosa è che io non sto usando XAML mia pagina è costruita dal codice, quindi voglio ottenere gli stessi risultati, ma programmaticamente –

0

Nel codice è possibile provare questo:

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

Supponendo larghezza/altezza del ActivityIndicator di 32/32, si può scegliere una dimensione che si adatta alle vostre esigenze o calcolare la dimensione al volo.

Ci sembrano essere ancora bug nel RelateiveLayout, getta inaspettate eccezioni puntatore nullo in alcune occasioni, anche per i vincoli risolvibili

+1

Hi Sten, Grazie per la risposta.Quando provo ad aggiungere elementi al layout relativo come sopra la soluzione proposta sopra sto ricevendo un errore di chiamata ambigua .. Come indicato nel seguente post, sto cercando di risolvere questo come sembra Per poter utilizzare l'inizializzatore dell'oggetto per Figli, dovrai passare le tue espressioni o i tuoi limiti, tornerò una volta che ho provato alcune cose http://stackoverflow.com/questions/23963658/xamarin-forms-vertical-align-image-at- bottom-programmatically –

4

risposta accpetable ma ho scritto un estensioni per tutti contentpage. Penso che potrebbe essere carino.

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

Nota: IsWorking deve essere membro del ViewModel (implementato INotifyProppertyChanged) proprietà.

Call extension page ctor ultima istruzione.

this.AddProgressDisplay(); 
+0

Molto bello! Non sono sicuro del motivo per cui non ci sono più voti positivi. – Helzgate

4

È necessario utilizzare il layout assoluto. Seguire la seguente gerarchia di layout:

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

Con questo l'indicatore di attività verrà sovrapposto nel bel mezzo di un layout stack.

0

È inoltre possibile utilizzare l'indicatore di attività all'interno del layout assoluto. e associare la proprietà isVisible del layout assoluto a isBusy. Qui di seguito è il mio approccio

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

Il legame nel file cs assomiglia

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