Skip to content

Instantly share code, notes, and snippets.

@LynoDesu
Created June 20, 2018 19:04
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save LynoDesu/64904b6d143892cf14a60a32798a36bb to your computer and use it in GitHub Desktop.
Save LynoDesu/64904b6d143892cf14a60a32798a36bb to your computer and use it in GitHub Desktop.
Disable ShiftMode in Xamarin.Forms Android BottomNavigationView
using System;
using Android.Support.Design.Internal;
using Android.Support.Design.Widget;
namespace MyProject.App.Droid.Helpers
{
public static class AndroidHelpers
{
public static void SetShiftMode(this BottomNavigationView bottomNavigationView, bool enableShiftMode, bool enableItemShiftMode)
{
try
{
var menuView = bottomNavigationView.GetChildAt(0) as BottomNavigationMenuView;
if (menuView == null)
{
System.Diagnostics.Debug.WriteLine("Unable to find BottomNavigationMenuView");
return;
}
var shiftMode = menuView.Class.GetDeclaredField("mShiftingMode");
shiftMode.Accessible = true;
shiftMode.SetBoolean(menuView, enableShiftMode);
shiftMode.Accessible = false;
shiftMode.Dispose();
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);
}
menuView.UpdateMenuView();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Unable to set shift mode: {ex}");
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
namespace MyProject.App.Controls
{
public class BottomNavTabPage : TabbedPage
{
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Support.Design.Widget;
using Android.Views;
using Android.Widget;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android.AppCompat;
using View = Android.Views.View;
[assembly: ExportRenderer(typeof(BottomNavTabPage), typeof(BottomNavTabPageRenderer))]
namespace MyProject.App.Droid.Renderers
{
public class BottomNavTabPageRenderer : TabbedPageRenderer
{
private bool _isShiftModeSet;
public BottomNavTabPageRenderer(Context context)
: base(context)
{
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
try
{
if (!_isShiftModeSet)
{
var children = GetAllChildViews(ViewGroup);
if (children.SingleOrDefault(x => x is BottomNavigationView) is BottomNavigationView bottomNav)
{
bottomNav.SetShiftMode(false, false);
_isShiftModeSet = true;
}
}
}
catch (Exception e)
{
Console.WriteLine($"Error setting ShiftMode: {e}");
}
}
private List<View> GetAllChildViews(View view)
{
if (!(view is ViewGroup group))
{
return new List<View> {view };
}
var result = new List<View>();
for (int i = 0; i < group.ChildCount; i++)
{
var child = group.GetChildAt(i);
var childList = new List<View> {child};
childList.AddRange(GetAllChildViews(child));
result.AddRange(childList);
}
return result.Distinct().ToList();
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
<controls:BottomNavTabPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:MyProject.App.Views;assembly=MyProjects.App"
xmlns:controls="clr-namespace:MyProject.App.Controls;assembly=MyProjects.App"
x:Class="MyProject.App.Views.MainTabPage"
Title="">
<views:NewsFeed></views:NewsFeed>
<views:Rewards></views:Rewards>
<views:Nominations></views:Nominations>
<views:Notifications></views:Notifications>
</controls:BottomNavTabPage>
@abhcr
Copy link

abhcr commented May 30, 2021

FYI
var shiftMode = menuView.Class.GetDeclaredField("mShiftingMode");
This property is not accessible if pro guard obfuscates it. Either edit the pro guard configuration, or just comment it out. The code just below it where each child contents in the tab has item.SetShifting(false) -> will solve the issue for most. In such cases, the swipe from edges will still allow tab switching, but not swipe inside the content. I found that optimal in my use case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment