Last active
June 16, 2016 19:35
-
-
Save smetlov/57d7e55f0b7308b0f48911a6ecbd57cd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[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