2
respostas

Dúvida quanto ao ActivityIndicator

Estou fazendo um app, para ir treinando o que aprendi no curso...

No caso, eu coloquei um activityindicator no xaml da tela de login, porém ele não aparece quando clico no botão de login.

Meu código:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="UniApp.View.LoginView"
             BackgroundColor="Yellow">

    <StackLayout VerticalOptions="Center">

        <ActivityIndicator IsVisible="{Binding Aguardar}" IsRunning="{Binding Aguardar}">

        </ActivityIndicator>

        <Label Text="UniApp" TextColor="Black" FontSize="35" HorizontalOptions="Fill" HorizontalTextAlignment="Center"></Label>
        <Frame OutlineColor="Yellow" Margin="15" VerticalOptions="CenterAndExpand">
            <StackLayout Orientation="Vertical">
                <!-- Usuário -->
                <StackLayout Orientation="Vertical">
                    <Label Text="Matrícula:" HorizontalOptions="Center"></Label>
                    <Entry Text="{Binding Matricula}"></Entry>
                </StackLayout>
                <!-- Senha -->
                <StackLayout>
                    <Label Text="Senha:" HorizontalOptions="Center"></Label>
                    <Entry Text="{Binding Senha}" IsPassword="True"></Entry>
                </StackLayout>
            </StackLayout>
        </Frame>
        <Button Text="Entrar" HorizontalOptions="Fill" TextColor="White" BackgroundColor="Black" Command="{Binding FazerLoginCommand}"></Button>
    </StackLayout>

</ContentPage>
public class LoginViewModel : BaseViewModel
    {
        private string matricula;
        private string senha;
        private bool aguardar;
        public ICommand FazerLoginCommand { get; private set; }

        public string Matricula
        {
            get { return matricula; }
            set
            {
                matricula = value;
                ((Command)FazerLoginCommand).ChangeCanExecute();
            }
        }
        public string Senha
        {
            get { return senha; }
            set
            {
                senha = value;
                ((Command)FazerLoginCommand).ChangeCanExecute();
            }
        }
        public bool Aguardar
        {
            get { return aguardar; }
            set
            {
                aguardar = value;
                OnPropertyChanged();
            }
        }

        public LoginViewModel()
        {
            FazerLoginCommand = new Command(() =>
                {
                    var oLoginService = new LoginService();
                    var oLogin = new Login(this.matricula, this.senha);
                    var oUsuario = oLoginService.FazerLogin(oLogin);

                    this.Aguardar = true;

                    DateTime t = DateTime.Now;
                    DateTime tf = DateTime.Now.AddSeconds(3);
                    while (t < tf)
                    {
                        t = DateTime.Now;
                    }

                    // Login efetuado com sucesso
                    if (oUsuario.Inexistente == false)
                        MessagingCenter.Send<Usuario>(oUsuario, "SucessoLogin");
                    else
                        MessagingCenter.Send<LoginException>(new LoginException("Usuário ou senha incorretos!"), "FalhaLogin");

                    this.Aguardar = false;
                },
                () =>
                {
                    return !string.IsNullOrEmpty(matricula) && !string.IsNullOrEmpty(senha);
                }
            );
        }
    }

Minha BaseViewModel é a mesma do curso, por isso não incluirei aqui.

Alguma sugestão?

2 respostas

Olá, José Guilherme

1) Tente forçar o IsVisible e IsRunning do ActivityIndicator para true:

        <ActivityIndicator IsVisible="true" IsRunning="true">
        </ActivityIndicator>

Se ainda assim não aparecer, o problema é do seu layout

2) Se aparecer, tente forçar o aguardar para true:

private bool aguardar = true;
// this.Aguardar = false;

Se ainda assim não aparecer, o problema está no binding do XAML, ou no code behind. Neste caso, poste aqui o LoginView.Xaml.cs para darmos uma olhada.

Então, na sugestão 1, aparece o loader... na sugestão 2, ele também aparece...

testando de novo aqui, reparei que acontece o seguinte: quando eu clico no botão de entrar, é disparado o command FazerLoginCommand. Dentro disso, na minha arrow function, eu seto a propriedade pra true, chamo a função que faz o login (no meu caso é só teste, então ela só verifica a igualdade entre 2 strings), depois eu fiz um timer pra atrasar a execução em 3 segundos para conseguir ver se aparece o loader. O que reparei, é que o loader aparece logo depois que a função de fazerLogin termina, ou seja, o loader aparece na tela juntamente com o DisplayMessage dizendo que o login falhou.

Talvez tenha algum assincronicidade na implícita na arrow function?

xaml.cs:

[XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class LoginView : ContentPage
    {
        public LoginViewModel ViewModel { get; set; }

        public LoginView()
        {
            InitializeComponent();

            this.ViewModel = new LoginViewModel();
            this.BindingContext = this.ViewModel;
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();

            // Mostra mensagem de que o login não foi bem sucedido
            MessagingCenter.Subscribe<LoginException>(this, "FalhaLogin", (exception) =>
                {
                    DisplayAlert("Erro", exception.Message, "OK");
                }
            );
        }

        protected override void OnDisappearing()
        {
            base.OnDisappearing();
            MessagingCenter.Unsubscribe<LoginException>(this, "FalhaLogin");
        }
    }