summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.Android/AppCompat
diff options
context:
space:
mode:
authorE.Z. Hart <hartez@users.noreply.github.com>2016-05-10 11:15:47 -0600
committerJason Smith <jason.smith@xamarin.com>2016-05-10 10:15:47 -0700
commit5acafedb8e3e2ace8e66f9ff20655d5d96e8ed97 (patch)
treec816ea1127275953bcc458315e1714fd0cb17003 /Xamarin.Forms.Platform.Android/AppCompat
parentd4a5bb8dfcb39949451fe0e5390a684f116cc288 (diff)
downloadxamarin-forms-5acafedb8e3e2ace8e66f9ff20655d5d96e8ed97.tar.gz
xamarin-forms-5acafedb8e3e2ace8e66f9ff20655d5d96e8ed97.tar.bz2
xamarin-forms-5acafedb8e3e2ace8e66f9ff20655d5d96e8ed97.zip
[Android] Isolate fragment management for children of MasterDetailPage (#136)
* Isolate fragment management for children of MasterDetailPage in AppCompat If a MasterDetailPage hosts NavigationPages or TabbedPages in either the Master or Detail sections, wrap those pages in their own Fragment (and ChildFragmentManager) to isolate their Fragment management operations and avoid recursive entry into the executePendingTransactions method Also fix a disposal bug in the custom MDP renderer in Control Gallery * Remove MDP Split setting that breaks test on iPad
Diffstat (limited to 'Xamarin.Forms.Platform.Android/AppCompat')
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/FragmentContainer.cs9
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/MasterDetailContainer.cs92
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/MasterDetailPageRenderer.cs21
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/NavigationPageRenderer.cs2
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/TabbedPageRenderer.cs4
5 files changed, 121 insertions, 7 deletions
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/FragmentContainer.cs b/Xamarin.Forms.Platform.Android/AppCompat/FragmentContainer.cs
index 9ae56aba..cc35b1a3 100644
--- a/Xamarin.Forms.Platform.Android/AppCompat/FragmentContainer.cs
+++ b/Xamarin.Forms.Platform.Android/AppCompat/FragmentContainer.cs
@@ -11,6 +11,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
{
readonly WeakReference _pageReference;
+ Action<PageContainer> _onCreateCallback;
bool? _isVisible;
PageContainer _pageContainer;
IVisualElementRenderer _visualElementRenderer;
@@ -51,6 +52,11 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
return new FragmentContainer(page) { Arguments = new Bundle() };
}
+ public void SetOnCreateCallback(Action<PageContainer> callback)
+ {
+ _onCreateCallback = callback;
+ }
+
public override AView OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
if (Page != null)
@@ -59,6 +65,9 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
Android.Platform.SetRenderer(Page, _visualElementRenderer);
_pageContainer = new PageContainer(Forms.Context, _visualElementRenderer, true);
+
+ _onCreateCallback?.Invoke(_pageContainer);
+
return _pageContainer;
}
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/MasterDetailContainer.cs b/Xamarin.Forms.Platform.Android/AppCompat/MasterDetailContainer.cs
new file mode 100644
index 00000000..de167906
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AppCompat/MasterDetailContainer.cs
@@ -0,0 +1,92 @@
+using Android.App;
+using Android.Content;
+using Fragment = Android.Support.V4.App.Fragment;
+using FragmentManager = Android.Support.V4.App.FragmentManager;
+using FragmentTransaction = Android.Support.V4.App.FragmentTransaction;
+
+namespace Xamarin.Forms.Platform.Android.AppCompat
+{
+ internal class MasterDetailContainer : Xamarin.Forms.Platform.Android.MasterDetailContainer, IManageFragments
+ {
+ PageContainer _pageContainer;
+ FragmentManager _fragmentManager;
+ readonly bool _isMaster;
+ readonly MasterDetailPage _parent;
+
+ public MasterDetailContainer(MasterDetailPage parent, bool isMaster, Context context) : base(parent, isMaster, context)
+ {
+ Id = FormsAppCompatActivity.GetUniqueId();
+ _parent = parent;
+ _isMaster = isMaster;
+ }
+
+ FragmentManager FragmentManager => _fragmentManager ?? (_fragmentManager = ((FormsAppCompatActivity)Context).SupportFragmentManager);
+
+ protected override void OnLayout(bool changed, int l, int t, int r, int b)
+ {
+ base.OnLayout(changed, l, t, r, b);
+
+ // If we're using a PageContainer (i.e., we've wrapped our contents in a Fragment),
+ // Make sure that it gets laid out
+ if (_pageContainer != null)
+ {
+ if (_isMaster)
+ {
+ var width = (int)Context.ToPixels(_parent.MasterBounds.Width);
+ // When the base class computes the size of the Master container, it starts at the top of the
+ // screen and adds padding (_parent.MasterBounds.Top) to leave room for the status bar
+ // When this container is laid out, it's already starting from the adjusted y value of the parent,
+ // so we subtract _parent.MasterBounds.Top from our starting point (to get 0) and add it to the
+ // bottom (so the master page stretches to the bottom of the screen)
+ var height = (int)Context.ToPixels(_parent.MasterBounds.Height + _parent.MasterBounds.Top);
+ _pageContainer.Layout(0, 0, width, height);
+ }
+ else
+ {
+ _pageContainer.Layout(l, t, r, b);
+ }
+
+ _pageContainer.Child.UpdateLayout();
+ }
+ }
+
+ protected override void AddChildView(VisualElement childView)
+ {
+ _pageContainer = null;
+
+ Page page = childView as NavigationPage ?? (Page)(childView as TabbedPage);
+
+ if (page == null)
+ {
+ // Not a NavigationPage or TabbedPage? Just do the normal thing
+ base.AddChildView(childView);
+ }
+ else
+ {
+ // The renderers for NavigationPage and TabbedPage both host fragments, so they need to be wrapped in a
+ // FragmentContainer in order to get isolated fragment management
+
+ Fragment fragment = FragmentContainer.CreateInstance(page);
+
+ var fc = fragment as FragmentContainer;
+ fc?.SetOnCreateCallback(pc =>
+ {
+ _pageContainer = pc;
+ SetDefaultBackgroundColor(pc.Child);
+ });
+
+ FragmentTransaction transaction = FragmentManager.BeginTransaction();
+ transaction.DisallowAddToBackStack();
+ transaction.Add(Id, fragment);
+ transaction.SetTransition((int)FragmentTransit.FragmentOpen);
+ transaction.Commit();
+ }
+ }
+
+ public void SetFragmentManager(FragmentManager fragmentManager)
+ {
+ if (_fragmentManager == null)
+ _fragmentManager = fragmentManager;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/MasterDetailPageRenderer.cs b/Xamarin.Forms.Platform.Android/AppCompat/MasterDetailPageRenderer.cs
index a180c135..0173f485 100644
--- a/Xamarin.Forms.Platform.Android/AppCompat/MasterDetailPageRenderer.cs
+++ b/Xamarin.Forms.Platform.Android/AppCompat/MasterDetailPageRenderer.cs
@@ -3,10 +3,11 @@ using System.ComponentModel;
using System.Threading.Tasks;
using Android.Support.V4.Widget;
using Android.Views;
+using Android.Support.V4.App;
namespace Xamarin.Forms.Platform.Android.AppCompat
{
- public class MasterDetailPageRenderer : DrawerLayout, IVisualElementRenderer, DrawerLayout.IDrawerListener
+ public class MasterDetailPageRenderer : DrawerLayout, IVisualElementRenderer, DrawerLayout.IDrawerListener, IManageFragments
{
#region Statics
@@ -17,12 +18,12 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
int _currentLockMode = -1;
MasterDetailContainer _detailLayout;
-
+ MasterDetailContainer _masterLayout;
bool _disposed;
bool _isPresentingFromCore;
- MasterDetailContainer _masterLayout;
bool _presented;
VisualElementTracker _tracker;
+ FragmentManager _fragmentManager;
public MasterDetailPageRenderer() : base(Forms.Context)
{
@@ -68,6 +69,12 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
UpdateIsPresented();
}
+ void IManageFragments.SetFragmentManager(FragmentManager fragmentManager)
+ {
+ if (_fragmentManager == null)
+ _fragmentManager = fragmentManager;
+ }
+
VisualElement IVisualElementRenderer.Element => Element;
event EventHandler<VisualElementChangedEventArgs> IVisualElementRenderer.ElementChanged
@@ -114,6 +121,12 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
LayoutParameters = new LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent) { Gravity = (int)GravityFlags.Start }
};
+ if (_fragmentManager != null)
+ {
+ _detailLayout.SetFragmentManager(_fragmentManager);
+ _masterLayout.SetFragmentManager(_fragmentManager);
+ }
+
AddView(_detailLayout);
AddView(_masterLayout);
@@ -329,7 +342,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
void UpdateMaster()
{
- MasterDetailContainer masterContainer = _masterLayout;
+ Android.MasterDetailContainer masterContainer = _masterLayout;
if (masterContainer == null)
return;
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/NavigationPageRenderer.cs b/Xamarin.Forms.Platform.Android/AppCompat/NavigationPageRenderer.cs
index 6a735fe2..1132c8fa 100644
--- a/Xamarin.Forms.Platform.Android/AppCompat/NavigationPageRenderer.cs
+++ b/Xamarin.Forms.Platform.Android/AppCompat/NavigationPageRenderer.cs
@@ -85,7 +85,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
}
}
- public void SetFragmentManager(FragmentManager childFragmentManager)
+ void IManageFragments.SetFragmentManager(FragmentManager childFragmentManager)
{
if (_fragmentManager == null)
_fragmentManager = childFragmentManager;
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/TabbedPageRenderer.cs b/Xamarin.Forms.Platform.Android/AppCompat/TabbedPageRenderer.cs
index ade398a1..8af824ce 100644
--- a/Xamarin.Forms.Platform.Android/AppCompat/TabbedPageRenderer.cs
+++ b/Xamarin.Forms.Platform.Android/AppCompat/TabbedPageRenderer.cs
@@ -28,7 +28,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
AutoPackage = false;
}
- public FragmentManager FragmentManager => _fragmentManager ?? (_fragmentManager = ((FormsAppCompatActivity)Context).SupportFragmentManager);
+ FragmentManager FragmentManager => _fragmentManager ?? (_fragmentManager = ((FormsAppCompatActivity)Context).SupportFragmentManager);
internal bool UseAnimations
{
@@ -43,7 +43,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
}
}
- public void SetFragmentManager(FragmentManager childFragmentManager)
+ void IManageFragments.SetFragmentManager(FragmentManager childFragmentManager)
{
if (_fragmentManager == null)
_fragmentManager = childFragmentManager;