Cancel webview navigation is not working, and sometimes it works but makes the webview unresponsive. Any suggestions, I need to get some data from javascript to c#. TIA @JamesMontemagno @candidodmv @MarkWheeldon
Cancel webview navigation event, e.Cancel = true not working.
GoBack() on a custom HybridWebView?
Hello Xamarin Community,
I built myself a Xamarin App with the HybridWebView as described on the official
The problem is, everytime i press the back button of the OS, the app closes. This is not the behaviour I want, as I want the back button to affect the content inside the HybridWebview and go back one page on the website.
Just overriding OnBackButtonPressed() does not do the job, as the custom Hybridwebview has no GoBack() function like the native Webview and derrives just from View.
Is there any possibility to use the back button of the OS to navigate inside the HybridWebview?
The HybridWebview
.
.
public class HybridWebView : View
{
Action<string> action;
public static readonly BindableProperty UriProperty = BindableProperty.Create(
propertyName: "Uri",
returnType: typeof(string),
declaringType: typeof(HybridWebView),
defaultValue: default(string));
public string Uri
{
get { return (string)GetValue(UriProperty); }
set { SetValue(UriProperty, value); }
}
public void RegisterAction(Action<string> callback)
{
action = callback;
}
public void Cleanup()
{
action = null;
}
public void InvokeAction(string data)
{
if (action == null || data == null)
{
return;
}
action.Invoke(data);
}
}
inside the page
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<local:HybridWebView
x:Name="hybridWebView"
BackgroundColor="Black"
Margin="0"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
IsVisible="{Binding IsLoading, Converter={Helpers:InverseBoolConverter}}"
/>
Can you bind the hamburger menu icon in android?
I would like to do something like:
<MasterDetailPage.Master>
<ContentPage Title="Menu" IconImageSource="{Binding MyIcon}" BackgroundColor="#454d58">
But in Android it does not work. Is there a way to achieve that?
How to take a screen shot using HardwareButton (Power + VolumeDown) PROGRAMATICALLY
I want to capture GoogleMap screen shot
GoogleMap.Snapshot is another way to accomplish that but That is written in Java which I don't know how to convert.
https://stackoverflow.com/questions/13773658/capture-screen-shot-of-googlemap-android-api-v2/18093295#18093295
Best Practices for a modular MVVM design
Hello,
I am making this post looking for suggestions or best practices with implementing efficient MVVM design.
I am fairly new to using MVVM even though I’ve been using Xamarin Forms for a bit of time now, I’ve been kicking myself for not using MVVM sooner!
The problem that I am trying to solve is an effective manner for recreating a view in a MVVM fashion that allows for it to be a view composed of multiple subcomponents that are views themselves in a modular way so that these components can be used in other views as needed
Example:
Post(Model)
Posts(List of Post)
PostView(View based on Post)
{ Composed of
Header(view based on Post),
Content(view based on Post),
Footer(view based on Post)
}
Scrollview consisting of List of PostViews derived from Posts
Where the main view (PostView) acts like a container for the subcomponents (Header,content,footer) but all of them work off of the same underlying model (Post)
Question
1. How would I inform a view’s subcomponents like the header, content or footer of it’s underlying model (Post) in a proper MVVM way without the view directly knowing of it’s model?
2. Should the main view (PostView) inform the subcomponents of it’s model through exposure from the ViewModel?
3. Is there a way better or clearer way to implement modular views than my current concept?
Do something when MoveToRegion finished?
I want to run a function when XamarinMap.MoveToRegion's zoom completed. How can i do that?
App Store Connect (Application Loader) publishing failed - Failed to parse altool output.
I'm getting an error when trying to publish an update to my app using the Application Loader on VS. I tried researching on the error but the error itself isn't really clear. It originally worked earlier, but I got a "missing Info.plist value. CFBundleIconName is missing in the bundle" so I simply migrated to asset catalog (didn't use asset catalog for icons before) and now I'm getting this error. I cannot copy and paste the error but a picture of the error can be found below.
Wait for the Image to be uploaded
Hi,
I am using below to save a channel name and logo
I'd like to ask, using below code how can I make sure the photo was fully uploaded before showing the confirmation?
The problem here is when creating a new channel becauuse the file takes time to upload
but the bigger problem is when the user modify the channel because the Image control already has the existing umage and when updating it takes time which confuse the user and make him feel the image was not uploaded
var client = new HttpClient();
client.BaseAddress = new Uri("https://www.domain.com/save_media.php");
var content = new MultipartFormDataContent();
StreamImageSource streamImageSource = (StreamImageSource)viewModel.Image;
System.Threading.CancellationToken cancellationToken = System.Threading.CancellationToken.None;
Task<Stream> task = streamImageSource.Stream(cancellationToken);
Stream stream = task.Result;
var imageContent = new StreamContent(stream);
imageContent.Headers.ContentType = new MediaTypeHeaderValue("image/png");
content.Add(imageContent, "photo", "ChannelImage.png");
content.Add(new StringContent(TextBoxNewChannelName.Text), "\"channel\"");
var response = await client.PostAsync("https://www.domain.com/save_media.php", content);
/////// AFTER LOGO UPDLOADED ////////
Show Image on Image control
/////// AFTER LOGO UPDLOADED ////////
Thanks,
Jassim
If I ask a question and the help is useless...should I just wait????
My last two question on same topic is week old with no objective help!
I installed Xamarin.Forms.InputKit and get the following error from android main activity file
Error CS0234 The type or namespace name 'Platforms' does not exist in the namespace 'Plugin.InputKit'
How to fix Payload contains two or more files with the same destination path 'sqlite3.dll'?
I am getting the following error trying to compile an UWP app:
Schweregrad Code Beschreibung Projekt Datei Zeile Unterdrückungszustand
Fehler Die Ladung enthält mehrere Dateien mit dem gleichen Zielpfad "e_sqlite3.dll". Quelldateien:
C:\Users\chris.nuget\packages\sqlitepclraw.lib.e_sqlite3.v140\1.1.13\runtimes\win10-x64\native\e_sqlite3.dll
C:\Users\chris.nuget\packages\sqlitepclraw.lib.e_sqlite3.v140\1.1.13\runtimes\win10-x86\native\e_sqlite3.dll Retailer.UWP C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Microsoft\VisualStudio\v16.0\AppxPackage\Microsoft.AppXPackage.Targets 1828
I dont find a fix in web. Hopefully someone can help me.
Thanks
Agredo
In a Xamarin UITest, how to get the text color?
I'm working with an Android app. The app is written in Xamarin Forms and I've been told by the developers that looking at the XAML files for the object type won't work because the object is abstracted so it is generic and will be different object type depending on which platform it is compiled for (iOS or Android).
In REPL I can use this command, to find out that it is a TextView.
(output from REPL):
app.Query(x => x.Marked("John Doe").Invoke("getAccessibilityClassName"))
Query for Marked("John Doe").Invoke("getAccessibilityClassName") gave 1 results.
[
[0] "android.widget.TextView"
]
If I go to this web site https://developer.android.com/reference/android/widget/TextView I can scroll through the Public Methods on the right side, and see that there is something called 'getTextColors'. When I try to invoke this, I get a result with nothing in it. What am I doing wrong?
(output from REPL):
app.Query(x => x.Marked("John Doe").Invoke("getTextColors"))
Query for Marked("John Doe").Invoke("getTextColors") gave 1 results.
[
[0] {
changingConfigurations => [
],
colors => [
[0] [
]
],
defaultColor => [
],
states => [
[0] [
]
],
opaque => [
],
stateful => [
]
}
]
I know this is the right TextView, as I've tried the following:
(output from REPL):
app.Query(x => x.Marked("John Doe").Invoke("getText"))
Query for Marked("John Doe").Invoke("getText") gave 1 results.
[
[0] "John Doe"
]app.Query(x => x.Marked("John Doe").Invoke("getTextSize"))
Query for Marked("John Doe").Invoke("getTextSize") gave 1 results.
[
[0] 63
]
I also read somewhere to try 'getCurrentTextColor', but that returns -1
(output from REPL):
app.Query(x => x.Marked("John Doe").Invoke("getCurrentTextColor"))
Query for Marked("John Doe").Invoke("getCurrentTextColor") gave 1 results.
[
[0] -1
]
Thank,
Aracknid
how to allow to upload less than 4 photo
Hi xamarin forum
I have created uploading 4 photo to server however if I try to upload like 2 photos the app crashes anyway here is the code for uploading
Upload.cs
public partial class PostCreationPage : ContentPage
{
public List<t_Post> postslist;
string json;
public PostCreationPage()
{
InitializeComponent();
}
private MediaFile _mediaFile;
private MediaFile _mediaFile2;
private MediaFile _mediaFile3;
private MediaFile _mediaFile4;
List<string> _images = new List<string>();
private async void Upload_File(object sender, EventArgs e)
{
var content = new MultipartFormDataContent();
var content2 = new MultipartFormDataContent();
var content3 = new MultipartFormDataContent();
var content4 = new MultipartFormDataContent();
string userfirstname = App.FirstName;
var page = new LoadingPage();
content.Add(new StreamContent(_mediaFile.GetStream()),
"\"file\"",
$"\"{_mediaFile.Path}\"");
content2.Add(new StreamContent(_mediaFile2.GetStream()),
"\"file\"",
$"\"{_mediaFile2.Path}\"");
content3.Add(new StreamContent(_mediaFile3.GetStream()),
"\"file\"",
$"\"{_mediaFile3.Path}\"");
content4.Add(new StreamContent(_mediaFile4.GetStream()),
"\"file\"",
$"\"{_mediaFile4.Path}\"");
await PopupNavigation.Instance.PushAsync(page);
var httpClient = new HttpClient();
var uploadServiceBaseAddress = "http://xxx.xx.xx.xxx:8087/api/Files/Uploads";
var httpResponseMessage = await httpClient.PostAsync(uploadServiceBaseAddress, content);
var httpResponseMessage2 = await httpClient.PostAsync(uploadServiceBaseAddress, content2);
var Absolutepath_1 = "http://xxx.xx.xx.xxx:8087/Uploads";
var Absolutepath_2 = "http://xxx.xx.xx.xxx:8087/Uploads";
var Absolutepath_3 = "http://xxx.xx.xx.xxx:8087/Uploads";
var Absolutepath_4 = "http://xxx.xx.xx.xxx:8087/Uploads";
var pathToLabel = httpResponseMessage.Content.ReadAsStringAsync().ToString();
var pathToLabel2 = httpResponseMessage2.Content.ReadAsStringAsync().ToString();
string pathName = Path.GetFileName(_mediaFile.Path);
string pathName2 = Path.GetFileName(_mediaFile2.Path);
string pathName3 = Path.GetFileName(_mediaFile3.Path);
string pathName4 = Path.GetFileName(_mediaFile4.Path);
string pathNames = Absolutepath_1 + "/" + pathName;
string pathNames2 = Absolutepath_2 + "/" + pathName2;
string pathNames3 = Absolutepath_3 + "/" + pathName3;
string pathNames4 = Absolutepath_4 + "/" + pathName4;
Pipeline databaseConnect = new Pipeline();
try
{
SqlCommand sqlInsert = new SqlCommand("INSERT INTO tablename(House_Name, Post_Content, Photo, Photo_2, Photo_3, Photo_4, Location, Floor_Area, Price, Bedroom, Toilet_And_Bath, Storey, Uploader, Date_Uploaded) " +
"VALUES(@HouseName, @PostContent, @Photo, @Photo2, @Photo3, @Photo4, @Location, @Price, @Floor, @Bedroom, @TB, @Storey, @Uploader, @DateUploaded)", databaseConnect.connectDB());
sqlInsert.Parameters.AddWithValue("@HouseName", HouseName.Text);
sqlInsert.Parameters.AddWithValue("@PostContent", postContent.Text);
sqlInsert.Parameters.AddWithValue("@Photo", pathNames);
sqlInsert.Parameters.AddWithValue("@Photo2", pathNames2);
sqlInsert.Parameters.AddWithValue("@Photo3", pathNames3);
sqlInsert.Parameters.AddWithValue("@Photo4", pathNames4);
sqlInsert.Parameters.AddWithValue("@Uploader", userfirstname);
sqlInsert.Parameters.AddWithValue("@DateUploaded", DateTime.Now);
sqlInsert.Parameters.AddWithValue("@Location", HouseLocation.Text);
sqlInsert.Parameters.AddWithValue("@Price", HousePrice.Text);
sqlInsert.Parameters.AddWithValue("@Floor", FloorArea.Text);
sqlInsert.Parameters.AddWithValue("@Bedroom", Bedroom.Text);
sqlInsert.Parameters.AddWithValue("@TB", BathToilet.Text);
sqlInsert.Parameters.AddWithValue("@Storey", Storey.Text);
int i = sqlInsert.ExecuteNonQuery();
databaseConnect.connectDB().Close();
await DisplayAlert("Success", "Uploaded to Database.", "OK");
await PopupNavigation.Instance.PopAsync();
await Navigation.PopAsync();
}
catch (Exception ex)
{
}
}
}
}
Thanks in advance
Xamarin.Forms Android FileProvider: Files are opened readonly
Hi,
I have implemented a FileProvider in my Android app to edit PDF/DOCX files and call it from my Xamarin.Forms app via the dependency service.
The files I want to open reside in the private storage of my app.
Certain apps (like Google Docs) open the files in "write-mode", so that changes get saved in my private storage.
Other apps (like Microsoft Word and Adobe Reader) open the files read-only, although I am granting them full write access.
More details about my implementation can be found in this StackOverflow post:
http://stackoverflow.com/questions/42252933/xamarin-forms-android-fileprovider-grantwriteuripermission-not-always-working
Has anybody experienced similar issues?
Change localization based on user country
User has a flag, from where he is from (1 - Slovenia, 2 - Croatia) and I want to change locale and app language based on this flag.
When I'm on login page, user can choose what language he wants by pressing on the flag (button text and labels are translated successfully when this flags are pressed).
Code for changing language on loging page (arg is si or hr (name for slovenian and croatian language)):
private void ExecuteOnLanguageSelectedCommand(string arg)
{
if (arg == null)
return;
DependencyService.Get<ILocalize>().SetLocale(new CultureInfo(arg));
...
On app load, I check if language is set in Application settings or secure storage, if neither, then I go with phone language. This also works as expected, language is changed.
public App()
{
InitializeComponent();
...
CultureInfo ci = null;
string localeFromSS = SecureStorage.GetAsync("locale").Result;
if (localeFromSS != null)
ci = new CultureInfo(localeFromSS);
else if (ApplicationSettings.Locale != null)
ci = new CultureInfo(ApplicationSettings.Locale);
else
ci = DependencyService.Get<ILocalize>().GetCurrentCultureInfo();
DependencyService.Get<ILocalize>().SetLocale(ci);
...
But when user logs in and I want to change app language based on his location, language doesn't change, it stays like it was before. I tried changing language in LoginViewModel inside and outside mainUI thread:
...
string locale = await SecureStorage.GetAsync("locale").ConfigureAwait(false);
DependencyService.Get<ILocalize>().SetLocale(new CultureInfo(locale));
Device.BeginInvokeOnMainThread(async () =>
{
// string locale = await SecureStorage.GetAsync("locale").ConfigureAwait(false);
// DependencyService.Get<ILocalize>().SetLocale(new CultureInfo(locale));
Application.Current.MainPage = new AppShell();
await Shell.Current.GoToAsync("//main").ConfigureAwait(false);
});
...
Tried calling it in auth manager where I get locale info, but nothing changes it.
But when app is closed and opened, so it hits App() in App.xaml.cs constructor it changes language, the strange thing is it works in LoginPage.
Also, this is how I'm rerouting user, when he logs in, if that might help you in some way:
public App()
{
...
var IsLoggedIn = SecureStorage.GetAsync("isLoggedIn").Result;
var HasReadPrivacy = SecureStorage.GetAsync("HasReadPrivacy").Result;
if (ApplicationSettings.HasConnectivity == false)
MainPage = new NoConnectionPage();
else if (IsLoggedIn == "1")
if (HasReadPrivacy == "1")
MainPage = new AppShell();
else
MainPage = new PrivacyPolicyPage();
else
MainPage = new LoginPage();
...
This is code in Android Localize class that I'm calling with dependancyService
public void SetLocale(CultureInfo ci)
{
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;
}
Error: Device could not find component named
I cannot install the application on device no longer.
I have tried:
- change the package name, application name & version number.
- adb uninstall com.myapp.name.
- reboot my physical device
- try to delete manually in Android application manager
- I've tried to search the device files but couldn't find any related information - i have looked for "ExternalStorageDirectory", "com.myapp.namexxx", "com.myapp.name"
this is the Error:
Error: Device could not find component named: com.myapp.name/md5aa90eac5c6d14c19e9c8e7ab0853061c.SplashActivity
The application could not be started. Ensure that the application has been installed to the target device and has a launchable activity (MainLauncher = true).
Additionally, check Build->Configuration Manager to ensure this project is set to Deploy for this configuration.
Couldn't connect debugger. You can see more details in Xamarin Diagnostic output and the full exception on logs.
this is the Diagnostic output end (too long for the post):
D:RunShellCommand: 87899689 am broadcast -a "mono.android.intent.action.PACKAGE_VERSIONS" -e "packages" "Mono.Android.DebugRuntime,Mono.Android.Platform.ApiLevel_28,com.myapp.name" -n "Mono.Android.DebugRuntime/com.xamarin.mono.android.PackageVersions"
D:RunShellCommand: 87899689 setprop "debug.mono.extra" ""
D:RunShellCommand: 87899689 getprop
D:RunShellCommand: 87899689 am start -a "android.intent.action.MAIN" -c "android.intent.category.LAUNCHER" -n "com.myapp.name/md5aa90eac5c6d14c19e9c8e7ab0853061c.SplashActivity"
D:RunShellCommand: 87899689 am broadcast -a "mono.android.intent.action.EXTERNAL_STORAGE_DIRECTORY" -n "Mono.Android.DebugRuntime/com.xamarin.mono.android.ExternalStorageDirectory"
D:RunShellCommand: 87899689 rm -f "/storage/emulated/0/Android/data/com.myapp.name/files/.override/debug.mono.extra"
D:RunShellCommand: 87899689 am broadcast -a "mono.android.intent.action.PACKAGE_VERSIONS" -e "packages" "Mono.Android.DebugRuntime,Mono.Android.Platform.ApiLevel_28,com.myapp.name888" -n "Mono.Android.DebugRuntime/com.xamarin.mono.android.PackageVersions"
D:RunShellCommand: 87899689 date +%s
D:RunShellCommand: 87899689 setprop "debug.mono.extra" "debug=127.0.0.1:29312:29313,timeout=1571762599,loglevel=0,server=y"
D:RunShellCommand: 87899689 getprop
D:RunShellCommand: 87899689 am broadcast -a "mono.android.intent.action.EXTERNAL_STORAGE_DIRECTORY" -n "Mono.Android.DebugRuntime/com.xamarin.mono.android.ExternalStorageDirectory"
D:RunShellCommand: 87899689 am start -a "android.intent.action.MAIN" -c "android.intent.category.LAUNCHER" -n "com.myapp.name888/md5aa90eac5c6d14c19e9c8e7ab0853061c.SplashActivity"
D:RunShellCommand: 87899689 am force-stop com.myapp.name888
D:RunShellCommand: 87899689 setprop "debug.mono.connect" ""
[D:]: TrackDeviceTask got:
[I:]: Got new device list from adb with 0 devices
[D:]: TrackDeviceTask got: 87899689 offline
[I:]: Got new device list from adb with 1 devices
[D:]: TrackDeviceTask got: 87899689 device
[I:]: Got new device list from adb with 1 devices
D:RunShellCommand: 87899689 getprop
D:RunShellCommand: 87899689 am broadcast -a "mono.android.intent.action.PACKAGE_VERSIONS" -e "packages" "Mono.Android.DebugRuntime,Mono.Android.Platform.ApiLevel_28,com.myapp.name" -n "Mono.Android.DebugRuntime/com.xamarin.mono.android.PackageVersions"
D:RunShellCommand: 87899689 date +%s
D:RunShellCommand: 87899689 setprop "debug.mono.extra" "debug=127.0.0.1:29314:29315,timeout=1571762881,loglevel=0,server=y"
D:RunShellCommand: 87899689 getprop
D:RunShellCommand: 87899689 am broadcast -a "mono.android.intent.action.EXTERNAL_STORAGE_DIRECTORY" -n "Mono.Android.DebugRuntime/com.xamarin.mono.android.ExternalStorageDirectory"
D:RunShellCommand: 87899689 am start -a "android.intent.action.MAIN" -c "android.intent.category.LAUNCHER" -n "com.myapp.name/md5aa90eac5c6d14c19e9c8e7ab0853061c.SplashActivity"
D:RunShellCommand: 87899689 am force-stop com.myapp.name
D:RunShellCommand: 87899689 setprop "debug.mono.connect" ""
[D:]: TrackDeviceTask got:
[I:]: Got new device list from adb with 0 devices
[D:]: TrackDeviceTask got: 87899689 offline
[I:]: Got new device list from adb with 1 devices
[D:]: TrackDeviceTask got: 87899689 device
[I:]: Got new device list from adb with 1 devices
D:RunShellCommand: 87899689 getprop
D:RunShellCommand: 87899689 date +%s
D:RunShellCommand: 87899689 setprop "debug.mono.extra" "debug=127.0.0.1:29316:29317,timeout=1571763626,loglevel=0,server=y"
D:RunShellCommand: 87899689 getprop
D:RunShellCommand: 87899689 am broadcast -a "mono.android.intent.action.EXTERNAL_STORAGE_DIRECTORY" -n "Mono.Android.DebugRuntime/com.xamarin.mono.android.ExternalStorageDirectory"
D:RunShellCommand: 87899689 am start -a "android.intent.action.MAIN" -c "android.intent.category.LAUNCHER" -n "com.myapp.name/md5aa90eac5c6d14c19e9c8e7ab0853061c.SplashActivity"
D:RunShellCommand: 87899689 am force-stop com.myapp.name
D:RunShellCommand: 87899689 setprop "debug.mono.connect" ""
D:RunShellCommand: 87899689 setprop "debug.mono.extra" ""
D:RunShellCommand: 87899689 getprop
D:RunShellCommand: 87899689 am start -a "android.intent.action.MAIN" -c "android.intent.category.LAUNCHER" -n "com.myapp.name/md5aa90eac5c6d14c19e9c8e7ab0853061c.SplashActivity"
D:RunShellCommand: 87899689 am broadcast -a "mono.android.intent.action.EXTERNAL_STORAGE_DIRECTORY" -n "Mono.Android.DebugRuntime/com.xamarin.mono.android.ExternalStorageDirectory"
D:RunShellCommand: 87899689 rm -f "/storage/emulated/0/Android/data/com.myapp.name/files/.override/debug.mono.extra"
[D:]: TrackDeviceTask got:
[I:]: Got new device list from adb with 0 devices
[D:]: TrackDeviceTask got: 87899689 offline
[I:]: Got new device list from adb with 1 devices
[D:]: TrackDeviceTask got: 87899689 device
[I:]: Got new device list from adb with 1 devices
D:RunShellCommand: 87899689 getprop
D:RunShellCommand: 87899689 date +%s
D:RunShellCommand: 87899689 setprop "debug.mono.extra" "debug=127.0.0.1:29318:29319,timeout=1571764490,loglevel=0,server=y"
D:RunShellCommand: 87899689 getprop
D:RunShellCommand: 87899689 am broadcast -a "mono.android.intent.action.EXTERNAL_STORAGE_DIRECTORY" -n "Mono.Android.DebugRuntime/com.xamarin.mono.android.ExternalStorageDirectory"
D:RunShellCommand: 87899689 am start -a "android.intent.action.MAIN" -c "android.intent.category.LAUNCHER" -n "com.myapp.name/md5aa90eac5c6d14c19e9c8e7ab0853061c.SplashActivity"
D:RunShellCommand: 87899689 am force-stop com.myapp.name
D:RunShellCommand: 87899689 setprop "debug.mono.connect" ""
Severe lag after pressing a button (activity indicator and async REST-calls)
Hi all, this is my first message on this forum and of course, it's about problem I have with my Xamarin app.
I'm a newbie when it comes to Xamarin and I'm building my first app with it. The application is fairly simple (log in to an external system and fetch some data via REST.
When the app opens the user is greeted with a login screen. After giving the credentials and pressing the login-button, 3 things happen in the following order:
1) an activity indicator is shown
2) all the fields and buttons are disabled on the login page
3) authentication and data fetching is done via REST calls to an external system.
The problem is, that after the user presses the login-button, there's a lag of 1 - 4 seconds before anything happens. So it takes 1 - 4 seconds for the activity indicator to pop up and the fields to get disabled. This is quite a horrible user experience and I can't seem to understand why this is happening.
I'm using a CarouselPage and the code for the first page (login page) is simple like this (i removed all formatting for this example):
<ContentPage x:Name="loginPage">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness">
<On Platform="iOS, Android" Value="0,40,0,0" />
</OnPlatform>
</ContentPage.Padding>
<StackLayout>
<Image Source="logo" />
<Label x:Name="authenticationPageLabel"/>
<Entry x:Name="usernameField" />
<Entry x:Name="passwordField"/>
<Button x:Name="logInToSystemButton" Clicked="logInToVaultButton_Clicked" />
<ActivityIndicator x:Name="loginPageActivityIndicator"
Color="Orange"
VerticalOptions="CenterAndExpand"
HorizontalOptions="Fill" />
<Label x:Name="loginStatusLabel" />
</StackLayout>
</ContentPage>
Now the code for the logInToSystemButton click event is like this:
private async void logInToSystem_Clicked(object sender, EventArgs e)
{
// Show activity indicator and disable buttons/fields
loginPageActivityIndicator.IsRunning = true;
logInToSystemButton.IsEnabled = false;
chkBoxRememberMe.IsEnabled = false;
usernameField.IsEnabled = false;
passwordField.IsEnabled = false;
chkBoxRememberMe.Color = Color.Gray;
// Get input
string username = usernameField.Text;
string password = passwordField.Text;
// Authentication to the external system
Task<string> task1 = authenticateToSystemAsync(username, password, GUID);
authToken = await task1;
// Get stuff from the system
Task<List<Stuff>> task2 = GetStuffAsync(authToken);
listOfStuff.ItemsSource = await task2;
// Stop activity indicator
loginPageActivityIndicator.IsRunning = false;
// Jump to the next carousel page
CurrentPage = this.Children[1];
}
I've pinpointed the reason for the lag to be the two awaited tasks which make a REST call to the external system. If they are commented out the activity indicator and field disabling happens instantly after the button press. But why is this, since the awaited web-calls happen AFTER the UI stuff in the code and activity indicator is the first line in that click event?
The code example for GetStuffAsync() is something like this:
private static async Task<List<Stuff>> GetStuffAsync(string authToken)
{
// Create the web request with the passed authToken
var request = WebRequest.Create($"http://{hostServer}/REST/stuff");
request.Headers["X-Authentication"] = authToken;
request.Method = "GET";
request.Timeout = 30000; // 30 seconds
request.ContentLength = 0;
// Get response
string result = "";
using (HttpWebResponse response = await request.GetResponseAsync() as HttpWebResponse)
{
// Get the response stream
StreamReader reader = new StreamReader(response.GetResponseStream());
// Read the whole contents and return as a JSON string
result = await reader.ReadToEndAsync();
}
// Deserialize the returned data
dynamic lotsOfStuff= JsonConvert.DeserializeObject(result);
// Iterate over the returned JSON array
List<Stuff> listOfStuff= new List<Stuff>();
foreach (dynamic thing in listOfStuff.Items)
{
listOfStuff.Add(new Thing { Name = thing.Name, ID = thing.ID });
}
return listOfStuff;
}
So of course I'd like the activity indicator and disabling of the fields happen instantly after pressing the login button and then do the other work asynchronously while the user sees the activity indicator spinning. There must be something fundamental I'm doing wrong or missing here. Thank you in advance for reading and helping out.
// TDMR87
How to solve "Xamarin.Forms.Platform.iOS.SearchBarRenderer.UpdateTextColor" exception?
I started to get this exception in iOS, pretty randomly. I can't find a pattern, I click on things, navigate to pages and back, and "sometimes" I get this long exception. If I retry the same steps, it all works fine, then randomly it throws the exception again.
Not sure if it started with Xamarin.Forms 4.3 or not...I am not able to verify which older version (if any) worked.
Right now i was never able to reproduce this on any device/simulator with iOS 13.
" at UIKit.UIColor.GetRGBA (System.nfloat& red, System.nfloat& green, System.nfloat& blue, System.nfloat& alpha) [0x00007] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.4.0.2/src/Xamarin.iOS/UIKit/UIColor.cs:54 \n at Xamarin.Forms.Platform.iOS.ColorExtensions.ToColor (UIKit.UIColor color) [0x00000] in :0 \n at Xamarin.Forms.Platform.iOS.SearchBarRenderer.UpdateTextColor () [0x0004e] in :0 \n at Xamarin.Forms.Platform.iOS.SearchBarRenderer.OnElementPropertyChanged (System.Object sender, System.ComponentModel.PropertyChangedEventArgs e) [0x0005a] in :0 \n at (wrapper delegate-invoke) .invoke_void_object_PropertyChangedEventArgs(object,System.ComponentModel.PropertyChangedEventArgs)\n at Xamarin.Forms.BindableObject.OnPropertyChanged (System.String propertyName) [0x00000] in
\a\1\s\Xamarin.Forms.Core\BindableObject.cs:211 \n at Xamarin.Forms.Element.OnPropertyChanged (System.String propertyName) [0x00000] in
\a\1\s\Xamarin.Forms.Core\Element.cs:359 \n at Xamarin.Forms.BindableObject.SetValueActual (Xamarin.Forms.BindableProperty property, Xamarin.Forms.BindableObject+BindablePropertyContext context, System.Object value, System.Boolean currentlyApplying, Xamarin.Forms.Internals.SetValueFlags attributes, System.Boolean silent) [0x00114] in
\a\1\s\Xamarin.Forms.Core\BindableObject.cs:443 \n at Xamarin.Forms.BindableObject.SetValueCore (Xamarin.Forms.BindableProperty property, System.Object value, Xamarin.Forms.Internals.SetValueFlags attributes, Xamarin.Forms.BindableObject+SetValuePrivateFlags privateAttributes) [0x00173] in
\a\1\s\Xamarin.Forms.Core\BindableObject.cs:379 \n at Xamarin.Forms.BindableObject.SetValueCore (Xamarin.Forms.BindableProperty property, System.Object value, Xamarin.Forms.Internals.SetValueFlags attributes) [0x00000] in
\a\1\s\Xamarin.Forms.Core\BindableObject.cs:325 \n at Xamarin.Forms.SearchBar.set_IsEnabledCore (System.Boolean value) [0x00000] in
\a\1\s\Xamarin.Forms.Core\SearchBar.cs:91 \n at Xamarin.Forms.SearchBar.CommandCanExecuteChanged (System.Object sender, System.EventArgs eventArgs) [0x0000a] in
\a\1\s\Xamarin.Forms.Core\SearchBar.cs:157 \n at Prism.Commands.DelegateCommandBase.OnCanExecuteChanged () [0x0004f] in d:\a\1\s\Source\Prism\Commands\DelegateCommandBase.cs:45 \n at Prism.Commands.DelegateCommandBase.RaiseCanExecuteChanged () [0x00000] in d:\a\1\s\Source\Prism\Commands\DelegateCommandBase.cs:57 \n at Prism.Commands.PropertyObserverNode+<>c__DisplayClass9_0.<.ctor>b__0 () [0x00000] in d:\a\1\s\Source\Prism\Commands\PropertyObserverNode.cs:24 \n at Prism.Commands.PropertyObserverNode.OnPropertyChanged (System.Object sender, System.ComponentModel.PropertyChangedEventArgs e) [0x00029] in d:\a\1\s\Source\Prism\Commands\PropertyObserverNode.cs:65 \n at (wrapper delegate-invoke) .invoke_void_object_PropertyChangedEventArgs(object,System.ComponentModel.PropertyChangedEventArgs)\n at Prism.Mvvm.BindableBase.OnPropertyChanged (System.ComponentModel.PropertyChangedEventArgs args) [0x00000] in d:\a\1\s\Source\Prism\Mvvm\BindableBase.cs:99 \n at Prism.Mvvm.BindableBase.OnPropertyChanged (System.String propertyName) [0x00000] in d:\a\1\s\Source\Prism\Mvvm\BindableBase.cs:90 \n at Prism.Mvvm.BindableBase.RaisePropertyChanged (System.String propertyName) [0x00000] in d:\a\1\s\Source\Prism\Mvvm\BindableBase.cs:76 \n at Prism.Mvvm.BindableBase.SetProperty[T] (T& storage, T value, System.Action onChanged, System.String propertyName) [0x00025] in d:\a\1\s\Source\Prism\Mvvm\BindableBase.cs:60 \n at LiveDispatch.Mobile.ViewModels.ViewModelBase.set_IsBusy (System.Boolean value) [0x00001] in /Users/stesvis/Documents/projects/levitica/livedispatch/LiveDispatch.Mobile/LiveDispatch.Mobile/ViewModels/ViewModelBase.cs:73 \n at LiveDispatch.Mobile.ViewModels.WorkOrdersPageViewModel.ExecuteLongTapCommand (System.Object parameter) [0x000cd] in /Users/stesvis/Documents/projects/levitica/livedispatch/LiveDispatch.Mobile/LiveDispatch.Mobile/ViewModels/WorkOrders/WorkOrdersPageViewModel.cs:825 "
iOS 13.0 Broke MasterDetailPage on iPads?
I have noticed that after updating iOS to v13.0, the MasterDetailPage is broken on iPads but it's still working on iPhones and Androids.
By broken I mean the whole page is white, without content.
The only way to fix this is to update Xamarin.Forms to the latest v4.2+.
The problem is that some other packages are not compatible (XF broke something else after v4.0) so I cannot update XF yet.
The App Store is rejecting my app because it shows a white screen on iPads with iOS 13.0+....so I would have to stop targeting iPads!
Try for yourself, here is a basic sample repo with MasterDetail page (the default Xamarin Forms template with MasterDetailPage).
https://github.com/stesvis/MasterDetailTest2
The same happens with Prism MasterDetailsPage:
https://github.com/stesvis/MasterDetailTest
- iPhones: works
- iPad -> iOS 12.2: works
- iPad -> iOS 13.0: white screen
Any solution for this HUGE headache?
Xamarin grid column auto width but max possible?
Hi,
I set ColumnDefinition Width="Auto"
in in XAML.
This is fine, but I would like to restrict the max size of the column.
So till that point it's Auto, after that no more expanding width.
Is this possible?
Thanks