Skip to content

Instantly share code, notes, and snippets.

@mr5z
Last active May 13, 2021 07:11
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mr5z/4c36e45c6b2751bd5ecbcc2f7e9fbb35 to your computer and use it in GitHub Desktop.
Save mr5z/4c36e45c6b2751bd5ecbcc2f7e9fbb35 to your computer and use it in GitHub Desktop.
Raised Middle Button TabbedPage implementation for Xamarin.Android. Just replace the `Replace_With_Your_Custom_BottomNavigationView` with your own implementation of BNV!
using System;
using System.Reflection;
using Android.Content;
using Android.Support.Design.Widget;
using Android.Support.V4.View;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using AWidget = Android.Widget;
using ATabbedRenderer = Xamarin.Forms.Platform.Android.AppCompat.TabbedPageRenderer;
using System.Collections.Specialized;
namespace Your.Namespace.Here
{
public class RaisedTabbedPageRenderer : ATabbedRenderer
{
AWidget.RelativeLayout InternalRelativeLayout
{
get
{
var field = typeof(ATabbedRenderer).GetField("_relativeLayout", BindingFlags.NonPublic | BindingFlags.Instance);
return (AWidget.RelativeLayout)field.GetValue(this);
}
set
{
var field = typeof(ATabbedRenderer).GetField("_relativeLayout", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(this, value);
}
}
BottomNavigationView InternalBottomNavigationView
{
get
{
var field = typeof(ATabbedRenderer).GetField("_bottomNavigationView", BindingFlags.NonPublic | BindingFlags.Instance);
return (BottomNavigationView)field.GetValue(this);
}
set
{
var field = typeof(ATabbedRenderer).GetField("_bottomNavigationView", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(this, value);
}
}
ViewPager InternalViewPager
{
get
{
var field = typeof(ATabbedRenderer).GetField("_viewPager", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance);
return (ViewPager)field.GetValue(this);
}
set
{
var field = typeof(ATabbedRenderer).GetField("_viewPager", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(this, value);
}
}
public RaisedTabbedPageRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
{
base.OnElementChanged(e);
PerformHack(e);
}
void PerformHack(ElementChangedEventArgs<TabbedPage> e)
{
RemoveView(InternalRelativeLayout);
InternalRelativeLayout = new AWidget.RelativeLayout(Context)
{
LayoutParameters = new LayoutParams(LayoutParams.MatchParent, LayoutParams.MatchParent)
};
if (InternalBottomNavigationView != null)
{
InternalRelativeLayout.RemoveView(InternalBottomNavigationView);
InternalBottomNavigationView.SetOnNavigationItemSelectedListener(null);
}
var bottomNavigationViewLayoutParams = new AWidget.RelativeLayout.LayoutParams(
LayoutParams.MatchParent,
LayoutParams.WrapContent);
bottomNavigationViewLayoutParams.AddRule(AWidget.LayoutRules.AlignParentBottom);
// TODO Replace with your custom BottomNavigationView
InternalBottomNavigationView = new RaisedBottomNavigationBar(Context)
{
LayoutParameters = bottomNavigationViewLayoutParams,
Id = GenerateViewId()
};
var viewPagerParams = new AWidget.RelativeLayout.LayoutParams(LayoutParams.MatchParent, LayoutParams.MatchParent);
viewPagerParams.AddRule(AWidget.LayoutRules.Above, InternalBottomNavigationView.Id);
var pager = InternalViewPager;
pager.RemoveFromParent();
InternalRelativeLayout.AddView(pager, viewPagerParams);
InternalRelativeLayout.AddView(InternalBottomNavigationView, bottomNavigationViewLayoutParams);
AddView(InternalRelativeLayout);
OnChildrenCollectionChangedInternal(null, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
TabbedPage tabbedPage = e.NewElement;
if (tabbedPage.CurrentPage != null)
InvokeMethod("ScrollToCurrentPage");
InvokeMethod("UpdateBarBackgroundColor");
InvokeMethod("UpdateBarTextColor");
InvokeMethod("UpdateItemIconColor");
InvokeMethod("UpdateSwipePaging");
InvokeMethod("UpdateOffscreenPageLimit");
}
void OnChildrenCollectionChangedInternal(object sender, NotifyCollectionChangedEventArgs e)
{
MethodInfo privMethod = typeof(ATabbedRenderer).GetMethod("OnChildrenCollectionChanged", BindingFlags.NonPublic | BindingFlags.Instance);
privMethod.Invoke(this, new object[] { sender, e });
}
void InvokeMethod(string methodName)
{
MethodInfo privMethod = typeof(ATabbedRenderer).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
privMethod.Invoke(this, new object[] { });
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment