Xamarin.Forms: App crash after splash activity - xamarin.forms

I have splash screen, When I run my app its crash. Here is my splash screen code
If I don't use splash screen app is working fine but when I use splash screen and close my app and run again its crash after splash screen.
public class SplashActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
var mainIntent = new Intent(Application.Context, typeof(MainActivity));
if (Intent.Extras != null)
{
mainIntent.PutExtras(Intent.Extras);
}
mainIntent.SetFlags(ActivityFlags.SingleTop);
StartActivity(mainIntent);
}
}

I presume the issues is connected with the fact that you are trying to start the already started SingleTop activity for the second time.
However, the recommendation is to write a splash screen a bit differently - without needing separate activity. See this nice blog post by Adam Pedley on splash screen implementation in Xamarin.Forms.
Instead of having a separate activity, you can just temporarily apply a "splash" theme to the main activity, before the activity loads. This is useful, because it makes your app load faster than having a full separate splash screen activity.
Create a style in Resources/values/styles.xml:
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<style name="splashscreen" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">#drawable/splashscreen</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsTranslucent">false</item>
<item name="android:windowIsFloating">false</item>
<item name="android:backgroundDimEnabled">true</item>
</style>
<resources>
Set this theme to the MainActivity via attribute:
[Activity(Label = "Mobile App",
Theme = "#style/splashscreen",
Icon = "#drawable/icon",
MainLauncher = true,
ConfigurationChanges = ConfigChanges.ScreenSize |
ConfigChanges.Orientation,
LaunchMode = LaunchMode.SingleTop)]
public class MainActivity : Xamarin.Forms.Platform.Android.FormsAppCompatActivity
And then override the OnCreate method to set the actual theme back:
protected override void OnCreate(Bundle bundle)
{
base.Window.RequestFeature(WindowFeatures.ActionBar);
// For global use "global::" prefix - global::Android.Resource.Style.ThemeHoloLight
base.SetTheme(Resource.Style.MainTheme);
base.OnCreate(bundle);
...
}

Happened to me on .net Maui, It turned out I didn't register the services correctly, so the builder could not generate the page.

Related

How to disable Tab on TabbedPage xamarin forms?

Im looking for a way to disable a tab within a TabbedPage,
here my example of two tabs
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns=".."
xmlns:x=".."
x:Class="App.Views.Pages_Tabbed"
x:Name="myTabs"
xmlns:page="clr-App.Views">
<TabbedPage.Children>
<page:MemberShip x:Name="firstPage" ></page:MemberShip>
<page:Consent x:Name="secondPage"></page:Consent>
<page:Question x:Name="thirdPage"> </page:Question >
</TabbedPage.Children>
</TabbedPage> ```
I tried to set the Page to IsEnabled = false or IsVisible= false but not working .. it hide only content.
Also i followed https://stackoverflow.com/questions/54657758/how-to-set-the-currentpage-property-of-a-tabbedpage-in-the-oncurrentpagechanged but it crash the app cuz of the infinite loop.
The official does not seem to provide a way to directly disable the tab.
You can also hide the tab temporarily when you don't want the user to click on it. Let the user load it when he can click.
Here is the background code:
public partial class TabbedPage1 : TabbedPage
{
public static TabbedPage theTabbedPage {get; set;}
public TabbedPage1()
{
InitializeComponent();
theTabbedPage = this;
theTabbedPage.Children.RemoveAt(1);//Hide the second tab
}
}
When the user can click, use abbedPage1.theTabbedPage.Children.Insert(1,new Page2() {Title="page2"}); to add the tab.
Hope this method can help you too.

How to work with preference in single activity design using navigation component?

I want to migrate to single activity design using navigation component. I am using one activity and others are fragment. For some screens, I have only layouts, no preference. No problems to inflate those in fragment. But i faced problem when i try to work with preference.
My requirements is:
I need to inflate a toolbar and preference list in a fragment.
My approaches:
Add preference using this following code.
SettingFragment.java
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.setting_main, rootKey);
}
Configure for app bar for navigation component.
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mNavController = Navigation.findNavController(view);
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(mNavController.getGraph()).build();
Toolbar toolbar = view.findViewById(R.id.the_toolbar);
NavigationUI.setupWithNavController(toolbar, mNavController, appBarConfiguration);
}
In app theme, i used a layout for preference which contains toolbar and framelayout.
<style name="Theme.MyApp" parent="#style/Theme.AppCompat.Light.NoActionBar">
...
<item name="preferenceTheme">#style/PreferenceThemeOverlay</item>
</style>
<style name="PreferenceThemeOverlay">
<item name="android:layout">#layout/fragment_settings </item>
</style>
fragment_settings.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/the_toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:layout_gravity="bottom"
android:layout_marginBottom="12dp"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#android:id/list_container">
</FrameLayout>
</LinearLayout>
setting_main.xml
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="MyApp"
android:title="My application">
<androidx.preference.Preference
android:icon="#drawable/ic_list1"
android:key="PreferenceList1"
android:title="PreferenceList1" />
<androidx.preference.PreferenceCategory android:key="SecondCategory">
<androidx.preference.Preference
android:icon="#drawable/ic_list2"
android:key="PreferenceList2"
android:title="PreferenceList2" />
</androidx.preference.PreferenceCategory>
</androidx.preference.PreferenceScreen>
My problems:
If I do this, I can successfully add toolbar and preference. But i see a blinking issue in title during transaction from one fragment to another.
I have searched a lot, but did not find any suitable solutions. I am a newbie.
My questions:
How can I solve this issue?
Is there any way to work with preference in navigation component which also have a toolbar and preference in Fragment?
For others fragment, which does not have preference i can inflate using this code which works fine with no blink issue. Is there any ways to do this for preference also adjusting with my requirements?
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable
Bundle savedInstanceState) {
return inflater.inflate(R.layout.setting_main_fragment, container, false);
}

Cross Platform Xamarin Forms App - Android splash screen not displaying

I am creating my first Xamarin Forms cross-platform application. I am in the process of creating a splash screen using the native platform code for each OS.
My Android splash screen is not displaying. I trace through the application and it hits the correct code, but the page does not display.
My xml file is in the resources\layout folder which renders nicely when I view it. It is called SplashScreen.xml.
Can anyone shed some light as to why the page does not display?
{
[Activity(MainLauncher = true, NoHistory = true)]
public class SplashScreenActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
RequestWindowFeature(WindowFeatures.NoTitle);
base.OnCreate(savedInstanceState);
SetContentView(Droid.Resource.Layout.SplashScreen);
System.Threading.Thread.Sleep(3000);
StartActivity(typeof(MainActivity));
}
public override void OnBackPressed() { }
}
}
Better Approach
In your Resources -> Values -> styles.xml create your splash screen theme.
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<style name="splashscreen" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">#drawable/splashscreen</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsTranslucent">false</item>
<item name="android:windowIsFloating">false</item>
<item name="android:backgroundDimEnabled">true</item>
</style>
Go to your MainActivity.cs and ensure MainLauncher = true. Ensure no other activity has MainLauncher=true.
In MainActivity.cs change the default theme to the splash screen.
[Activity(Label = "Mobile App", Theme = "#style/splashscreen", Icon = "#drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation, LaunchMode = LaunchMode.SingleTop)]
public class MainActivity : Xamarin.Forms.Platform.Android.FormsAppCompatActivity
In OnCreate, switch your theme with the below code.
protected override void OnCreate(Bundle bundle)
{
base.Window.RequestFeature(WindowFeatures.ActionBar);
// Name of the MainActivity theme you had there before.
// Or you can use global::Android.Resource.Style.ThemeHoloLight
base.SetTheme(Resource.Style.MainTheme);
base.OnCreate(bundle);
...
Please refer this blog.
You should write a theme to load your xml first, like this:
<resources>
<style name="MyTheme.Base" parent="Theme.AppCompat.Light">
</style>
<style name="MyTheme" parent="MyTheme.Base">
</style>
<style name="MyTheme.Splash" parent ="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">#drawable/SplashScreen</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowActionBar">true</item>
</style>
</resources>
Then use that theme in the activity:
[Activity(Theme = "#style/MyTheme.Splash", MainLauncher = true, NoHistory = true)]
Here is the document about Splash Screen in Xamarin.Android and there are detailed steps you can follow.
A sample project is also available : splashscreen.

Back button missing on NavigationPage

I'm using Prism.Forms 6.3 in a Xamarin.Forms 2.3.4.247 project. I'm having a hard time tracking why the back arrow button isn't visible when I navigate to a details page within a Master/Detail setup.
I can navigate to the Pages just fine, but the back-button never shows up. Instead, the hamburger menu icon is always visible. This is my "Master" page.
<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:FloatSink.Apps.Mobile.Views.ValueConverters"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="FloatSink.Apps.Mobile.Views.MainPage"
BackgroundColor="Blue">
<MasterDetailPage.Master>
<ContentPage Title="Menu">
<StackLayout Padding="40">
<Label Text="Hello" />
<Button Text="Feed" Command="{Binding NavigateCommand}" CommandParameter="NavigationPage/FeedPage" />
<Button Text="Options" Command="{Binding NavigateCommand}" CommandParameter="NavigationPage/OptionsPage" />
</StackLayout>
</ContentPage>
</MasterDetailPage.Master>
</MasterDetailPage>
This is two of my Detail pages.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="FloatSink.Apps.Mobile.Views.FeedPage">
<Label Text="Hello from Feed Page!" />
</ContentPage>
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="FloatSink.Apps.Mobile.Views.OptionsPage">
<Label Text="Hello from Options Page!" />
</ContentPage>
I navigate to it using the CommandParameter specified in my Master page, using the navigation service in the MainPageViewModel.
private void NavigateToPage(string uri)
{
this.navigationService.NavigateAsync(uri);
}
I've setup my NavigationPage like this during the startup of the app so I land on the FeedPage first, then I can navigate to the OptionsPage.
public class App : PrismApplication
{
public App(IPlatformInitializer dependencyRegister) : base(dependencyRegister) { }
protected override void OnInitialized()
{
base.NavigationService.NavigateAsync("MainPage/NavigationPage");
}
protected override void RegisterTypes()
{
var builder = new ContainerBuilder();
builder.RegisterModule<NavigationRegistration>();
builder.RegisterModule<ServicesRegistration>();
base.Container.RegisterTypeForNavigation<NavigationPage>();
// This is deprecated but we have to wait for Prism.Autofac to update itself
builder.Update(base.Container);
}
}
The DI registrations associated with navigation are done in this module:
internal class NavigationRegistration : Module
{
/// <summary>
/// Load the navigation related types into the given builder.
/// </summary>
/// <param name="builder">Container Builder that will be turned into the final IOC Container</param>
protected override void Load(ContainerBuilder builder)
{
// Register the NavigationPage in Xamarin with the Prism Navigation system.
//builder.RegisterType<NavigationPage>().AsSelf();
//PageNavigationRegistry.Register(nameof(NavigationPage), typeof(NavigationPage));
// Get all of the Types that represent a View in our assembly for DI and navigation registration
// If start-up time ever becomes an issue, we can replace this assembly scan with explicit registrations.
Type[] viewTypes = base.ThisAssembly.GetTypes().Where(type => type.IsAssignableTo<Page>()).ToArray();
// Iterate over each discovered View Type and register it with the navigation system and DI container.
for(int index = 0; index < viewTypes.Length; index++)
{
Type viewType = viewTypes[index];
builder.RegisterType(viewType).Named<Page>(viewType.Name);
// If we ever need to disconnect a view name from its Type name, we can do so here.
// We would build a custom attribute to decorate the view with, pull the attribute from the Type
// and register the Type with the attribute value.
PageNavigationRegistry.Register(viewType.Name, viewType);
}
}
}
Again I can each one of my detail pages without problem, the hamburger menu exists and I can open the Master page to view my buttons used for navigating. I just can't navigate backwards once I'm there. Is that something I'm supposed to wire up myself?
I'm not sure I'm reading your question right but it sounds like this is normal behavior. In my (short) experience with XF/Prism, every navigation from the master is a beginning of the stack. If you were to add another page, e.g. from Master->PageA->PageB, I would expect Page A to have the hamburger menu but going to PageB would give you the back arrow.
For using NavigationPage inside uri you should register it for navigation in the App.xaml.cs:
protected override void RegisterTypes()
{
// your registrations
Container.RegisterTypeForNavigation<NavigationPage>();
}
I most cases it is the reason.
To Navigate To Master Page
"/MasterPage/NavigationPage/ViewA"
To Navigate out of Master Page from ViewA and with back button
"ViewB"
You need to start your app with MainPage = new NavigationPage(new StartPage()); That is how it is solved in normal situation. So maybe try to register your MainPage wrapped in a NavigationPage.

Embedded images not showing

This is my page in portable project
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:b="clr-namespace:Corcav.Behaviors;assembly=Corcav.Behaviors"
xmlns:local="clr-namespace:MyMobileApp;assembly=MyMobileApp"
x:Class="MyMobileApp.MainPage"
x:Name="MainPage">
<Image Source="{local:ImageResource myimage.jpg}" />
This is my ImageResourceExtension in same portable project
namespace MyMobileApp
{
[ContentProperty("Source")]
public class ImageResourceExtension : IMarkupExtension
{
public string Source { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
if (Source == null)
return null;
var imageSource = ImageSource.FromResource(Source);
return imageSource;
}
}
}
I have tried to add myimage.jpg as embedded in root of my project and in Resources folder, but no image is shown.
While debugging I see that the returned imageSource is of type Xamarin.Forms.StreamImageSource. How do I check if this is really found?
Can anyone spot the error here?
The correct XAML was to add the app name to the source.
<Image Source="{local:ImageResource MyMobileApp.myimage.jpg}" />
By default the image will have Build Action: None; this needs to be set to Build Action: EmbeddedResource.
Right click on Image > properties > set [Build Action: EmbeddedResource]
[]1
Can you explain the intent of the extension a bit more? Assuming you are putting your images in the proper folders ('Resources' on iOS, 'Resources/Drawable' on Android), then all you need in your XAML is just:
<Image Source="FeaturedAreaMockup.jpg" />
That will find the images in the appropriate folder and show them - why aren't you just doing that? What's the point of the extension?
To read assets/resources folder you need to use:
ImageSource.FromFile("myimage.jpg");'
ImageSource.FromResource uses images included as EmbeddedResource
More here: https://developer.xamarin.com/guides/cross-platform/xamarin-forms/working-with/images/

Resources