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:
Related
I'm using firebase to send push notifications from a server to my app, the message looks like this:
var message = new Message()
{
Notification = new Notification()
{
Title = "Title - Test",
Body = "Body - Test",
},
Token = registrationToken
};
The notification comes through to the device no problem. All I want from when the notification is clicked, is for the app to start if the app is closed (this works) and for the app to resume if it's in the background.
When it's in the background and I click the notification, I just get a white screen. The issue seems to go away when I remove my splash screen, however that is not an ideal solution...Here is the relevant code, what am I doing wrong?
SPLASH ACTIVITY:
[Activity(Label = "MyApp",
Theme = "#style/splashscreen",
MainLauncher = true,
NoHistory = true)]
public class SplashActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
}
protected override void OnResume()
{
base.OnResume();
var mainActivityIntent = new Intent(this, typeof(MainActivity));
mainActivityIntent.AddFlags(ActivityFlags.SingleTop | ActivityFlags.NoAnimation);
StartActivity(mainActivityIntent);
this.Finish();
}
public override void OnBackPressed() { }
}
MAIN ACTIVITY:
[Activity(Label = "MyApp",
Theme = "#style/MainTheme",
LaunchMode = LaunchMode.SingleTop,
MainLauncher = false,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation, ScreenOrientation = ScreenOrientation.FullSensor)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
public static MainActivity MainActivityInstance { get; private set; }
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
this.Window.SetFlags(WindowManagerFlags.KeepScreenOn, WindowManagerFlags.KeepScreenOn);
this.Window.SetSoftInputMode(SoftInput.AdjustPan);
Forms.Init(this, savedInstanceState);
MainActivityInstance = this;
LoadApplication(new App());
}
Try changing MainLauncher = true for the main activity.
Adding ActivityFlags.ClearTop to mainActivityIntent.AddFlags() in my OnResume method on
SplashActivity has seemed to have worked:
protected override void OnResume()
{
base.OnResume();
var mainActivityIntent = new Intent(this, typeof(MainActivity));
mainActivityIntent.AddFlags(ActivityFlags.NoAnimation | ActivityFlags.SingleTop | ActivityFlags.ClearTop);
StartActivity(mainActivityIntent);
this.Finish();
}
is there any chance to force change screen orientation based device screen resolution?
Have app for tablets, but I want to run app on mobile device too. I have a few pages, where I need to change orientation to landscape on phone, because then is my listview a litle bit messy.
Thank you for any advice and I apologize for the bad English :)
You can use MessagingCenter to achieve that .
For example , when navigating from MainPage to PageTwo in Forms , the content page of PageTwo as follow :
public partial class PageTwo : ContentPage
{
public PageTwo()
{
InitializeComponent();
}
protected override void OnAppearing()
{
base.OnAppearing();
MessagingCenter.Send(this, "allowLandScape");
}
//during page close setting back to portrait
protected override void OnDisappearing()
{
base.OnDisappearing();
MessagingCenter.Send(this, "quitLandScape");
}
}
In Android , need to modify MainActivity as follow :
[Activity(Label = "ForceOrientation", Icon = "#mipmap/icon", Theme = "#style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation, ScreenOrientation = ScreenOrientation.Portrait)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
//allowing the device to change the screen orientation based on the rotation
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
MessagingCenter.Subscribe<PageTwo>(this, "allowLandScape", sender =>
{
RequestedOrientation = ScreenOrientation.Landscape;
});
//during page close setting back to portrait
MessagingCenter.Subscribe<PageTwo>(this, "quitLandScape", sender =>
{
RequestedOrientation = ScreenOrientation.Portrait;
});
}
}
In iOS , we need to create a PageTwoRenderer as follow :
[assembly: ExportRenderer(typeof(PageTwo), typeof(PageTwoRenderer))]
namespace ForceOrientation.iOS
{
public class PageTwoRenderer : PageRenderer
{
public PageTwoRenderer()
{
MessagingCenter.Subscribe<PageTwo>(this, "allowLandScape", sender =>
{
UIDevice.CurrentDevice.SetValueForKey(NSNumber.FromNInt((int)(UIInterfaceOrientation.LandscapeLeft)), new NSString("orientation"));
});
//during page close setting back to portrait
MessagingCenter.Subscribe<PageTwo>(this, "quitLandScape", sender =>
{
UIDevice.CurrentDevice.SetValueForKey(NSNumber.FromNInt((int)(UIInterfaceOrientation.Portrait)), new NSString("orientation"));
});
}
}
}
==============================Update=============================
We can use Xamarin.Essentials: Device Information to check whether the device is Phone , Tablet or other devices .
DeviceInfo.Idiom correlates a constant string that maps to the type of device the application is running on. The values can be checked with the DeviceIdiom struct:
DeviceIdiom.Phone – Phone
DeviceIdiom.Tablet – Tablet
DeviceIdiom.Desktop – Desktop
DeviceIdiom.TV – TV
DeviceIdiom.Watch – Watch
DeviceIdiom.Unknown – Unknown
Modiied PageTwo as follow :
protected override void OnAppearing()
{
base.OnAppearing();
var idiom = DeviceInfo.Idiom;
if (idiom == DeviceIdiom.Phone)
{
MessagingCenter.Send(this, "allowLandScape");
}
}
//during page close setting back to portrait
protected override void OnDisappearing()
{
base.OnDisappearing();
var idiom = DeviceInfo.Idiom;
if (idiom == DeviceIdiom.Phone)
{
MessagingCenter.Send(this, "quitLandScape");
}
}
You can force set orientation on these few pages
// on IOS -> AppDelegate.cs
public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, UIWindow forWindow)
{
if (Device.Idiom == TargetIdiom.Phone ) {
{
return UIInterfaceOrientationMask.Landscape;
}
else
{
return UIInterfaceOrientationMask.Portrait;
}
}
// and on Android -> MainActivity.cs do the same if else in here
protected override void OnCreate(Bundle savedInstanceState)
{
if (Device.Idiom == TargetIdiom.Phone)
{
RequestedOrientation = ScreenOrientation.Landscape;
}
else
{
RequestedOrientation = ScreenOrientation.Portrait;
}
}
You can check about Device class more in documentation https://learn.microsoft.com/en-us/xamarin/xamarin-forms/platform/device#deviceidiom
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));
I am building a Xamarin Android app using Xamarin.Forms my App class is really simple and contains one page like so:
public App()
{
// The root page of your application
MainPage = new NavigationPage(new ContentPage()
{
Title = "My First Page!",
Content = new Label()
{
Text = "Test Page!",
TextColor = Color.White,
FontSize = 25,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
}
});
}
and my MainActivity class like so:
[Activity(Label = "GridTest", Icon = "#drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App());
}
}
When I launch the application though the NavigationBar is displayed with the word "GridTest" displayed in the top left which looks rubbish, shown below:
This is the NavigationBar I would like to hide.
After this my application loads with the navigation bar fine. Shown below:
I would like to keep this Navigation Bar
So my question is. How do I hide the Android NavigationBar that is displayed BEFORE the initial page has loaded?
SIDE NOTE:
I have tried NavigationPage.SetHasNavigationBar(page,false); but this does not work. This hides the NavigationBar for the first page shown below.
which I would like to keep! This also does not hide the "GridTest" navigation bar I am looking to hide (shown in screenshot 1)
To reiterate... I am looking to hide the INITIAL navigation bar. provided by the Android MainActivity NOT the Xamarin.Forms navigation bar
The main activity which will load the first time the application starts.
[Activity(Label = "testapp", MainLauncher = true, Theme = "#style/MyTheme", ScreenOrientation = ScreenOrientation.Portrait)]
public class SplashActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// SetContentView(Resource.Layout.LaunchScreen); //Set a splash screen here if you wish
Java.Lang.Runnable runnable = new Java.Lang.Runnable(() =>
{
Intent i = new Intent(this, typeof(MainActivity));
StartActivity(i);
});
new Handler().PostDelayed(runnable, 1000);
}
}
The theme for that activity must be saved to Resources/drawable/styles.xml and is
<resources>
<style name="MyTheme" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowNoTitle">true</item>
</style>
</resources>
This SplashActivity will load and call MainActivity
and your MainActivity will look like this:
[Activity(Label = "GridTest", Icon = "#drawable/icon", ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App());
}
}
You dont need to set the Theme here and it will work as before. Another Important note about the MainActivity is you MUST remove MainLauncher = true
You should be able to hide that navigation bar by setting a simple attribute in your page like so:
<ContentPage NavigationPage.HasNavigationBar="false"
..... >
</ContentPage>
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));
}
}
}