I want to make a loading spin in Xamarin forms. After the login screen, the webview on the main screen takes about 3 seconds to load, at that time I want to have a loading spin.I tried using the acr.userdialogs package but I could only trigger it with a button.
my goal is to work for 3 seconds from the moment the page is opened (without triggering it with a button or something like that.) how can i do that? thanks.
EDIT : (In the code I shared, I can trigger it with the login button, but my aim is to do it without triggering it with a button on the main page.)
`async void btnLoginClick(System.Object sender, System.EventArgs e)
{
if (Connectivity.NetworkAccess == NetworkAccess.Internet)
{
var userName = tbName.Text;
var password = tbPassword.Text;
var serviceUrl = "API";
var paramList = new List<ServiceParameterObject>();
paramList.Add(new ServiceParameterObject("_userCode", userName));
paramList.Add(new ServiceParameterObject("_userPassword", password));
var apiResult = ApiResult.SendPostRequestFromBody(serviceUrl, paramList);
if (apiResult.Status)
{
var user = JsonConvert.DeserializeObject<User>(apiResult.Message);
//Preferences.Set("userName", tbName.Text);
//Preferences.Set("Password", tbPassword.Text);
Preferences.Set("userId", user.Id.ToString());
var userIdCookie = Preferences.Get("userId", String.Empty);
await Navigation.PushAsync(new HomeScreen()); //!!!!!!!!!!!!!!
UserDialogs.Instance.ShowLoading("Yukleniyor...",MaskType.Black);
await Task.Delay(3000);
UserDialogs.Instance.HideLoading();
}
else
{
await DisplayAlert("Uyarı", "Kullanıcı Adınız veya Şifreniz hatalıdır. Lütfen tekrar deneyiniz.", "Tamam");
}`
public partial class HomeScreen : ContentPage
{
public HomeScreen ()
{
InitializeComponent ();
var userIdCookie = Preferences.Get("userId", String.Empty);
if (Connectivity.NetworkAccess == NetworkAccess.Internet)
{
//_userCode = Encrytpion.EncryptString(_userCode,"1234567812345678");
OneSignal.Default.SetExternalUserId(userIdCookie);
webView.Source = "wvsource";
Device.BeginInvokeOnMainThread(async () =>
{
UserDialogs.Instance.ShowLoading("Yukleniyor...", MaskType.Black);
await Task.Delay(3000);
UserDialogs.Instance.HideLoading();
});
}
else
{
DisplayAlert("Uyarı", "İnternet bağlantınız yok. Lütfen Bağlantınızı kontrol edip tekrar deneyiniz", "Tamam");
}
}
i did it.
Related
this method works fine but only issue is that after user enter google email & password, it doesn't go back to HomePage in app. user has to manually tap on close button and than it goes to HomePage inside app
i found similar code online and they all seem to have the same thing. not sure what i am missing
async void OnAuthCompleted(object sender, AuthenticatorCompletedEventArgs e)
{
var authenticator = sender as OAuth2Authenticator;
if (authenticator != null)
{
authenticator.Completed -= OnAuthCompleted;
authenticator.Error -= OnAuthError;
}
User user = null;
if (e.IsAuthenticated)
{
var request = new OAuth2Request("GET", new Uri(Constants.UserInfoUrl), null, e.Account);
var response = await request.GetResponseAsync();
if (response != null)
{
string userJson = await response.GetResponseTextAsync();
user = JsonConvert.DeserializeObject<User>(userJson);
}
if (user != null)
{
store.Delete(account, Constants.AppName);
var route = $"{ nameof(HomePage)}";
await Shell.Current.GoToAsync(route);
}
await store.SaveAsync(account = e.Account, Constants.AppName);
}
}//end of method
android project
[Activity(Label = "CustomUrlSchemeInterceptorActivity", NoHistory = true, LaunchMode = LaunchMode.SingleTop)]
[IntentFilter(
new[] { Intent.ActionView },
Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable },
DataSchemes = new[] { "com.googleusercontent.apps.59233251-abcd" },
DataPath = "/oauth2redirect")]
public class CustomUrlSchemeInterceptorActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Convert Android.Net.Url to Uri
var uri = new Uri(Intent.Data.ToString());
// Load redirectUrl page
AuthenticationState.Authenticator.OnPageLoading(uri);
Finish();
}
}
In my UWP App I can turn on the camera via a button click and can turn it off again. But as soon as I try and turn it back on again I get the following error:
System.Exception: 'The op is invalid.
The op is invalid.'
Here is my code I am using at the moment.
private async void Camera_Click(object sender, RoutedEventArgs e)
{
if (_mediaCapture == null)
{
var cameraDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
var backFacingDevice = cameraDevices
.FirstOrDefault(c => c.EnclosureLocation?.Panel == Windows.Devices.Enumeration.Panel.Back);
var preferredDevice = backFacingDevice ?? cameraDevices.FirstOrDefault();
_mediaCapture = new MediaCapture();
await _mediaCapture.InitializeAsync(
new MediaCaptureInitializationSettings
{
VideoDeviceId = preferredDevice.Id
});
PreviewControl.Source = _mediaCapture;
await _mediaCapture.StartPreviewAsync();
}
else
{
await _mediaCapture.StopPreviewAsync();
}
}
I am really not sure what I am doing wrong here.
Thanks
The problem occurs when you repeatedly call _mediaCapture.StopPreviewAsync().
You can try this:
private async void Button_Click(object sender, RoutedEventArgs e)
{
if (_mediaCapture == null)
{
var cameraDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
var backFacingDevice = cameraDevices
.FirstOrDefault(c => c.EnclosureLocation?.Panel == Windows.Devices.Enumeration.Panel.Back);
var preferredDevice = backFacingDevice ?? cameraDevices.FirstOrDefault();
_mediaCapture = new MediaCapture();
await _mediaCapture.InitializeAsync(
new MediaCaptureInitializationSettings
{
VideoDeviceId = preferredDevice.Id
});
PreviewControl.Source = _mediaCapture;
}
if (_mediaCapture.CameraStreamState==Windows.Media.Devices.CameraStreamState.Streaming)
await _mediaCapture.StopPreviewAsync();
else
await _mediaCapture.StartPreviewAsync();
}
Check if _mediaCapture is null when the button is clicked. If yes, initialize it first.
After this, the code that controls the _mediaCapture state should be performed independently, by checking _mediaCapture.CameraStreamState to determine the current state, and decide whether to start the preview or stop the preview.
Thanks.
Can anybody help me with this code in my Xamarin project. I am trying to set a loading wheel (to signify that an action is happening and to let the user know to wait) when the "Login" button is clicked. For some reason since the function is asynchronous the loading wheel is never set to visible when the API code is run. It just fails to show up when I click login, however, it still does the login function.
// Defined up above in the file
var loginButton = new Button
{
Text = "Login",
};
loginButton.BackgroundColor = Color.Navy;
loginButton.TextColor = Color.White;
loginButton.Clicked += OnLoginButtonClicked;
async void OnLoginButtonClicked(object sender, EventArgs e)
{
loadingWheel.IsVisible = true;
try
{
var restUrl = "*******";
var content = string.Empty;
using (var client = new HttpClient())
{
string body = "{\"UserName\":\"" + usernameEntry.Text + "\", \"Password\":\"" + passwordEntry.Text + "\"}";
var contentType = new StringContent(body, Encoding.UTF8, "application/json");
var result = client.PostAsync(restUrl, contentType).Result;
content = await result.Content.ReadAsStringAsync();
}
if (content.ToLower() != "false")
{
var menuPage = new MenuPage();
NavigationPage = new NavigationPage(new HomePage());
RootPage = new Views.MainPage();
RootPage.Master = menuPage;
RootPage.Detail = NavigationPage;
MainPage = RootPage;
}
else
{
messageLabel.Text = "Username or password incorrect. Please try again.";
passwordEntry.Text = string.Empty;
}
}
catch (Exception ex)
{
messageLabel.Text = "Please check the internet connection for the connectivity.";
}
}
If I comment out the entire try block then the loading wheel does show up. It just does not work with the code in there.
Can anybody help me solve this problem? Thanks.
I think you can try with BeginInvokeOnMainThread
Device.BeginInvokeOnMainThread (() => {
loadingWheel.IsVisible = true;
});
UPDATE
I have also create this REPO... it works without BeginInvodeOnMainThread
public class MyPage6 : ContentPage
{
ActivityIndicator _ac = new ActivityIndicator { IsVisible = false, IsRunning = false };
public MyPage6()
{
Button b = new Button {Text = "Press for ActivityIndicator" };
b.Clicked += B_Clicked;
Content = new StackLayout
{
Children = {
_ac,
b,
new Label { Text = "Hello ContentPage" }
}
};
}
async void B_Clicked(object sender, EventArgs e)
{
_ac.IsRunning = true;
_ac.IsVisible = true;
await Task.Delay(2000);
_ac.IsRunning = false;
_ac.IsVisible = false;
}
}
I am using ZXing.Net camera barcode scanner, xamarin forms, and C# and it appears to be working good. But I have an issue where if I go the the next page via Navigation.PushAsync(), then click the Back Navigation Button, the ZXingScannerPage camera will not reload...(it will only be a still image of the last pic taken)...how do I reload the ZXingScannerPage so that the camera is actively upon pressing the Back Navigation? Is the anyway to refresh the camera view attached to the page?
Use the following code. Stop the scanning as soon as scanning is done. Don't do a manual manuver.
Entry objScanner= new Entry();
objScanner.Placeholder = "Barcode";
objScanner.Keyboard = Keyboard.Numeric;
objScanner.HorizontalOptions = LayoutOptions.StartAndExpand;
objScanner.WidthRequest = Application.Current.MainPage.Width - 40;
objScanner.SetBinding(Entry.TextProperty, "ElementValue", BindingMode.TwoWay);
objScanner.BindingContext = control;
layout.Children.Add(objScanner);
objScanner.Focused += async (s, e) =>
{
var scanPage = new ZXingScannerPage();
await Navigation.PushAsync(scanPage);
scanPage.OnScanResult += (result) =>
{
// Stop scanning
scanPage.IsScanning = false;
// Pop the page and show the result
Device.BeginInvokeOnMainThread(async () =>
{
await Navigation.PopAsync();
objScanner.Text = result.Text;
// await DisplayAlert("Scanned Barcode", result.Text, "OK");
});
};
};
The solution that I found that works for me to allow back navigation using ZXing Scanner page is to remove all instances of ZXing Scanner page before push a new instance of the page to the navigation stack. In your navigation.cs, when you get ready to push the page, use this:
foreach(var x in _navigation.Navigation.NavigationStack.ToList())
{
if((x.GetType() == typeof(/* name of your scanner page */)))
{
_navigation.Navigation.RemovePage(x);
}
}
var page = new /* your scanner page */();
_navigation.PushAsync( /* your scanner page */);
I have found a workaround which may be useful.
On content page, create a local content variable.
If I instantiate the scanner and add it to Content in OnAppearing method, then set Content = null OnDisappearing method. Nulling the Content seems to trigger the necessary cleanups up the stack.
Here's my code:
public class QrCodeScanPage : ZXingScannerPage
{
View _content;
public QrCodeScanPage()
{
InitScanner();
}
void InitScanner()
{
IsAnalyzing = true;
IsScanning = true;
DefaultOverlayTopText = "Align the barcode within the frame";
DefaultOverlayBottomText = string.Empty;
OnScanResult += ScanPage_OnScanResult;
Title = "Scan Code";
var item = new ToolbarItem
{
Text = "Cancel",
Command = new Command(async () =>
{
IsScanning = false;
await Navigation.PopAsync();
})
};
if (Device.RuntimePlatform != Device.iOS)
item.IconImageSource = "toolbar_close.png";
ToolbarItems.Add(item);
}
void ScanPage_OnScanResult(ZXing.Result result)
{
Device.BeginInvokeOnMainThread(async () =>
{
IsScanning = false;
IsAnalyzing = false;
await Navigation.PushAsync(new QrCodeScanResultPage());
});
}
protected override void OnAppearing()
{
IsScanning = true;
IsAnalyzing = true;
base.OnAppearing();
if (Content != null)
{
_content = Content;
}
if (Content == null)
{
Content = _content;
}
}
protected override void OnDisappearing()
{
base.OnDisappearing();
Content = null;
}
}
Hi I have read other tutorials but could not figure it out. I am running a task and when task is completed I want to hide the current form and load another form but It hangs and nothing is displayed. This is my code please guide me -
public Loading()
{
InitializeComponent();
Shown += Loading_Shown;
}
private void Loading_Shown(object sender, EventArgs e)
{
label2.Text = "Step 1...";
Task.Run(() =>
{
if (Directory.Exists(contentPath))
{
filePresent = false;
}
if (filesPresent == false)
{
BeginInvoke(
(MethodInvoker)delegate
{
label2.Text = "Downloading Files...";
}
);
Directory.CreateDirectory(contentPath);
Home form = new Home();
form.Visible = true;
}
else
{
Home form = new Home();
form.Visible = true;
}
});
}
The other form loads half and screen hangs. Please guide me how to continue with this. Thanks
You don't create the second form "when [the] task is completed", but inside that task. So you create the second form on a different thread than the first one. This is a bad idea.
One solution is to make Loading_Shown an async method and await the task. Then, when the task really has completed and control flow returned to the original ui thread, you can create the second form:
private async void Loading_Shown(object sender, EventArgs e)
{
label2.Text = "Step 1...";
await Task.Run(() =>
{
// different thread
filePresent = Directory.Exists(contentPath);
if (!filePresent) Directory.CreateDirectory(contentPath);
});
// back on UI thread
if (!filesPresent)
{
label2.Text = "Downloading Files..."; });
Home form = new Home();
form.Visible = true;
}
else{
Home form = new Home();
form.Visible = true;
}
}