Xamarin.forms: [Enhancement] Implement fixed mode for Bottom Navigation Bar Android

Created on 19 Jun 2018  Â·  40Comments  Â·  Source: xamarin/Xamarin.Forms

Description

Currently if you add more then 3 icons to the bottom tab bar on android it will use an animated shifting mode to display all the tabs.

Support libraries v28 surface a new setting on BottomNavigationView
LabelVisibilityMode

Once we take a dependency on v28 with forms then we should surface that enumeration for the platform specifics.

API Changes

Add an android platform specific api for
C# public enum BottomToolBarLabelVisibilityMode { Default; Auto ; Labeled Selected Unlabeled } SetBottomToolBarLabelVisibilityMode(BottomToolBarLabelVisibilityMode labelVisibilityMode) SetBottomToolBarItemHorizontalTranslationEnabled(bool)
When implementing these settings make sure to just ignore these if they haven't been set and to retain the default if changed

Notes

https://github.com/xamarin/Xamarin.Forms/issues/1675#issuecomment-394419356
https://montemagno.com/remove-shifting-bottomnavigationview-android/

navbar in-progress high impact Android proposal-open enhancement âž•

Most helpful comment

All 40 comments

Hi @PureWeen,

Just out of curiosity, did you manage to get James's code working? I'm trying to use his code to remove shifting for our production app using bottom tab bar but failing.

Using latest Xamarin.Forms 3.1 and Targeting Android 8.1

The offending code is :

FindViewById<BottomNavigationView>(Resource.Id.bottom_navigation);

Looking at the renderer it appears the BottomNavigationView is generated from code behind along with it's ID.

Hence FindViewById<BottomNavigationView>(Resource.Id.bottom_navigation); fails to compile as that resource is not available during compile time with the message

'Resource.Id' does not contain a definition for 'bottom_navigation'

Can you help us out please with some pointers?

Regards,

@syed-pelican We were having a discussion in https://github.com/xamarin/Xamarin.Forms/issues/1675 and LynoDesu posted a wonderful gist which shows how to inclement a custom renderer for Android to remove shifting.

https://gist.github.com/LynoDesu/64904b6d143892cf14a60a32798a36bb

I believe it's a bit different in that it didn't look for the tabbed pages by Id, but it worked for me.

Cheers!

@greenec Yup! stumbled upon it and got it working visually. :D

Thanks!

Correct, mine is for traditional native Android, not for Forms. But that was the route I was about to blog up.

up-for-grabs label should be removed as this issue cannot be resolved before Forms is compatible with support packages v28: https://github.com/xamarin/Xamarin.Forms/pull/4003/files#r226462764

Will the ability to set BottomToolBarLabelVisibilityMode be implemented soon? Is there any workaround that is working for now?

Now that 28.0.0.1 is out we should be able to implement this. We will probably have to try/catch incase 28.x isn't installed though.

It wouldn't be too much work if someone wants to use this existing PR

https://github.com/xamarin/Xamarin.Forms/pull/4003#issuecomment-448449343

With the Shell changes we added a utility method that easily just applies the shifting mode based on if you are using API 27 vs 28

https://github.com/xamarin/Xamarin.Forms/blob/78385f9fc1fc56dc88bd98e73bf9c8f2f2d0a90a/Xamarin.Forms.Platform.Android/Renderers/BottomNavigationViewUtils.cs

Thanks for the replies! It seems like those guides are specific to Xamarin Forms. :( Was it a mistake to use android.support.design.widget.BottomNavigationView if I don't want labels? I can set the labels to be empty but that makes the icons line up with an empty space below them. In native android, there is the setBottomToolBarLabelVisibilityMode functionality, but it's missing in Xamarin Android. I've got fairly specific designs I need to adhere to, so I would appreciate any ideas or support.

In native android, there is the setBottomToolBarLabelVisibilityMode functionality, but it's missing in Xamarin Android

My guess is that you are targeting API 27
That method is only available in the Support 28 libraries when your app is targeting API 28 and above

or @hunter-digital if you look at the code here

https://github.com/xamarin/Xamarin.Forms/blob/78385f9fc1fc56dc88bd98e73bf9c8f2f2d0a90a/Xamarin.Forms.Platform.Android/Renderers/BottomNavigationViewUtils.cs

That's all just native android code that does what you want. It has a version that works for API 27 and a version that works for API 28

Thanks guys. I was indeed targeting 27, but the bottomNavigationView.LabelVisibilityMode property doesn't show up. I ended up rigging the BottomNavigationViewUtils file found in one of James Montemagno's articles to also set the padding of the BottomNavigationItemViews as such:

for(int i = 0; i < menuView.ChildCount; i++) { var item = menuView.GetChildAt(i) as BottomNavigationItemView; if (item == null) continue; item.SetShiftingMode(enableItemShiftMode); item.SetChecked(item.ItemData.IsChecked); // Remove labels and center var largeLabelItem = item.FindViewById(Resource.Id.largeLabel); var smallLabelItem = item.FindViewById(Resource.Id.smallLabel); item.RemoveView(largeLabelItem); item.RemoveView(smallLabelItem); item.SetPadding(35,35,35,35); }

It's not perfect, and I need to add some more visual goodies, but I will have to revisit when I have time to actually extend the classes. Thanks again.

@hunter-digital when you have a chance can you post a picture of the UI you achieved so we can make sure it's a use case that is considered when implementing this? Thank you in advance

@hunter-digital Just check this one out https://github.com/muhaym/ElegantTabs
I had similar requirements, and I made an extendible Tabs, bit hacky, but get the things done. Do open issue in the repo if you need to know more.

@pauldipietro During our meeting we discussed this, we need to plan a complete flexible tab control!

Hey @jamesmontemagno . Thank you for this awesome blogpost. As I said on disqus, I tested your effect trick, but LabelVisibilityLabeled acts just like LabelVisibilitySelected . This is not a prob of implementation as other modes are working great ... Thanks !

Thanks for the good news @jamesmontemagno. I was wondering if we could disable the zoom-in effect whenever a tab is selected in Labeled mode? Text and the icon gets zoomed in whenever I select a tab and this truncates some tab texts which are long.

@vincentcastagna Have u tried to set android:TabbedPage.BarItemColor?

<android.support.design.widget.BottomNavigationView
    app:labelVisibilityMode="unlabeled"

Pretty late to the party, but on the off chance you see this and have the time to respond, I'm running into an issue where setting the value to Unlabeled or Selected works, but the other two options do not.

if I have any number (2 or more) of tabs, only the selected tab will show text or none of them will show when 'unlabeled' is selected

Xamarin.Forms 4.4.0.991757
Android Support Packages: 28.0.0.3 (Annotations, Compat, Core.Utils, CustomTabs)
The TabbedPage we use utilizes a custom renderer (BadgedTabbedPageRenderer)

We were previously using reflection in an overridden OnLayout call that would call SetShiftMode(false,false) but when that stopped working I attempted to implement the solution that James posted about in his blog here, which allowed me to set the value to unlabeled successfully, but all other options resulted in what the 'Selected' option describes.

Happy to provide any other details as I can. More than willing to believe that we have either set up our tabbed page incorrectly or are doing things that conflict with this labelVisibilityMode property somehow

*edit - additional note, it appears that setting the value to 'LabelVisibilityLabeled' will move all of the icons up to account for the text, but does not draw the text (Samsung Active Tab 2, Debug GPU Overdraw)

Hi @jermoe1 I have the same issue.. Have you found a solution for this?

@jamesmontemagno has something changed in the latest packages? I'm using 4.5.0.396 and setting the VisibilityMode is not working. I'm just adding this stuff now so I cannot say if this would have worked with earlier versions.

EDIT: Sorry.. figured out the issue.. I had to set the Text Color for Android with a ColorStateList so it gets an unselected Text Color.. @jermoe1 maybe its the same for you?

@PureWeen, is this problem still open to community work? I think we can solve this problem and

6220 in the same PR.

Yes! @pictos

@PureWeen I want to work on this, if it's possible. I have a question... Why we don't add the reference of Xamarin.Android.Support.Core.Utils package into the Xamarin.Forms.Platform.Android, when the target is not MonoAndroid10.0? That way we don't need to use the reflection code (used here).

I'm pretty sure all the code inside

#if __ANDROID81__

Can just get deleted. We're not compiling that target anymore

What about adding Xamarin.Android.Support.Core.Util? I'm asking this because in MonoAndroid9 there is no LabelVisibilityMode property and the LabelVisibilityMode enumeration.

I feel like you're looking at a really old branch. There's a LabelVisibilityMode on API 28 and 29

https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/BottomNavigationViewUtils.cs#L19

Yes, for the API29 it's by default, but for older versions isn't. I made some tests just for Shell, and to make it work I need to add that XA.Support package. You can see my comment here and here you can see my branch/commit

I'm still not following :-(

this code
```C#

        var p = ShellItem.Items;

        if (!p.Any(x => string.IsNullOrEmpty(x.Title)))
            _bottomView.LabelVisibilityMode = LabelVisibilityMode.LabelVisibilityUnlabeled;
        else
            _bottomView.LabelVisibilityMode = LabelVisibilityMode.LabelVisibilityAuto;

```

Works without that nuget

That library is only relevant if you are targeting API 27

You'll see that I did a PR for essentials here
https://github.com/xamarin/Essentials/pull/903

Removing that nuget if you're above API27

I think your branch is old and still building with API 27

Strange, here I can't run without that package. I'll update everything here and try again. If it works I'll implement and open a PR ASAP.

Sounds good @pictos !!

Excited for it

@PureWeen, just to confirm. We can't access the IPlatformElementConfiguration<PlatformConfiguration.Android, T> OnThisPlatform<T>(this T element) from shell, is that correct?

example

Element.OnThisPlatform().SomeFancyMethod();

It's been a minute since I've reviewed this API but would there be a way to make this work on all the platforms?

So we can just add the property to TabbedPage and as a property on BaseShellItem?

I created an AttachedProperty for Shell and the PlatformEspecific for TabbedPage. This after I tried some approaches to have the OnThisPlatform method inside the ShellItemRenderer. Is that a problem, do this way for now?

Yea, do that for now!

Was this page helpful?
0 / 5 - 0 ratings