I call a web service which gets 4 files, and while these files are loading I want to show progress to the user (circular or horizontal it doesn't matter). I've followed the examples on internet but nothing appears on screen.
MobileSellReference.Service1 service = new MobileSellReference.Service1();
service.Url = settings.Synchronization.Msellurl;
ProgressBar progressBar = FindViewById<ProgressBar>(Resource.Id.progressBar);
progressBar.Max = 100;
progressBar.Progress = 0;
byte[][] basedataResult = service.ToPPC(basedataZipName, objectId);
progressBar.IncrementProgressBy(25);
byte[][] dutybasedataResult = service.ToPPC(dutybasedataZipName, objectId);
progressBar.IncrementProgressBy(25);
byte[][] tranbasedataResult = service.ToPPC(tranbasedataZipName, objectId);
progressBar.IncrementProgressBy(25);
byte[][] vendbasedataResult = service.ToPPC(vendbasedataZipName, objectId);
progressBar.IncrementProgressBy(25);
I've found a lot of examples using external progressbar libraries but they all want to change the theme of the Activity
. Instead I want some simple ProgressBar
built into Xamarin.Android
. For example when the first file is downloaded I want 1/4 of the circle to be filled, when 2 files are downloaded 1/2 of the circle to be filled et cetera. Similarly for a horizontal ProgressBar
.
Use AsyncTask
.axml
file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="0" />
<ProgressBar
android:id="@+id/pb"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="?android:attr/progressBarStyleHorizontal" />
</LinearLayout>
MainActivity
:
public class MainActivity : Activity
{
ProgressBar pb;
TextView tv;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
pb = FindViewById<ProgressBar>(Resource.Id.pb);
tv = FindViewById<TextView>(Resource.Id.tv);
UpdatePB uptask = new UpdatePB(this,pb,tv);
uptask.Execute(100);
}
public class UpdatePB : AsyncTask<int, int, string>
{
Activity mcontext;
ProgressBar mpb;
TextView mtv;
public UpdatePB(Activity context,ProgressBar pb,TextView tv) {
this.mcontext = context;
this.mpb = pb;
this.mtv = tv;
}
protected override string RunInBackground(params int[] @params)
{
// TODO Auto-generated method stub
for (int i = 1; i <= 4; i++)
{
try
{
Thread.Sleep(3000);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
Android.Util.Log.Error("lv",e.Message);
}
mpb.IncrementProgressBy(25);
PublishProgress(i * 25);
}
return "finish";
}
protected override void OnProgressUpdate(params int[] values)
{
mtv.Text = String.ValueOf(values[0]);
Android.Util.Log.Error("lv==", values[0] + "");
}
protected override void OnPostExecute(string result)
{
mcontext.Title = result;
}
}
}
This might be a helpful link:
https://developer.android.com/reference/android/widget/ProgressBar.html
Code:
<ProgressBar
android:id="@+id/determinateBar"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:progress="25"/>
... and then you just change the progress; 25, 50, 75, 100?
After running into the same problem, I found another solution that got it working. I was reluctant to define a new class (like AsyncTask) to fix this, so looked into async await and threading. I found that after defining an Android.Widget.ProgressBar
in an .axml
layout file like so:
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progress="0"
style="?android:attr/progressBarStyleHorizontal" />
I could get it to update if I put the updating tasks in a System.Threading.Tasks.Task.Run
and passing in an action that does the updates with RunOnUiThread
call like:
btnDoStuff.Click += (sender, e) =>
{
Task.Run(() =>
{
RunOnUiThread(() =>
{
progressBar.Max = 100;
progressBar.Progress = 0;
progressBar.Visibility = ViewStates.Visible;
});
DoSomeWork1(arguments);
RunOnUiThread(() => progressBar.Progress += 25);
DoSomeWork2(arguments);
RunOnUiThread(() => progressBar.Progress += 25);
DoSomeWork3(arguments);
RunOnUiThread(() => progressBar.Progress += 25);
DoSomeWork4(arguments);
RunOnUiThread(() => progressBar.Progress += 25);
});
}
But even then I've had some inconsistent behavior - there may be an element of timing to it as well...