How to change Shell Tabbar height - c#

My Problem:
I use Shell with bottom Tabbar and I simply want to change it height on Android and maybe on iOS.
My Search Results:
I know that the Tabbar is an Android/iOS build in feature with solid specified height.
There seems to be a way to achieve that using a "Custom-Renderer". All projects I have found with this approach don't work with my visual studio (>100 Errors or simply does nothing).
I find it hard to believe that i need >100 rows of code to "only" adjust a height. Could someone provide a working solution to change the Shell Tabbar (bottom tabs) height ?
Edit

Unfourtounately you need to create a custom renderer on each platform project:
Android
MyShellRenderer class
[assembly: ExportRenderer(typeof(App.AppShell), typeof(App.Droid.MyShellRenderer))]
namespace App.Droid
{
public class MyShellRenderer : ShellRenderer
{
public MyShellRenderer(Context context) : base(context)
{
}
protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
{
return new MyBottomNavViewAppearanceTracker(this, shellItem);
}
}
}
MyBottomNavViewAppearanceTracker class
class MyBottomNavViewAppearanceTracker : ShellBottomNavViewAppearanceTracker
{
public MyBottomNavViewAppearanceTracker(IShellContext shellContext, ShellItem shellItem) : base(shellContext, shellItem)
{
}
public override void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
{
bottomView.LayoutParameters.Height = 400;
base.SetAppearance(bottomView, appearance);
}
}
Edit:
iOS part credit goes to https://forums.xamarin.com/discussion/169894/how-to-change-shell-height-of-flyout-items-at-the-bottom-of-the-page
iOS
MyShellRenderer class
[assembly: ExportRenderer(typeof(App.AppShell), typeof(App.iOS.MyShellRenderer))]
namespace App.iOS
{
public class MyShellRenderer : ShellRenderer
{
protected override IShellTabBarAppearanceTracker CreateTabBarAppearanceTracker()
{
return new MyCreateTabBarAppearanceTracker();
}
}
}
CreateTabBarAppearanceTracker class
class CreateTabBarAppearanceTracker : ShellTabBarAppearanceTracker
{
public override void SetAppearance(UITabBarController controller, ShellAppearance appearance)
{
UITabBar tabBar = controller.TabBar;
int tabBarHeight = 100;
if (tabBar.Frame.Height != tabBarHeight)
{
tabBar.Frame = new CGRect(tabBar.Frame.X, tabBar.Frame.Y + (tabBar.Frame.Height - tabBarHeight), tabBar.Frame.Width, tabBarHeight);
}
}
}
Extras
You were probably missing some namespaces that would explains the abnormal big number of errors.
could not be found are you missing a using directive or an assembly reference
Usually people don't include namespaces (using statements) in answers because most of the time namespaces are obvious and are handled easily by visual studio intellisense.
Just put or hover the cursor on the red underlined statement and a small tooltip appears
Then click on "Show potential fix" or one of the keyboard shortcuts, select the appropriate fix (usually the first one of the suggested list), in this case intelisense will add the required namespace automatically.

Every Code example i have found has excluded the using directives. in my case i needed those following 3 which i wasnt able to find. Thanks to the answer of #Cfun the code above work with adding:
using Google.Android.Material.BottomNavigation;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

Related

Previewing Fonts in Designer in Xamarin.FORMS

I made a Xamarin.Forms project and I referenced my own font and then added an alias in the assembly like so:
[assembly: ExportFont("Samantha.ttf", Alias = "MyAwesomeCustomFont")]
Now... the thing is, this font which I have referenced is NOT being shown in the designer, instead I'm still getting the default font, even after referencing it:
<Button WidthRequest="70" Text="Click me" FontFamily="MyAwesomeCustomFont"/>
Now, this is frustrating because it is working when I deploy it and it showing the font
although I want the designer to illustrate exactly what's going on, so I do want the custom font to be shown in the designer... Is this possible?
Thanks,
I've solved my own problem. I created a custom renderer and it's showing in the preview:
[assembly: ExportRenderer(typeof(Xamarin.Forms.Button), typeof(CustomButtonRenderer))]
namespace Custombutton.Droid
{
class CustomButtonRenderer : ButtonRenderer
{
public CustomButtonRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.SetAllCaps(false);
Typeface tf = Typeface.CreateFromAsset(Android.App.Application.Context.Assets, "NUNITO-BOLD.ttf");
Control.SetTypeface(tf, TypefaceStyle.Bold);
}
}
}
}
Result in designer:

How can I change style of the original tabbed page bar (android with xamarin.forms)?

good morning,
I'm designing my first app in xamarin.forms, but I ran into a problem that is the style of the tabbedpage bar in android.
On iOS it works great, but on Android it has a different display, but I would like to make the homogeneous thing on both operating systems know how to do it?
Screen Android https://ibb.co/cYRLvc4
Screen iOS https://ibb.co/ysnxBr8
You should use a custom effect, first update your android target to 9.0 (and support libraries)
then, create the Routing Effect in your Forms solution:
using Xamarin.Forms;
namespace YourApp
{
public class NoShiftEffect : RoutingEffect
{
public NoShiftEffect() : base("MyEffect.NoShiftEffect")
{
}
}
}
Then, in Android, create a custom renderer:
using Android.Support.Design.BottomNavigation;
using Android.Support.Design.Widget;
using Android.Views;
using yournamespace.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly:ResolutionGroupName ("MyEffect")]
[assembly:ExportEffect (typeof(NoShiftEffect), "NoShiftEffect")]
namespace yournamespace.Droid
{
public class NoShiftEffect : PlatformEffect
{
protected override void OnAttached ()
{
if (!(Container.GetChildAt(0) is ViewGroup layout))
return;
if (!(layout.GetChildAt(1) is BottomNavigationView bottomNavigationView))
return;
// This is what we set to adjust if the shifting happens
bottomNavigationView.LabelVisibilityMode = LabelVisibilityMode.LabelVisibilityLabeled;
}
protected override void OnDetached ()
{
}
}
}
finally, in your tabbde page:
<TabbedPage.Effects>
<local:NoShiftEffect />
</TabbedPage.Effects>

Referencing of classes and namespaces Visual Studio 2017

I noticed for my little project that when importing classes some use full folder reference while otheres don't.
Here is code from project Mini that i am working on.
Models folder
Contains two entities, Auto and Airplane
namespace Mini.Models {
public class Auto {
// code and stuff
}
}
namespace Mini.Models {
public class Airplane {
// code and stuff
}
}
Services folder Contains single service class
namespace Mini.Services
{
public class AutoService : IAutoService {
public bool Get() {
var autoObject = new Models.Auto(); // notice how it references Models folder
var planeObject = new Airplane(); // Same folder but not referencing Models in front of it
// other code
}
}
public interface IAutoService {
bool Get();
// others
}
}
While not a major bugbear, it is still annoying that two classes in same folder get referenced differently, and i cannot figure out why.
Any advice would be appreciated.
Error Message when removing Models folder
Error CS0118: 'Auto' is a namespace but is used like a type (34, 27)
Based on the error message you have provided:
Error CS0118: 'Auto' is a namespace but is used like a type (34, 27)
It would appear that you have a namespace called Auto. Imagine the following example:
namespace MyApp.Auto
{
class Test
{
}
}
namespace MyApp
{
class Auto
{
}
class MyTest
{
private Auto test;
}
}
Because you can see, from the MyApp namespace, both a class called Auto and a namespace called Auto (either namespace MyApp.Auto or simply namespace Auto), C# isn't sure which one you want. As such, it's forcing you to be specific in choosing one or the other.
The easiest solution is to change the MyApp.Auto namespace to something else.
This is not fix but explaining with proper code sample (and why ).
namespace Mini.Models
{
public class Auto
{
// code and stuff
}
}
namespace Mini.Models
{
public class Airplane
{
// code and stuff
}
}
namespace Mini.Auto
{
public class OtherAirplane
{
// code and stuff
}
}
namespace Mini
{
using Mini.Models;
using namespaceAuto = Auto ; /// this also not fix the issue.
class NamespaceIssue
{
void execute()
{
var autoObject = new Auto(); // Error
var planeObject = new Airplane(); // Same folder but not referencing Models in front of it
// other code
}
}
}
now you can see some were in code you have "Mini.Auto" namespace , and it is couching issue.
i tested for VS 2015 have same issue. maybe we have to report to VS team or it is by design .
The issue seemed to be with VS2017 or the way it created the project first time around.
Upon starting brand new project (ASP Core 2.2, Web API, with https enabled and docker disabled), and using same classes the issue was non-existant.

How is Setup class instantiated in MVVMCross in Xamarin?

I'm starting learning MVVM cross, In the android app, I have a splash screen class:
[Activity(MainLauncher = true,
Label = "#string/app_name",
Theme = "#style/Theme.Splash",
NoHistory = true,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation,
ScreenOrientation = ScreenOrientation.Portrait)]
public class SplashScreen : MvxSplashScreenActivity
{
public SplashScreen() : base(Resource.Layout.SplashScreen)
{
}
}
and this is the Setup class:
public class Setup : MvxAndroidSetup
{
protected Setup(Context applicationContext) : base(applicationContext)
{
}
protected override IMvxApplication CreateApp()
{
return null;
}
}
the problem is that the debugger doesn't hit the constructor of the Setup Class, instead I get "An unhandled exception" after the constructor of the splash screen
EDIT
I've already defined the App class in the PCL project:
public class App : MvxApplication
{
public override void Initialize()
{
base.Initialize();
}
also defined the AppStart:
public class AppStart : MvxNavigatingObject, IMvxAppStart
{
public async void Start(object hint = null)
{
//hardcoded login for this demo
//var userService = Mvx.Resolve<IUserDataService>();
//await userService.Login("gillcleeren", "123456");
ShowViewModel<MainViewModel>();
}
}
The main reason behind this project is to understand the sequence of code required and executed by MVVM Cross, so I provide the minimum code till it runs successfully without runtime errors.
Update
I have read your code again more thoroughly and I can see the issue now. You defined the constructor of the Setup class as protected, which makes it invisible for activation.
On MvvmCross for Android the magic happens inside MvxAndroidSetupSingleton class (see the source code here) which searches for the Setup type you defined. The FindSetupType method looks for your defined Setup class first and then inside the CreateSetup method Activator.CreateInstance is used to build the Setup instance. The CreateInstance method variant used however searches only for public constructors, which means it doesn't find your protected one. The result is that it cannot build the Setup class and crashes.
Original answer
The reason this happens is that you have no Core libary that would define the MvvmCross App class and would initialize other required setup. I suggest you to start with a simple tutorial or to look into the official sample projects to see what is necessary to make MvvmCross work in a Xamarin.Android app.

Xamarin - Custom Switch not working

So this is the very first time I try to create a custom renderer. I followed this thread here: https://forums.xamarin.com/discussion/32264/how-can-i-change-switch-text-color-android. I took a look at the first guy who placed an example code. I tried to use it with my own renderer but It gives the following error:
Type or namespace 'controls' doesn't exist in 'saleskicker'
here is my code:
using System;
using Xamarin.Forms.Platform.Android;
using Xamarin.Forms;
using SalesKicker;
[assembly:ExportRenderer(typeof(SalesKicker.Controls.CustomSwitch), typeof(CustomSwitchRenderer))]
namespace SalesKicker
{
public class CustomSwitchRenderer : SwitchRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Switch> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.TextOn = "AAN";
Control.TextOff = "UIT";
Control.SetTextColor(Color.White);
}
if (Control.Checked == true)
{
Control.SetBackgroundColor(Color.Green);
}
}
}
}
However, the error didn't show up when I had the class inside a folder called 'CustomRenderers'. But I think this shouldn't be such a big deal. What am I doing wrong here? Can someone please help me?
If you just want to change the Color, you don't need a CustomControl. And then you can replace the default renderer with your own.
[assembly:ExportRenderer(typeof(Switch), typeof(CustomSwitchRenderer))]

Categories

Resources