public ShellToolbarTracker(IShellContext shellContext, AToolbar toolbar, DrawerLayout drawerLayout) { ShellContext = shellContext ?? throw new ArgumentNullException(nameof(shellContext)); _toolbar = toolbar ?? throw new ArgumentNullException(nameof(toolbar)); _drawerLayout = drawerLayout ?? throw new ArgumentNullException(nameof(drawerLayout)); _appBar = _toolbar.Parent.GetParentOfType <AppBarLayout>(); _globalLayoutListener = new GenericGlobalLayoutListener(() => UpdateNavBarHasShadow(Page)); _appBar.ViewTreeObserver.AddOnGlobalLayoutListener(_globalLayoutListener); _toolbar.SetNavigationOnClickListener(this); ((IShellController)ShellContext.Shell).AddFlyoutBehaviorObserver(this); ShellContext.Shell.Toolbar.PropertyChanged += OnToolbarPropertyChanged; }
public object WatchForChangesOnLayout(VisualElement visualElement, Action action) { if (action == null) { return(null); } var view = Platform.Android.Platform.GetRenderer(visualElement); var androidView = view?.View; if (androidView == null || !androidView.IsAlive()) { return(null); } ViewTreeObserver.IOnGlobalLayoutListener listener = null; listener = new GenericGlobalLayoutListener(() => { if (!androidView.IsAlive()) { action = null; androidView = null; try { _mainActivity?.Window?.DecorView?.RootView?.ViewTreeObserver?.RemoveOnGlobalLayoutListener(listener); } catch { // just in case something along the call path here is disposed of } return; } action?.Invoke(); }); androidView.ViewTreeObserver.AddOnGlobalLayoutListener(listener); return(listener); }
protected virtual void LoadView(IShellContext shellContext) { var context = shellContext.AndroidContext; var layoutInflator = shellContext.Shell.FindMauiContext().GetLayoutInflater(); var coordinator = (ViewGroup)layoutInflator.Inflate(Controls.Resource.Layout.flyoutcontent, null); _appBar = coordinator.FindViewById <AppBarLayout>(Controls.Resource.Id.flyoutcontent_appbar); (_appBar.LayoutParameters as CoordinatorLayout.LayoutParams) .Behavior = new AppBarLayout.Behavior(); _rootView = coordinator as ViewGroup; _appBar.AddOnOffsetChangedListener(this); _actionBarHeight = context.GetActionBarHeight(); UpdateFlyoutHeader(); var metrics = context.Resources.DisplayMetrics; var width = Math.Min(metrics.WidthPixels, metrics.HeightPixels); width -= _actionBarHeight; coordinator.LayoutParameters = new LP(width, LP.MatchParent); _bgImage = new ImageView(context) { LayoutParameters = new LP(coordinator.LayoutParameters) }; UpdateFlyoutHeaderBehavior(); _shellContext.Shell.PropertyChanged += OnShellPropertyChanged; UpdateFlyoutBackground(); UpdateVerticalScrollMode(); UpdateFlyoutFooter(); if (FlyoutView.FlyoutBehavior == FlyoutBehavior.Locked) { OnFlyoutViewLayoutChanging(); } if (View is ShellFlyoutLayout sfl) { // The purpose of this code is to load the flyout content after // the details content is visible. // Loading the Recycler View the first time is expensive // so we want to delay loading to the latest possible point in time so // it doesn't delay initial startup. GenericGlobalLayoutListener ggll = null; ggll = new GenericGlobalLayoutListener(InitialLoad); sfl.ViewTreeObserver.AddOnGlobalLayoutListener(ggll); void InitialLoad() { OnFlyoutViewLayoutChanging(); if (_flyoutContentView == null || ggll == null) { return; } var listener = ggll; ggll = null; // Once initial load has finished let's just attach to Layout Changing sfl.ViewTreeObserver.RemoveOnGlobalLayoutListener(listener); sfl.LayoutChanging += OnFlyoutViewLayoutChanging; } } }