protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (_child == null) { SetMeasuredDimension(0, 0); return; } VisualElement element = _child.Element; Context ctx = Context; var width = (int)ctx.FromPixels(MeasureSpecFactory.GetSize(widthMeasureSpec)); SizeRequest request = _child.Element.Measure(width, double.PositiveInfinity, MeasureFlags.IncludeMargins); Xamarin.Forms.Layout.LayoutChildIntoBoundingRegion(_child.Element, new Rectangle(0, 0, width, request.Request.Height)); int widthSpec = MeasureSpecFactory.MakeMeasureSpec((int)ctx.ToPixels(width), MeasureSpecMode.Exactly); int heightSpec = MeasureSpecFactory.MakeMeasureSpec((int)ctx.ToPixels(request.Request.Height), MeasureSpecMode.Exactly); _child.View.Measure(widthMeasureSpec, heightMeasureSpec); SetMeasuredDimension(widthSpec, heightSpec); }
void IPlatformLayout.OnLayout(bool changed, int l, int t, int r, int b) { if (Page == null) { return; } if (changed) { LayoutRootPage(Page, r - l, b - t); } GetRenderer(Page)?.UpdateLayout(); for (var i = 0; i < _renderer.ChildCount; i++) { AView child = _renderer.GetChildAt(i); if (child is ModalContainer) { child.Measure(MeasureSpecFactory.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(t - b, MeasureSpecMode.Exactly)); child.Layout(l, t, r, b); } } }
protected override void OnLayout(bool changed, int l, int t, int r, int b) { AToolbar bar = _toolbar; // make sure bar stays on top of everything bar.BringToFront(); int barHeight = ActionBarHeight(); if (Element.IsSet(BarHeightProperty)) { barHeight = Element.OnThisPlatform().GetBarHeight(); } if (barHeight != _lastActionBarHeight && _lastActionBarHeight > 0) { ResetToolbar(); bar = _toolbar; } _lastActionBarHeight = barHeight; bar.Measure(MeasureSpecFactory.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(barHeight, MeasureSpecMode.Exactly)); var barOffset = ToolbarVisible ? barHeight : 0; int containerHeight = b - t - ContainerTopPadding - barOffset - ContainerBottomPadding; PageController.ContainerArea = new Rectangle(0, 0, Context.FromPixels(r - l), Context.FromPixels(containerHeight)); // Potential for optimization here, the exact conditions by which you don't need to do this are complex // and the cost of doing when it's not needed is moderate to low since the layout will short circuit pretty fast Element.ForceLayout(); base.OnLayout(changed, l, t, r, b); bool toolbarLayoutCompleted = false; for (var i = 0; i < ChildCount; i++) { AView child = GetChildAt(i); Page childPage = (child as PageContainer)?.Child?.Element as Page; if (childPage == null) { return; } // We need to base the layout of both the child and the bar on the presence of the NavBar on the child Page itself. // If we layout the bar based on ToolbarVisible, we get a white bar flashing at the top of the screen. // If we layout the child based on ToolbarVisible, we get a white bar flashing at the bottom of the screen. bool childHasNavBar = NavigationPage.GetHasNavigationBar(childPage); if (childHasNavBar) { bar.Layout(0, 0, r - l, barHeight); child.Layout(0, barHeight + ContainerTopPadding, r, b - ContainerBottomPadding); } else { bar.Layout(0, -1000, r, barHeight - 1000); child.Layout(0, ContainerTopPadding, r, b - ContainerBottomPadding); } toolbarLayoutCompleted = true; } // Making the layout of the toolbar dependant on having a child Page could potentially mean that the toolbar is not laid out. // We'll do one more check to make sure it isn't missed. if (!toolbarLayoutCompleted) { if (ToolbarVisible) { bar.Layout(0, 0, r - l, barHeight); } else { bar.Layout(0, -1000, r, barHeight - 1000); } } }
protected override void OnLayout(bool changed, int l, int t, int r, int b) { AToolbar bar = _toolbar; // make sure bar stays on top of everything bar.BringToFront(); base.OnLayout(changed, l, t, r, b); int barHeight = ActionBarHeight(); if (barHeight != _lastActionBarHeight && _lastActionBarHeight > 0) { ResetToolbar(); bar = _toolbar; } _lastActionBarHeight = barHeight; bar.Measure(MeasureSpecFactory.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(barHeight, MeasureSpecMode.Exactly)); int internalHeight = b - t - barHeight; int containerHeight = ToolbarVisible ? internalHeight : b - t; containerHeight -= ContainerPadding; Element.ContainerArea = new Rectangle(0, 0, Context.FromPixels(r - l), Context.FromPixels(containerHeight)); // Potential for optimization here, the exact conditions by which you don't need to do this are complex // and the cost of doing when it's not needed is moderate to low since the layout will short circuit pretty fast Element.ForceLayout(); for (var i = 0; i < ChildCount; i++) { AView child = GetChildAt(i); bool isBar = JNIEnv.IsSameObject(child.Handle, bar.Handle); if (ToolbarVisible) { if (isBar) { bar.Layout(0, 0, r - l, barHeight); } else { child.Layout(0, barHeight + ContainerPadding, r, b); } } else { if (isBar) { bar.Layout(0, -1000, r, barHeight - 1000); } else { child.Layout(0, ContainerPadding, r, b); } } } }
protected override void OnLayout(bool changed, int l, int t, int r, int b) { TabLayout tabs = _tabLayout; FormsViewPager pager = _viewPager; Context context = Context; int width = r - l; int height = b - t; tabs.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.AtMost)); var tabsHeight = 0; if (tabs.Visibility != ViewStates.Gone) { //MinimumHeight is only available on API 16+ if ((int)Build.VERSION.SdkInt >= 16) { tabsHeight = Math.Min(height, Math.Max(tabs.MeasuredHeight, tabs.MinimumHeight)); } else { tabsHeight = Math.Min(height, tabs.MeasuredHeight); } } pager.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.AtMost), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.AtMost)); if (width > 0 && height > 0) { PageController.ContainerArea = new Rectangle(0, context.FromPixels(tabsHeight), context.FromPixels(width), context.FromPixels(height - tabsHeight)); for (var i = 0; i < PageController.InternalChildren.Count; i++) { var child = PageController.InternalChildren[i] as VisualElement; if (child == null) { continue; } IVisualElementRenderer renderer = Android.Platform.GetRenderer(child); var navigationRenderer = renderer as NavigationPageRenderer; if (navigationRenderer != null) { navigationRenderer.ContainerPadding = tabsHeight; } } pager.Layout(0, 0, width, b); // We need to measure again to ensure that the tabs show up tabs.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(tabsHeight, MeasureSpecMode.Exactly)); tabs.Layout(0, 0, width, tabsHeight); UpdateTabBarTranslation(pager.CurrentItem, 0); } base.OnLayout(changed, l, t, r, b); }
SizeRequest IVisualElementRenderer.GetDesiredSize(int widthConstraint, int heightConstraint) { if (_disposed) { return(new SizeRequest()); } if (_lastSizeRequest.HasValue) { // if we are measuring the same thing, no need to waste the time bool canRecycleLast = widthConstraint == _lastConstraintWidth && heightConstraint == _lastConstraintHeight; if (!canRecycleLast) { // if the last time we measured the returned size was all around smaller than the passed constraint // and the constraint is bigger than the last size request, we can assume the newly measured size request // will not change either. int lastConstraintWidthSize = MeasureSpecFactory.GetSize(_lastConstraintWidth); int lastConstraintHeightSize = MeasureSpecFactory.GetSize(_lastConstraintHeight); int currentConstraintWidthSize = MeasureSpecFactory.GetSize(widthConstraint); int currentConstraintHeightSize = MeasureSpecFactory.GetSize(heightConstraint); bool lastWasSmallerThanConstraints = _lastSizeRequest.Value.Request.Width < lastConstraintWidthSize && _lastSizeRequest.Value.Request.Height < lastConstraintHeightSize; bool currentConstraintsBiggerThanLastRequest = currentConstraintWidthSize >= _lastSizeRequest.Value.Request.Width && currentConstraintHeightSize >= _lastSizeRequest.Value.Request.Height; canRecycleLast = lastWasSmallerThanConstraints && currentConstraintsBiggerThanLastRequest; } if (canRecycleLast) { return(_lastSizeRequest.Value); } } //We need to clear the Hint or else it will interfere with the sizing of the Label var hint = Control.Hint; bool setHint = Control.LayoutParameters != null; if (!string.IsNullOrEmpty(hint) && setHint) { Control.Hint = string.Empty; } var hc = MeasureSpec.GetSize(heightConstraint); Measure(widthConstraint, heightConstraint); var result = new SizeRequest(new Size(MeasuredWidth, MeasuredHeight), new Size()); //Set Hint back after sizing if (setHint) { Control.Hint = hint; } result.Minimum = new Size(Math.Min(Context.ToPixels(10), result.Request.Width), result.Request.Height); // if the measure of the view has changed then trigger a request for layout // if the measure hasn't changed then force a layout of the label var measureIsChanged = !_lastSizeRequest.HasValue || (_lastSizeRequest.Value.Request.Height != MeasuredHeight || _lastSizeRequest.Value.Request.Width != MeasuredWidth); if (measureIsChanged) { this.MaybeRequestLayout(); } else { ForceLayout(); } _lastConstraintWidth = widthConstraint; _lastConstraintHeight = heightConstraint; _lastSizeRequest = result; return(result); }
protected override void OnLayout(bool changed, int l, int t, int r, int b) { FormsViewPager pager = _viewPager; Context context = Context; int width = r - l; int height = b - t; pager.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.AtMost), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.AtMost)); if (width > 0 && height > 0) { PageController.ContainerArea = new Rectangle(0, 0, context.FromPixels(width), context.FromPixels(height)); pager.Layout(0, 0, width, b); } base.OnLayout(changed, l, t, r, b); }
protected override void OnLayout(bool changed, int l, int t, int r, int b) { FormsViewPager pager = _viewPager; Context context = Context; var width = r - l; var height = b - t; if (IsBottomTabPlacement) { if (width <= 0 || height <= 0) { return; } _relativeLayout.Measure( MeasureSpec.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpec.MakeMeasureSpec(height, MeasureSpecMode.Exactly)); pager.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.AtMost), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.AtMost)); if (width > 0 && height > 0) { PageController.ContainerArea = new Rectangle(0, 0, context.FromPixels(width), context.FromPixels(height - _bottomNavigationView.MeasuredHeight)); SetNavigationRendererPadding(0, _bottomNavigationView.MeasuredHeight); pager.Layout(0, 0, width, b); // We need to measure again to ensure that the tabs show up _relativeLayout.Measure( MeasureSpec.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpec.MakeMeasureSpec(height, MeasureSpecMode.Exactly)); _relativeLayout.Layout(0, 0, _relativeLayout.MeasuredWidth, _relativeLayout.MeasuredHeight); } } else { TabLayout tabs = _tabLayout; tabs.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.AtMost)); var tabsHeight = 0; if (tabs.Visibility != ViewStates.Gone) { //MinimumHeight is only available on API 16+ if ((int)Build.VERSION.SdkInt >= 16) { tabsHeight = Math.Min(height, Math.Max(tabs.MeasuredHeight, tabs.MinimumHeight)); } else { tabsHeight = Math.Min(height, tabs.MeasuredHeight); } } pager.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.AtMost), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.AtMost)); if (width > 0 && height > 0) { PageController.ContainerArea = new Rectangle(0, context.FromPixels(tabsHeight), context.FromPixels(width), context.FromPixels(height - tabsHeight)); SetNavigationRendererPadding(tabsHeight, 0); pager.Layout(0, 0, width, b); // We need to measure again to ensure that the tabs show up tabs.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(tabsHeight, MeasureSpecMode.Exactly)); tabs.Layout(0, 0, width, tabsHeight); UpdateTabBarTranslation(pager.CurrentItem, 0); } } base.OnLayout(changed, l, t, r, b); }
protected override void OnLayout(bool changed, int l, int t, int r, int b) { int width = r - l; int height = b - t; var context = Context; _bottomBar.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.AtMost)); int tabsHeight = Math.Min(height, Math.Max(_bottomBar.MeasuredHeight, _bottomBar.MinimumHeight)); if (width > 0 && height > 0) { _pageController.ContainerArea = new Rectangle(0, 0, context.FromPixels(width), context.FromPixels(_frameLayout.MeasuredHeight)); ObservableCollection <Element> internalChildren = _pageController.InternalChildren; for (var i = 0; i < internalChildren.Count; i++) { var child = internalChildren [i] as VisualElement; if (child == null) { continue; } IVisualElementRenderer renderer = Platform.GetRenderer(child); var navigationRenderer = renderer as NavigationPageRenderer; if (navigationRenderer != null) { // navigationRenderer.ContainerPadding = tabsHeight; } } _bottomBar.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(tabsHeight, MeasureSpecMode.Exactly)); _bottomBar.Layout(0, 0, width, tabsHeight); } base.OnLayout(changed, l, t, r, b); }
protected override void OnLayout(bool changed, int l, int t, int r, int b) { var width = r - l; var height = b - t; var context = Context; bottomBar.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.AtMost)); var tabsHeight = Math.Min(height, Math.Max(bottomBar.MeasuredHeight, bottomBar.MinimumHeight)); if (width > 0 && height > 0) { pageController.ContainerArea = new Rectangle(0, 0, context.FromPixels(width), context.FromPixels(frameLayout.Height)); var internalChildren = pageController.InternalChildren; foreach (var el in internalChildren) { var child = el as VisualElement; if (child == null) { continue; } var renderer = Platform.GetRenderer(child); var navigationRenderer = renderer as NavigationPageRenderer; if (navigationRenderer != null) { // navigationRenderer.ContainerPadding = tabsHeight; } } bottomBar.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(tabsHeight, MeasureSpecMode.Exactly)); bottomBar.Layout(0, 0, width, tabsHeight); } base.OnLayout(changed, l, t, r, b); }
protected override void OnLayout(bool changed, int l, int t, int r, int b) { int width = r - l; _height = Math.Max(b - t, _height); var context = Context; _bottomBar.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(_height, MeasureSpecMode.AtMost)); int tabsHeight = Math.Min(_height, Math.Max(_bottomBar.MeasuredHeight, _bottomBar.MinimumHeight)); if (width > 0 && _height > 0) { _pageController.ContainerArea = new Rectangle(0, 0, context.FromPixels(width), context.FromPixels(_frameLayout.MeasuredHeight)); ObservableCollection <Element> internalChildren = _pageController.InternalChildren; for (int i = 0; i < internalChildren.Count; i++) { var bottomBarTab = _bottomBar.ItemContainer.GetChildAt(i); var tabIcon = bottomBarTab.FindViewById <AppCompatImageView>(BottomNavigationBar.Resource.Id.bb_bottom_bar_icon); var tabTitle = bottomBarTab.FindViewById <TextView>(BottomNavigationBar.Resource.Id.bb_bottom_bar_title); tabTitle.ScaleX = tabIcon.ScaleX = 1f; tabTitle.ScaleY = tabIcon.ScaleY = 1f; tabIcon.LayoutParameters = new FrameLayout.LayoutParams( bottomBarTab.Width / 2, bottomBarTab.Height / 2) { Gravity = GravityFlags.CenterHorizontal }; bottomBarTab.SetPadding(0, 0, 0, 0); tabIcon.SetPadding(0, 12, 0, 0); try { if (i == _tabPosition) { tabIcon.SetColorFilter(Element.IconActiveColor.ToAndroid(), PorterDuff.Mode.SrcIn); } } catch (Exception e) { Console.WriteLine($"--- Error: {e.StackTrace}"); } } _bottomBar.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(tabsHeight, MeasureSpecMode.Exactly)); _bottomBar.Layout(0, 0, width, tabsHeight); } base.OnLayout(changed, l, t, r, b); }
protected override void OnLayout(bool changed, int l, int t, int r, int b) { int width = r - l; int height = b - t; var context = Context; _bottomBar.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.AtMost)); int tabsHeight = Math.Min(height, Math.Max(_bottomBar.MeasuredHeight, _bottomBar.MinimumHeight)); if (width > 0 && height > 0) { _pageController.ContainerArea = new Rectangle(0, 0, context.FromPixels(width), context.FromPixels(height)); _bottomBar.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(tabsHeight, MeasureSpecMode.Exactly)); _bottomBar.Layout(0, 0, width, tabsHeight); } base.OnLayout(changed, l, t, r, b); }
void IPlatformLayout.OnLayout(bool changed, int l, int t, int r, int b) { if (changed) { LayoutRootPage((FormsAppCompatActivity)_context, Page, r - l, b - t); } Android.Platform.GetRenderer(Page).UpdateLayout(); for (var i = 0; i < _renderer.ChildCount; i++) { global::Android.Views.View child = _renderer.GetChildAt(i); if (child is ModalContainer) { child.Measure(MeasureSpecFactory.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(t - b, MeasureSpecMode.Exactly)); child.Layout(l, t, r, b); } } }
protected override void OnLayout(bool changed, int l, int t, int r, int b) { int width = r - l; int height = b - t; if (width > 0 && height > 0) { var context = Context; _rootLayout.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.AtMost), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.AtMost)); _rootLayout.Layout(0, 0, _rootLayout.MeasuredWidth, _rootLayout.MeasuredHeight); _bottomBar.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.AtMost)); int tabsHeight = BottomBarHeight.HasValue ? (int)Context.ToPixels(BottomBarHeight.Value) : Math.Min(height, Math.Max(_bottomBar.MeasuredHeight, _bottomBar.MinimumHeight)); _frameLayout.Layout(0, 0, width, height - tabsHeight); _pageController.ContainerArea = new Rectangle(0, 0, context.FromPixels(width), context.FromPixels(_frameLayout.Height)); _bottomBar.Layout(0, height - tabsHeight, width, height); } base.OnLayout(changed, l, t, r, b); }
protected override void OnLayout(bool changed, int l, int t, int r, int b) { var width = r - l; var height = b - t; var context = Context; _bottomBar.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.AtMost)); int tabsHeight = Math.Min(height, Math.Max(_bottomBar.MeasuredHeight, _bottomBar.MinimumHeight)); if (width > 0 && height > 0) { _pageController.ContainerArea = new Rectangle(0, 0, context.FromPixels(width), context.FromPixels(_frameLayout.MeasuredHeight)); ObservableCollection <Element> internalChildren = _pageController.InternalChildren; foreach (Element t1 in internalChildren) { if (!(t1 is VisualElement child)) { continue; } IVisualElementRenderer renderer = Platform.GetRenderer(child); if (renderer is NavigationPageRenderer navigationRenderer) { // TODO: } } _bottomBar.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(tabsHeight, MeasureSpecMode.Exactly)); _bottomBar.Layout(0, 0, width, tabsHeight); } base.OnLayout(changed, l, t, r, b); }
protected override void OnLayout(bool changed, int l, int t, int r, int b) { int num1 = r - l; int num2 = b - t; Context context = this.Context; this._bottomBar.Measure(MeasureSpecFactory.MakeMeasureSpec(num1, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(num2, MeasureSpecMode.AtMost)); int num3 = Math.Min(num2, Math.Max(this._bottomBar.MeasuredHeight, this._bottomBar.MinimumHeight)); if (num1 > 0 && num2 > 0) { this._pageController.ContainerArea = new Rectangle(0.0, 0.0, context.FromPixels((double)num1), context.FromPixels((double)this._frameLayout.MeasuredHeight)); ObservableCollection <Element> internalChildren = this._pageController.InternalChildren; for (int index = 0; index < internalChildren.Count; ++index) { VisualElement bindable = internalChildren[index] as VisualElement; if (bindable != null) { NavigationPageRenderer renderer = Xamarin.Forms.Platform.Android.Platform.GetRenderer(bindable) as NavigationPageRenderer; } } this._bottomBar.Measure(MeasureSpecFactory.MakeMeasureSpec(num1, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(num3, MeasureSpecMode.Exactly)); this._bottomBar.Layout(0, 0, num1, num3); } base.OnLayout(changed, l, t, r, b); }