static void RegisterHandler(Type target, Type handler, Type filter)
{
+ Profile.FrameBegin();
+
+ Profile.FramePartition(target.Name);
Type current = Registrar.Registered.GetHandlerType(target);
- if (current != filter)
- return;
- Registrar.Registered.Register(target, handler);
+ if (current == filter)
+ {
+ Profile.FramePartition("Register");
+ Registrar.Registered.Register(target, handler);
+ }
+
+ Profile.FrameEnd();
}
// This is currently being used by the previewer please do not change or remove this
if (!_renderersAdded)
{
+ Profile.FramePartition("RegisterHandlers");
RegisterHandlers();
_renderersAdded = true;
}
if (_application != null)
_application.PropertyChanged -= AppOnPropertyChanged;
+ Profile.FramePartition("SetAppIndexingProvider");
_application = application ?? throw new ArgumentNullException(nameof(application));
((IApplicationController)application).SetAppIndexingProvider(new AndroidAppIndexProvider(this));
+
+ Profile.FramePartition("SetCurrentApplication");
Xamarin.Forms.Application.SetCurrentApplication(application);
+ Profile.FramePartition("SetSoftInputMode");
if (Xamarin.Forms.Application.Current.OnThisPlatform().GetWindowSoftInputModeAdjust() != WindowSoftInputModeAdjust.Unspecified)
SetSoftInputMode();
+ Profile.FramePartition("CheckForAppLink");
CheckForAppLink(Intent);
application.PropertyChanged += AppOnPropertyChanged;
Bundle savedInstanceState,
ActivationFlags flags)
{
+ Profile.FrameBegin();
_activityCreated = true;
if (!AllowFragmentRestore)
{
savedInstanceState?.Remove("android:support:fragments");
}
+ Profile.FramePartition("Xamarin.Android.OnCreate");
base.OnCreate(savedInstanceState);
+ Profile.FramePartition("SetSupportActionBar");
AToolbar bar;
if (ToolbarResource != 0)
{
SetSupportActionBar(bar);
+ Profile.FramePartition("SetContentView");
_layout = new ARelativeLayout(BaseContext);
SetContentView(_layout);
+ Profile.FramePartition("OnStateChanged");
Xamarin.Forms.Application.ClearCurrent();
_previousState = _currentState;
OnStateChanged();
+ Profile.FramePartition("Forms.IsLollipopOrNewer");
if (Forms.IsLollipopOrNewer)
{
// Allow for the status bar color to be changed
if ((flags & ActivationFlags.DisableSetStatusBarColor) == 0)
{
+ Profile.FramePartition("Set DrawsSysBarBkgrnds");
Window.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);
}
}
if (Forms.IsLollipopOrNewer)
{
// Listen for the device going into power save mode so we can handle animations being disabled
+ Profile.FramePartition("Allocate PowerSaveModeReceiver");
_powerSaveModeBroadcastReceiver = new PowerSaveModeBroadcastReceiver();
}
+
+ Profile.FrameEnd();
}
protected override void OnDestroy()
protected override void OnResume()
{
+ Profile.FrameBegin();
+
// counterpart to OnPause
base.OnResume();
}
OnStateChanged();
+
+ Profile.FrameEnd();
}
protected override void OnStart()
{
+ Profile.FrameBegin();
+
+ Profile.FramePartition("Android OnStart");
base.OnStart();
_previousState = _currentState;
_currentState = AndroidApplicationLifecycleState.OnStart;
+ Profile.FramePartition("OnStateChanged");
OnStateChanged();
+
+ Profile.FrameEnd();
}
// Scenarios that stop and restart your app
// We want this to be updated when we have a new activity (e.g. on a configuration change)
// because Device.Info watches for orientation changes and we need a current activity for that
- Profile.FramePartition("new AndroidDeviceInfo(activity)");
+ Profile.FramePartition("create AndroidDeviceInfo");
Device.Info = new AndroidDeviceInfo(activity);
+
+ Profile.FramePartition("setFlags");
Device.SetFlags(s_flags);
Profile.FramePartition("AndroidTicker");
internal static IVisualElementRenderer CreateRenderer(VisualElement element, Context context)
{
- Profile.FrameBegin(nameof(CreateRenderer));
IVisualElementRenderer renderer = Registrar.Registered.GetHandlerForObject<IVisualElementRenderer>(element, context)
?? new DefaultRenderer(context);
- Profile.FramePartition(element.GetType().Name);
+
renderer.SetElement(element);
- Profile.FrameEnd();
return renderer;
}
using Android.Views;
using System;
using System.ComponentModel;
+using Xamarin.Forms.Internals;
using AView = Android.Views.View;
using LP = Android.Views.ViewGroup.LayoutParams;
protected virtual void AttachFlyout(IShellContext context, AView content)
{
+ Profile.FrameBegin();
+
_content = content;
+ Profile.FramePartition("Create ContentRenderer");
_flyoutContent = context.CreateShellFlyoutContentRenderer();
// Depending on what you read the right edge of the drawer should be Max(56dp, actionBarSize)
// this is about landscape devices and google does not perfectly follow these
// rules... so we'll kind of just... do our best.
+ Profile.FramePartition("Fudge Width");
var metrics = Context.Resources.DisplayMetrics;
var width = Math.Min(metrics.WidthPixels, metrics.HeightPixels);
_flyoutContent.AndroidView.LayoutParameters =
new LayoutParams(width, LP.MatchParent) { Gravity = (int)GravityFlags.Start };
+ Profile.FramePartition("AddView Content");
AddView(content);
+
+ Profile.FramePartition("AddView Flyout");
AddView(_flyoutContent.AndroidView);
+ Profile.FramePartition("Add DrawerListener");
AddDrawerListener(this);
+ Profile.FramePartition("Add BehaviorObserver");
((IShellController)context.Shell).AddFlyoutBehaviorObserver(this);
+
+ Profile.FrameEnd();
}
protected virtual void OnShellPropertyChanged(object sender, PropertyChangedEventArgs e)
using System.ComponentModel;
using AView = Android.Views.View;
using LP = Android.Views.ViewGroup.LayoutParams;
-using Android.Graphics;
+using Xamarin.Forms.Internals;
namespace Xamarin.Forms.Platform.Android
{
#endregion IShellFlyoutContentRenderer
- IShellContext _shellContext;
- bool _disposed;
- HeaderContainer _headerView;
- ViewGroup _rootView;
- Drawable _defaultBackgroundColor;
+ IShellContext _shellContext;
+ bool _disposed;
+ HeaderContainer _headerView;
+ ViewGroup _rootView;
+ Drawable _defaultBackgroundColor;
ImageView _bgImage;
- View _flyoutHeader;
- int _actionBarHeight;
+ View _flyoutHeader;
+ int _actionBarHeight;
- public ShellFlyoutTemplatedContentRenderer(IShellContext shellContext)
- {
- _shellContext = shellContext;
+ public ShellFlyoutTemplatedContentRenderer(IShellContext shellContext)
+ {
+ _shellContext = shellContext;
LoadView(shellContext);
}
protected virtual void LoadView(IShellContext shellContext)
{
+ Profile.FrameBegin();
+
var context = shellContext.AndroidContext;
// Android designer can't load fragments or resources from layouts
}
var coordinator = LayoutInflater.FromContext(context).Inflate(Resource.Layout.FlyoutContent, null);
+
+ Profile.FramePartition("Find Recycler");
var recycler = coordinator.FindViewById<RecyclerView>(Resource.Id.flyoutcontent_recycler);
+
+ Profile.FramePartition("Find AppBar");
var appBar = coordinator.FindViewById<AppBarLayout>(Resource.Id.flyoutcontent_appbar);
_rootView = coordinator as ViewGroup;
+ Profile.FramePartition("Add Listener");
appBar.AddOnOffsetChangedListener(this);
+ Profile.FramePartition("Add HeaderView");
_actionBarHeight = (int)context.ToPixels(56);
_flyoutHeader = ((IShellController)shellContext.Shell).FlyoutHeader;
};
appBar.AddView(_headerView);
+ Profile.FramePartition("Recycler.SetAdapter");
var adapter = new ShellFlyoutRecyclerAdapter(shellContext, OnElementSelected);
recycler.SetPadding(0, (int)context.ToPixels(20), 0, 0);
recycler.SetClipToPadding(false);
recycler.SetLayoutManager(new LinearLayoutManager(context, (int)Orientation.Vertical, false));
recycler.SetAdapter(adapter);
+ Profile.FramePartition("Initialize BgImage");
var metrics = context.Resources.DisplayMetrics;
var width = Math.Min(metrics.WidthPixels, metrics.HeightPixels);
LayoutParameters = new LP(coordinator.LayoutParameters)
};
+ Profile.FramePartition("UpdateFlyoutHeaderBehavior");
UpdateFlyoutHeaderBehavior();
- _shellContext.Shell.PropertyChanged += OnShellPropertyChanged;
+ _shellContext.Shell.PropertyChanged += OnShellPropertyChanged;
+
+ Profile.FramePartition("UpdateFlyoutBackground");
+ UpdateFlyoutBackground();
- UpdateFlyoutBackground();
- }
+ Profile.FrameEnd();
+ }
void OnFlyoutHeaderMeasureInvalidated(object sender, EventArgs e)
{
((IShellController)_shellContext.Shell).OnFlyoutItemSelected(element);
}
- protected virtual void OnShellPropertyChanged(object sender, PropertyChangedEventArgs e)
- {
+ protected virtual void OnShellPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
if (e.PropertyName == Shell.FlyoutHeaderBehaviorProperty.PropertyName)
UpdateFlyoutHeaderBehavior();
else if (e.IsOneOf(
Shell.FlyoutBackgroundImageProperty,
Shell.FlyoutBackgroundImageAspectProperty))
UpdateFlyoutBackground();
- }
+ }
protected virtual void UpdateFlyoutBackground()
{
_headerView.SetPadding(0, -verticalOffset, 0, 0);
}
- protected override void Dispose(bool disposing)
- {
- if (!_disposed)
- {
- if (disposing)
- {
- _shellContext.Shell.PropertyChanged -= OnShellPropertyChanged;
+ protected override void Dispose(bool disposing)
+ {
+ if (!_disposed)
+ {
+ if (disposing)
+ {
+ _shellContext.Shell.PropertyChanged -= OnShellPropertyChanged;
- if (_flyoutHeader != null)
- _flyoutHeader.MeasureInvalidated += OnFlyoutHeaderMeasureInvalidated;
+ if (_flyoutHeader != null)
+ _flyoutHeader.MeasureInvalidated += OnFlyoutHeaderMeasureInvalidated;
- _headerView.Dispose();
- _rootView.Dispose();
- _defaultBackgroundColor?.Dispose();
+ _headerView.Dispose();
+ _rootView.Dispose();
+ _defaultBackgroundColor?.Dispose();
_bgImage?.Dispose();
}
- _flyoutHeader = null;
- _defaultBackgroundColor = null;
+ _flyoutHeader = null;
+ _defaultBackgroundColor = null;
_bgImage = null;
_rootView = null;
- _headerView = null;
- _shellContext = null;
- _disposed = true;
- }
+ _headerView = null;
+ _shellContext = null;
+ _disposed = true;
+ }
base.Dispose(disposing);
}
using System;
using System.ComponentModel;
using System.Threading.Tasks;
+using Xamarin.Forms.Internals;
using AColor = Android.Graphics.Color;
using AView = Android.Views.View;
using LP = Android.Views.ViewGroup.LayoutParams;
event EventHandler<PropertyChangedEventArgs> _elementPropertyChanged;
public ShellRenderer(Context context)
- {
+ {
AndroidContext = context;
}
protected virtual void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
+ Profile.FrameBegin();
+
if (e.PropertyName == Shell.CurrentItemProperty.PropertyName)
SwitchFragment(FragmentManager, _frameLayout, Element.CurrentItem);
_elementPropertyChanged?.Invoke(sender, e);
+
+ Profile.FrameEnd();
}
protected virtual void OnElementSet(Shell shell)
{
+ Profile.FrameBegin();
+
+ Profile.FramePartition("Flyout");
_flyoutRenderer = CreateShellFlyoutRenderer();
+
+ Profile.FramePartition("Frame");
_frameLayout = new CustomFrameLayout(AndroidContext)
{
LayoutParameters = new LP(LP.MatchParent, LP.MatchParent),
Id = Platform.GenerateViewId(),
};
+
+ Profile.FramePartition("SetFitsSystemWindows");
_frameLayout.SetFitsSystemWindows(true);
+ Profile.FramePartition("AttachFlyout");
_flyoutRenderer.AttachFlyout(this, _frameLayout);
+ Profile.FramePartition("AddAppearanceObserver");
((IShellController)shell).AddAppearanceObserver(this, shell);
// Previewer Hack
- if(AndroidContext.GetActivity() != null)
+ Profile.FramePartition("Previewer Hack");
+ if (AndroidContext.GetActivity() != null)
SwitchFragment(FragmentManager, _frameLayout, shell.CurrentItem, false);
+
+ Profile.FrameEnd();
}
IShellItemRenderer _currentRenderer;
protected virtual void SwitchFragment(FragmentManager manager, AView targetView, ShellItem newItem, bool animate = true)
{
+ Profile.FrameBegin();
+
+ Profile.FramePartition("IsDesignerContext");
if (AndroidContext.IsDesignerContext())
return;
+ Profile.FramePartition("CreateShellItemRenderer");
var previousRenderer = _currentRenderer;
_currentRenderer = CreateShellItemRenderer(newItem);
_currentRenderer.ShellItem = newItem;
var fragment = _currentRenderer.Fragment;
+ Profile.FramePartition("Transaction");
FragmentTransaction transaction = manager.BeginTransaction();
if (animate)
transaction.Replace(_frameLayout.Id, fragment);
transaction.CommitAllowingStateLoss();
+ Profile.FramePartition("OnDestroyed");
void OnDestroyed (object sender, EventArgs args)
{
previousRenderer.Destroyed -= OnDestroyed;
if (previousRenderer != null)
previousRenderer.Destroyed += OnDestroyed;
+
+ Profile.FrameEnd();
}
void OnElementSizeChanged(object sender, EventArgs e)
{
+ Profile.FrameBegin();
+
+ Profile.FramePartition("ToPixels");
int width = (int)AndroidContext.ToPixels(Element.Width);
int height = (int)AndroidContext.ToPixels(Element.Height);
+
+ Profile.FramePartition("Measure");
_flyoutRenderer.AndroidView.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.Exactly),
MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.Exactly));
+
+ Profile.FramePartition("Layout");
_flyoutRenderer.AndroidView.Layout(0, 0, width, height);
+
+ Profile.FrameEnd();
}
void UpdateStatusBarColor(ShellAppearance appearance)
{
+ Profile.FrameBegin("UpdtStatBarClr");
+
var activity = AndroidContext.GetActivity();
var window = activity?.Window;
var decorView = window?.DecorView;
// All it really is is a drawable that only draws under the statusbar/bottom bar to make sure
// we dont draw over areas we dont need to. This has very limited benefits considering its
// only saving us a flat color fill BUT it helps people not freak out about overdraw.
+ AColor color;
if (appearance != null)
{
- var color = appearance.BackgroundColor.ToAndroid(Color.FromHex("#03A9F4"));
- decorView.SetBackground(new SplitDrawable(color, statusBarHeight, navigationBarHeight));
+ color = appearance.BackgroundColor.ToAndroid(Color.FromHex("#03A9F4"));
}
else
{
- var color = Color.FromHex("#03A9F4").ToAndroid();
- decorView.SetBackground(new SplitDrawable(color, statusBarHeight, navigationBarHeight));
+ color = Color.FromHex("#03A9F4").ToAndroid();
}
+
+ Profile.FramePartition("Create SplitDrawable");
+ var split = new SplitDrawable(color, statusBarHeight, navigationBarHeight);
+
+ Profile.FramePartition("SetBackground");
+ decorView.SetBackground(split);
}
+
+ Profile.FrameEnd();
}
class SplitDrawable : Drawable