How can I implement a simple "splash screen" on program startup? I am copying a SQLite DB and it can be a bit of a long process that is not UI "friendly" .
I would prefer not to use "java code".
TIA
I recently solved this problem in the following way.
In the main activity I passed a parameter via the intent to set the number of milliseconds for which the splash screen would remain visible.
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
Intent i=new Intent();
i.SetClass(this, typeof (Splash));
i.PutExtra("Milliseconds", 3000);
StartActivity(i);
}
Then, in the second activity which I named "Splash" I retrieved the value and set a second thread to end the activity when the time had elapsed.
[Activity(Label = "Daraize Tech")]
public class Splash : Activity
{
private int _milliseconds;
private DateTime _dt;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
_milliseconds = Intent.GetIntExtra("Milliseconds", 1000);
SetContentView(Resource.Layout.Splash);
_dt=DateTime.Now.AddMilliseconds(_milliseconds);
}
public override void OnAttachedToWindow()
{
base.OnAttachedToWindow();
new Thread(new ThreadStart(() =>
{
while (DateTime.Now < _dt)
Thread.Sleep(10);
RunOnUiThread( Finish );
}
)).Start();
}
}
Also see http://docs.xamarin.com/android/tutorials/Creating_a_Splash_Screen
Really great tutorial.
It only takes about 10 lines of code :)
In a Styles.xml:
<resources>
<style name="Theme.Splash" parent="android:Theme">
<item name="android:windowBackground">#drawable/splash</item>
<item name="android:windowNoTitle">true</item>
</style>
</resources>
In your activity:
[Activity (MainLauncher = true, Theme = "#style/Theme.Splash", NoHistory = true)]
public class SplashActivity : Activity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Create your async task here...
StartActivity (typeof (Activity1));
}
}
This worked for me:
Starting an new thread from the splash activity. You can wait a few seconds or load some data or something else.
[Activity(MainLauncher = true, NoHistory = true)]
public class Splashscreen : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView (Resource.Layout.splashscreen);
new Thread (new ThreadStart (() =>
{
//Load something here ...
Thread.Sleep(1500);
Intent main = new Intent (this, typeof(MainActivity));
this.StartActivity (main);
this.Finish ();
})).Start ();
}
}
This solution gets you the following:
Immediate display of the splash screen
Removal of splash screen the exact time the "main" activity is launched (main activity replaces the splash activity)
In OnCreate, SetContentView is called to get the splash screen up, and then the worker thread is kicked off, which runs the slow processing data initialization stuff.
This way, the spalsh screen is displayed without delay. The last statement in the worker thread kicks off the "main" app/activity, which will have its DB & data all ready for access. Calling StartActivity() from OnCreate (ie, after initializeDataWorker.Start()), will cause MainActivity to run before/while the DB is being created and/or data is being fetched, which is usually not desireable).
This solution lacks a way to remove the splash screen from the backstack. When I get around to implementing this functionality I'll update it.
namespace Mono.Droid
{
[Activity(
Label = "Splash Activity",
MainLauncher = true,
Theme = "#android:style/Theme.Black.NoTitleBar",
Icon = "#drawable/icon",
NoHistory = false)]
public class SplashActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.SplashLayout);
Thread initializeDataWorker = new Thread(new ThreadStart(InitializeData));
initializeDataWorker.Start();
}
private void InitializeData()
{
// create a DB
// get some data from web-service
// ...
StartActivity(typeof(MainActivity));
}
}
}
Related
At first I should say that I have read all similar questions and they can not solve my problem .
I have a Splash Screen in my Xamarin Forms project and check the credentials in it and then in each condition start Main Activity with different parameter toward the condition . When Splash Screen finish it's work and disappear , the app show a black screen about 10 seconds and then main page is showing
this is my Splash :
[Activity(Theme = "#style/MainTheme.Splash",
MainLauncher = true,
NoHistory = true,
ScreenOrientation = ScreenOrientation.Portrait)]
public class SplashActivity : Activity
{
static readonly string TAG = "X:" + typeof(SplashActivity).Name;
public override void OnCreate(Bundle savedInstanceState, PersistableBundle persistentState)
{
base.OnCreate(savedInstanceState, persistentState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
Log.Debug(TAG, "SplashActivity.OnCreate");
}
protected override void OnResume()
{
base.OnResume();
Task startupWork = new Task(() => { SimulateStartup(); });
startupWork.Start();
}
async void SimulateStartup()
{
Some Code ...
InvokeMainActivity("SomeType");
}
private void InvokeMainActivity(string type)
{
Intent _activity = new Intent(Application.Context, typeof(MainActivity));
_activity.PutExtra("Key", type);
_activity.AddFlags(ActivityFlags.NoAnimation);
StartActivity(_activity);
}
and this is my MainActivity :
[Activity(Label = "#string/app_name",
Icon = "#drawable/icon",
Theme = "#style/MainTheme",
MainLauncher = false,
LaunchMode = LaunchMode.SingleTask,
ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.Locale | ConfigChanges.LayoutDirection)
]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override async void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
Xamarin.Essentials.Platform.Init(this, bundle);
Rg.Plugins.Popup.Popup.Init(this, bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
FFImageLoading.Forms.Platform.CachedImageRenderer.Init(enableFastRenderer: true);
Window.DecorView.LayoutDirection = LayoutDirection.Rtl;
string type = Intent.GetStringExtra("SomeType");
LoadApplication(new App(type));
}
}
How can I fix this ?
Thanks to #LeonLu-MSFT I add this code in style.xml without any change in MainActivity and Spalsh Screen
<item name="android:windowIsTranslucent">true</item>
I don't have Mac and ios device to test in ios
I was also facing similar problem. I fixed it by adding
<item name="android:windowIsTranslucent">true</item>
in ~\Resources\values\styles.xml.
So if you are facing similar problem add it as per below screen shot and hopefully it will also work for you:
Following this article I created a simple application that displays a list. The list I get from a web service (.asmx web service).
I want to auto update RecyclerView every 5 seconds and I have no idea how to do it.
In WinForms I would have used the Timer component, but I don't know how this works in Xamarin.
MainActivity.cs
[Activity(Label = "CibMonitor", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : AppCompatActivity
{
RecyclerView recyclerView;
RecyclerView.LayoutManager layoutManager;
ConnectionItemsAdapter adapter;
ConnectionItem[] connectionItems;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
var ci = new ConnectionItem();
//Get list from web service
connectionItems = ci.GetList().ToArray();
//Setup RecyclerView
adapter = new ConnectionItemsAdapter(this, connectionItems);
recyclerView = FindViewById<RecyclerView>(Resource.Id.recyclerView);
recyclerView.SetAdapter(adapter);
ChangedData();
}
}
Update
I created new method in activity class as York Shen suggested
void ChangedData()
{
Task.Delay(5000).ContinueWith(t =>
{
var newData = ConnectionItem.GetList();
adapter.RefreshItems(newData);
ChangedData();
}, TaskScheduler.FromCurrentSynchronizationContext());
}
This is my update method in adapter class:
public void RefreshItems(List<ConnectionItem> newItems)
{
items.Clear();
items = newItems;
NotifyDataSetChanged();
}
my app stops working, no exception only this message:
You can create a Task which can help you update recyclerView every 5 seconds:
void ChangedData()
{
Task.Delay(5000).ContinueWith(t =>
{
adapter.NotifyDataSetChanged();
ChangedData();//This is for repeate every 5s.
}, TaskScheduler.FromCurrentSynchronizationContext());
}
EDIT:
Sorry for late reply, calling the ChangedData() in Task.Delay() can resolve the repeate problem. You can invoke the ChangedData() in OnCreate() method. Hope this can help you. : )
I am wondering how I am meant to Call public static async Task CopyAssetAsync(Activity activity) from the OnCreate method.
public static async Task CopyAssetAsync(Activity activity)
{
{
var notesPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "NotesData.txt");
if (!File.Exists(notesPath))
{
try
{
UPDATE 1:
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
ActionBar.Hide();
btnAdd = FindViewById<Button>(Resource.Id.btnAdd);
//Notes
notesList = FindViewById<ListView>(Resource.Id.lvNotes);
//Where I am trying to call the method...
CopyAssetAsync();
UPDATE 2:
You have to use await keyword while calling and make the OnCreate() method async :
protected override async void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
ActionBar.Hide();
btnAdd = FindViewById<Button>(Resource.Id.btnAdd);
//Notes
notesList = FindViewById<ListView>(Resource.Id.lvNotes);
//Where I am trying to call the method...
await CopyAssetAsync(this);
}
i have problem with navigating, i can get to the second layout but i can not get back to the first(main) from the second. Even hardware/software back button not working. As far as i know on layout Profil does not work everything, when i try to make button what can change textview on that layout, it does not work too. IDs should be right.
Here is the first activity:
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Home);
Button btnProfil = FindViewById<Button>(Resource.Id.btnProfil);
btnProfil.Click += delegate
{
StartActivity(typeof(Activity1));
};
Here is the second activity:
public class Activity1 : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Profil);
Button btnBack = FindViewById<Button>(Resource.Id.btnBack);
btnBack.Click += delegate
{
StartActivity(typeof(MainActivity));
};
}
}
These formulations works same when they are in same script.
Button btnProfil = FindViewById<Button>(Resource.Id.btnProfil);
btnProfil.Click += delegate { SetContentView(Resource.Layout.Profil); };
Button btnBack = FindViewById<Button>(Resource.Id.btnBack);
btnBack.Click += delegate { SetContentView(Resource.Layout.Home); } ;
Thank you :)
I wanna point out that i'm a total newbie in Xamarin.
My goal is to create simple app that after you push the button, it will jump to another layout. My problem is, that after i created a new layout(called layout1) and new activity, I can't reference to this layout in my MainActivity.
freshly created Activity:
namespace Layouts
{
[Activity(Label = "Activity1")]
public class Activity1 : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.layout1);
}
}
}
And my MainActivity:
namespace Layouts
{
[Activity(Label = "Layouts", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView (Resource.Layout.Main);
Button button1 = FindViewById<Button>(Resource.Id.button);
button1.Click += delegate
{
StartActivity(typeof(layout1)); //can't reference layout1 there
};
}
}
}
Any help will be great, thanks :)
StartActivity(typeof(Activity1));