Change font size of tabs in a TabbedPage - xamarin.forms

Is there anyway to changed the font size of the ContentPage? enter image description here
Example is that, the last Tab. SUMMARY is cut and I want to set the font size to small.
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Test.ViewModels"
xmlns:model="clr-namespace:Test.Models"
Shell.TabBarBackgroundColor="Transparent"
x:Class="Test.Views.MainPage">
<ContentPage Title="Delivery">
</ContentPage>
<ContentPage Title="Pending">
</ContentPage>
<ContentPage Title="Success">
</ContentPage>
<ContentPage Title="Failed">
</ContentPage>
<ContentPage Title="Summary">
</ContentPage>
</TabbedPage>
I tried adding this:
<NavigationPage.TitleView>
<Label Text="This is my Title" FontSize="12" TextColor="White" />
</NavigationPage.TitleView>
But doesn't do anything.

I was able to reproduce the tab title as the screenshot you privided. You could try the code below to set the TabMode, TabGravity in custom renderer.
[assembly: ExportRenderer(typeof(TabbedPage),
typeof(CustomTabbedPageRenderer))]
namespace App15.Droid
{
class CustomTabbedPageRenderer : TabbedPageRenderer
{
private TabLayout tabLayout = null;
public CustomTabbedPageRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.TabbedPage> e)
{
base.OnElementChanged(e);
this.tabLayout = (TabLayout)this.GetChildAt(1);
tabLayout.TabMode = TabLayout.ModeScrollable;
tabLayout.TabGravity = TabLayout.GravityFill;
}
}
}
Normally, we could set the TextSize in tabbed page custom renderer. But sometimes we would miss the different types if TextView. So i think the way above would be better. You could also check the way to set the TextSize in custom renderer.
Tabbed page custom renderer on Xamarin.Forms
When TabbedPage use android:TabbedPage.ToolbarPlacement="Bottom" to set the tabs in the bottom, the renderer above does not work. You could refer to teh solution in the link below.
How to change Tabbar text size when using TabbedPage.ToolbarPlacement="Bottom" in Xamarin Android?

Related

Xamarin.Forms: Display additional tab on specific Platform

Good morning
I have a TabbedPage in my application. Due to restictions I would like to display one more tab on Android than on iOS.
My current TabbedPage look like:
<TabbedPage>
...
<ContentPage x:Name="Page1"/>
<ContentPage x:Name="Page2"/>
<ContentPage x:Name="Page3"/>
<ContentPage x:Name="Page4"/>
</TabbedPage>
I have decided to render Page3 only for Android. I changed my code into:
<TabbedPage>
...
<ContentPage x:Name="Page1"/>
<ContentPage x:Name="Page2"/>
<OnPlatform x:TypeArguments="Page">
<On Platform="Android">
<On.Value>
<ContentPage x:Name="Page3"/>
</On.Value>
</On>
</OnPlatform>
<ContentPage x:Name="Page4"/>
</TabbedPage>
This leads to runtime exception when entering into this TabbedPage:
An error occurred: 'Value cannot be null. Parameter name: item'.
Callstack: ' at
Xamarin.Forms.ObservableWrapper`2[TTrack,TRestrict].Add (TRestrict
item) [0x00008] in D:\a\1\s\Xamarin.Forms.Core\ObservableWrapper.cs:27
I tried to remove x:Name but did not work. Any ideas?
PS. As a workaround I am always able to:
Constructor()
{
if(Runtime.IsIOS)
{
this.Children.Remove(this.Page3)
}
}
However would be better to not render it at all and have it at XAML level.
Unless someone comes up with a way to do this in XAML, this is the best you can do (building on Jason's comment):
xaml:
<ContentPage x:Name="Page1"/>
<ContentPage x:Name="Page2"/>
<!-- no Page3 in XAML -->
<ContentPage x:Name="Page4"/>
c#:
private ContentPage page3;
Constructor()
{
InitializeComponent();
if (Runtime.IsAndroid)
{
page3 = new ContentPage();
// After pages 1 and 2.
Children.Insert(2, page3);
}
}
// Elsewhere in code-behind.
if (page3 != null)
{
...refer to page3...
}
This has the advantage of not constructing the page at all on iOS.
It also makes it easy to test whether page3 is there (page3 != null).
In practice, the other pages will typically be their own classes. Given partial class Page3 : ContentPage elsewhere:
private Page3 page3;
...
page3 = new Page3();
According to this,xaml is an alternative to programming code for instantiating and initializing objects, and organizing those objects in parent-child hierarchies.If you add one additional tab on android it will cause a NullReferenceException on ios.So you may want to do it in codebehind with Device.RuntimePlatform.
Here is my test you can refer to:
switch (Device.RuntimePlatform)
{
case Device.Android:
Children.Add(page1);
Children.Add(page2);
break;
case Device.iOS:
Children.Add(page1);
break;
case Device.UWP:
Children.Add(page1);
break;
}

AutoWirePartialView with prism does not work or badly used?

I'm trying to use prism 7.1 AutoWirePartialView to bind a PartialView to its viewModel. However, binding is not working, or at least, setting the viewModel to the PartialView does not seem to work, it still has the page's BindingContext as BindingContext.
There is my Page :
<?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="Project.Core.Views.NotConnectedViews.ForecastDemoPage"
xmlns:carouselForecast="clr-namespace:Project.Core.Views.MainViews"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
x:Name="ForecastDemo"
BackgroundColor="{StaticResource PrimaryColorOne}" ControlTemplate="{StaticResource MainAppTemplate}">
<ContentPage.ToolbarItems>
<ToolbarItem Name="SearchForecast" Command="{Binding ShowSearchForecastDemoCommand}" Order="Primary" Icon="ic_search_white_24dp.png" Priority="0" />
</ContentPage.ToolbarItems>
<ContentView x:Name="ContentViewForecast" ControlTemplate="{StaticResource ForecastTownControlTemplate}">
<carouselForecast:ForecastPartialViewCarousel prism:ViewModelLocator.AutowirePartialView="{x:Reference ForecastDemo}"></carouselForecast:ForecastPartialViewCarousel>
</ContentView>
</ContentPage>
Binding: 'DayWeatherForecasts' property not found on
'Project.Core.ViewModels.ForecastDemoPageViewModel', target property:
'Project.Core.Views.MainViews.ForecastPartialViewCarousel.ItemsSource'
As you can see, I'm using the partial view as a ContentPresenter for a ContentView that uses a ControlTemplate.
There is my PartialView :
<carousel:CarouselViewControl x:Name="carouselView"
Position="{Binding CarouselPosition}"
PositionSelectedCommand="{Binding PositionChanged}"
Orientation="Horizontal" AnimateTransition="True" IsSwipeEnabled="False"
ItemsSource="{Binding DayWeatherForecasts}" InterPageSpacing="10"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:carousel="clr-namespace:CarouselView.FormsPlugin.Abstractions;assembly=CarouselView.FormsPlugin.Abstractions"
x:Class="Project.Core.Views.MainViews.ForecastPartialViewCarousel">
<!-- Item template is defined here, removed for readability -->
</carousel:CarouselViewControl>
And this is my PartialView ViewModel :
namespace Project.Core.ViewModels
{
public class ForecastPartialViewCarouselViewModel : ViewModelBase
{
public ForecastPartialViewCarouselViewModel(IForecastService forecastService,
INavigationService navigationService) : base(navigationService)
{
InitStubForecasts();
}
private ObservableCollection<DayWeatherForecast> _dayWeatherForecasts;
public ObservableCollection<DayWeatherForecast> DayWeatherForecasts
{
get => _dayWeatherForecasts;
set => SetProperty(ref _dayWeatherForecasts, value);
}
}
}
Of course DayWeatherForecasts is set with some stub values. I simplified the viewModel for readability purpose.
I'm not using prism AutoWiring viewModel, so in app.xaml.cs :
containerRegistry.RegisterForNavigation<ForecastDemoPage, ForecastDemoPageViewModel>();
Question : Could it be that my PartialViewModel is in the ViewModels folder and that the Partialview I want to be be bound to this ViewModel is under a subfolder MainViews ? Should I create a MainViewsViewModel folder and put my viewModel there ?
EDIT : I tried this solution, but as I expected it does nothing.
If not, then I don't know why it doesnt work ...
Thanks !
Ok so I finally found out that its not enough to put this to my PartialView
prism:ViewModelLocator.AutowirePartialView="{x:Reference ForecastDemo}
As I organized my views in subfolders, prism cannot register alone my ViewModel and my PartialView.
So what I needed is to register manually the ViewModel with the PartialView using ViewModelLocationProvider
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
ViewModelLocationProvider.Register<ForecastPartialViewCarousel,
ForecastPartialViewCarouselViewModel>();
}
It's not only a matter of name, but of namespace too. If I wanted the PartialView to have the correct ViewModel set w/o registering it manually, I should have put my PartialView in the Views root folder and the corresponding ViewModel in the ViewModels root folder (with naming convention)

How can I make CommandBar render in Xamarin Forms UWP?

I have a ContentPage (actually an MvxContentPage) with ToolbarItems defined. The Items appear in Android and iOS as expected, but do not appear at all in UWP. I have tried setting SetToolbarPlacement to both Top and Bottom manually, in both the constructor and the OnAppearing method. Thus far, I have not been able to affect any change in the UWP application. Am I doing something wrong? Can Mvx not render the Toolbar?
<mvx:MvxContentPage
xmlns:mvx="clr-namespace:MvvmCross.Forms.Views;assembly=MvvmCross.Forms"
x:TypeArguments="viewModels:CategoryListViewModel"
xmlns:viewModels=""
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="GSP.X.AccuStore.Forms.Views.Site.Profiles.CategoryListView">
<ContentPage.ToolbarItems>
<ToolbarItem Text="Areas" Command="{Binding Path=GoToAreasCommand}" />
</ContentPage.ToolbarItems>
</mvx:MvxContentPage>
The problem is you have not add start page to NavigationPage. I have test with the follow code in the blank Xamrin.Froms app, the ToolbarItem display well in the top of MainPage.
public App()
{
InitializeComponent();
var nav = new NavigationPage(new MainPage());
MainPage = nav;
}

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.

reusability user controls of Xaml in xamarin.forms

I am trying a new approach i.e. XAML to make application in xamarin.forms. At this time i am facing an issue to reuse my stack layout which is having a image and label. How i can reuse my layout in different pages using XAML.
You can actually define your custom component in a separate XAML file and then just link the component wherever you need it.
For example a label with image can be grouped together in a dedicated XAML file:
<?xml version="1.0" encoding="utf-8" ?>
<StackLayout xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="UserControls.ImageWithTitle"
VerticalOptions="Center" HorizontalOptions="Center" >
<Label HorizontalOptions="Center"
x:Name="TitleLabel" />
<Image Source="noimage.png" />
</StackLayout>
On the .cs file I've defined a binding for the TitleLabel
public string TitleName
{
get { return TitleLabel.Text; }
set { TitleLabel.Text = value; }
}
So when you include the component on another layout, you can assign the label value directly (or via a binding):
<usercontrols:ImageWithTitle TitleName="Home"/>

Resources