Skip to content

Instantly share code, notes, and snippets.

@smetlov
Last active June 16, 2016 19:35
Show Gist options
  • Save smetlov/57d7e55f0b7308b0f48911a6ecbd57cd to your computer and use it in GitHub Desktop.
Save smetlov/57d7e55f0b7308b0f48911a6ecbd57cd to your computer and use it in GitHub Desktop.
[assembly: ExportRenderer(typeof(MainPage), typeof(MainPageRenderer))]
namespace CustomBottomMenu.Droid.Renderers
{
internal class MainPageRenderer : VisualElementRenderer<MainPage>, IOnTabClickListener
{
public MainPageRenderer()
{
// Required to say packager to not to add child pages automatically
AutoPackage = false;
}
public void OnTabSelected(int position)
{
LoadPageContent(position);
}
protected override void OnElementChanged(ElementChangedEventArgs<MainPage> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
ClearElement(e.OldElement);
}
if (e.NewElement != null)
{
InitializeElement(e.NewElement);
}
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
if (Element == null)
{
return;
}
int width = r - l;
int height = b - t;
_bottomBar.Measure(
MeasureSpec.MakeMeasureSpec(width, MeasureSpecMode.Exactly),
MeasureSpec.MakeMeasureSpec(height, MeasureSpecMode.AtMost));
// We need to call measure one more time with measured sizes
// in order to layout the bottom bar properly
_bottomBar.Measure(
MeasureSpec.MakeMeasureSpec(width, MeasureSpecMode.Exactly),
MeasureSpec.MakeMeasureSpec(_bottomBar.ItemContainer.MeasuredHeight, MeasureSpecMode.Exactly));
int barHeight = _bottomBar.ItemContainer.MeasuredHeight;
_bottomBar.Layout(0, b - barHeight, width, b);
float density = Android.Content.Res.Resources.System.DisplayMetrics.Density;
double contentWidthConstraint = width / density;
double contentHeightConstraint = (height - barHeight) / density;
if (_currentPage != null)
{
var renderer = Platform.GetRenderer(_currentPage);
renderer.Element.Measure(contentWidthConstraint, contentHeightConstraint);
renderer.Element.Layout(new Rectangle(0, 0, contentWidthConstraint, contentHeightConstraint));
renderer.UpdateLayout();
}
}
private void InitializeElement(MainPage element)
{
PopulateChildren(element);
}
private void PopulateChildren(MainPage element)
{
// Unfortunately bottom bar can not be reused so we have to
// remove it and create the new instance
_bottomBar?.RemoveFromParent();
_bottomBar = CreateBottomBar(element.Children);
AddView(_bottomBar);
LoadPageContent(0);
}
private BottomBar CreateBottomBar(IEnumerable<Page> pageIntents)
{
var bar = new BottomBar(Context);
// TODO: Configure the bottom bar here according to your needs
bar.SetOnTabClickListener(this);
bar.UseFixedMode();
PopulateBottomBarItems(bar, pageIntents);
bar.ItemContainer.SetBackgroundColor(Color.LightGray);
return bar;
}
private void PopulateBottomBarItems(BottomBar bar, IEnumerable<Page> pages)
{
var barItems = pages.Select(x => new BottomBarTab(Context.Resources.GetDrawable(x.Icon), x.Title));
bar.SetItems(barItems.ToArray());
}
private void LoadPageContent(int position)
{
ShowPage(position);
}
private void ShowPage(int position)
{
if (position != _lastSelectedTabIndex)
{
Element.CurrentPage = Element.Children[position];
if (Element.CurrentPage != null)
{
LoadPageContent(Element.CurrentPage);
}
}
_lastSelectedTabIndex = position;
}
private void LoadPageContent(Page page)
{
UnloadCurrentPage();
_currentPage = page;
LoadCurrentPage();
Element.CurrentPage = _currentPage;
}
private void LoadCurrentPage()
{
var renderer = Platform.GetRenderer(_currentPage);
if (renderer == null)
{
renderer = Platform.CreateRenderer(_currentPage);
Platform.SetRenderer(_currentPage, renderer);
AddView(renderer.ViewGroup);
}
else
{
// As we show and hide pages manually OnAppearing and OnDisappearing
// workflow methods won't be called by the framework. Calling them manually...
var basePage = _currentPage as BaseContentPage;
basePage?.SendAppearing();
}
renderer.ViewGroup.Visibility = ViewStates.Visible;
}
private void UnloadCurrentPage()
{
if (_currentPage != null)
{
var basePage = _currentPage as BaseContentPage;
basePage?.SendDisappearing();
var renderer = Platform.GetRenderer(_currentPage);
if (renderer != null)
{
renderer.ViewGroup.Visibility = ViewStates.Invisible;
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment