summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.Android/Renderers/CarouselPageAdapter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Platform.Android/Renderers/CarouselPageAdapter.cs')
-rw-r--r--Xamarin.Forms.Platform.Android/Renderers/CarouselPageAdapter.cs155
1 files changed, 155 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.Android/Renderers/CarouselPageAdapter.cs b/Xamarin.Forms.Platform.Android/Renderers/CarouselPageAdapter.cs
new file mode 100644
index 00000000..345501d5
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/Renderers/CarouselPageAdapter.cs
@@ -0,0 +1,155 @@
+using System;
+using System.Collections.Specialized;
+using System.Linq;
+using Android.Content;
+using Android.Support.V4.View;
+using Android.Views;
+using Object = Java.Lang.Object;
+
+namespace Xamarin.Forms.Platform.Android
+{
+ internal class CarouselPageAdapter : PagerAdapter, ViewPager.IOnPageChangeListener
+ {
+ readonly Context _context;
+ readonly ViewPager _pager;
+ bool _ignoreAndroidSelection;
+ CarouselPage _page;
+
+ public CarouselPageAdapter(ViewPager pager, CarouselPage page, Context context)
+ {
+ _pager = pager;
+ _page = page;
+ _context = context;
+
+ page.PagesChanged += OnPagesChanged;
+ }
+
+ public override int Count
+ {
+ get { return _page.Children.Count(); }
+ }
+
+ public void OnPageScrolled(int position, float positionOffset, int positionOffsetPixels)
+ {
+ }
+
+ public void OnPageScrollStateChanged(int state)
+ {
+ }
+
+ public void OnPageSelected(int position)
+ {
+ if (_ignoreAndroidSelection)
+ return;
+
+ int currentItem = _pager.CurrentItem;
+ _page.CurrentPage = currentItem >= 0 && currentItem < _page.LogicalChildren.Count ? _page.LogicalChildren[currentItem] as ContentPage : null;
+ }
+
+ public override void DestroyItem(ViewGroup p0, int p1, Object p2)
+ {
+ var holder = (ObjectJavaBox<Tuple<ViewGroup, Page, int>>)p2;
+ Page destroyedPage = holder.Instance.Item2;
+
+ IVisualElementRenderer renderer = Platform.GetRenderer(destroyedPage);
+ renderer.ViewGroup.RemoveFromParent();
+ holder.Instance.Item1.RemoveFromParent();
+ }
+
+ public override int GetItemPosition(Object item)
+ {
+ // The int is the current index.
+ var holder = (ObjectJavaBox<Tuple<ViewGroup, Page, int>>)item;
+ Element parent = holder.Instance.Item2.RealParent;
+ if (parent == null)
+ return PositionNone;
+
+ // Unfortunately we can't just call CarouselPage.GetIndex, because we need to know
+ // if the item has been removed. We could update MultiPage<T> to set removed items' index
+ // to -1 to support this if it ever becomes an issue.
+ int index = ((CarouselPage)parent).Children.IndexOf(holder.Instance.Item2);
+ if (index == -1)
+ return PositionNone;
+
+ if (index != holder.Instance.Item3)
+ {
+ holder.Instance = new Tuple<ViewGroup, Page, int>(holder.Instance.Item1, holder.Instance.Item2, index);
+ return index;
+ }
+
+ return PositionUnchanged;
+ }
+
+ public override Object InstantiateItem(ViewGroup container, int position)
+ {
+ ContentPage child = _page.Children.ElementAt(position);
+ if (Platform.GetRenderer(child) == null)
+ Platform.SetRenderer(child, Platform.CreateRenderer(child));
+
+ IVisualElementRenderer renderer = Platform.GetRenderer(child);
+ renderer.ViewGroup.RemoveFromParent();
+
+ ViewGroup frame = new PageContainer(_context, renderer);
+
+ container.AddView(frame);
+
+ return new ObjectJavaBox<Tuple<ViewGroup, Page, int>>(new Tuple<ViewGroup, Page, int>(frame, child, position));
+ }
+
+ public override bool IsViewFromObject(global::Android.Views.View p0, Object p1)
+ {
+ var holder = (ObjectJavaBox<Tuple<ViewGroup, Page, int>>)p1;
+ ViewGroup frame = holder.Instance.Item1;
+ return p0 == frame;
+ }
+
+ public void UpdateCurrentItem()
+ {
+ if (_page.CurrentPage == null)
+ throw new InvalidOperationException("CarouselPage has no children.");
+
+ int index = CarouselPage.GetIndex(_page.CurrentPage);
+ if (index >= 0 && index < _page.Children.Count)
+ _pager.CurrentItem = index;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && _page != null)
+ {
+ foreach (Element element in _page.LogicalChildren)
+ {
+ var childPage = element as VisualElement;
+
+ if (childPage == null)
+ continue;
+
+ IVisualElementRenderer childPageRenderer = Platform.GetRenderer(childPage);
+ if (childPageRenderer != null)
+ {
+ childPageRenderer.ViewGroup.RemoveFromParent();
+ childPageRenderer.Dispose();
+ Platform.SetRenderer(childPage, null);
+ }
+ }
+ _page.PagesChanged -= OnPagesChanged;
+ _page = null;
+ }
+ base.Dispose(disposing);
+ }
+
+ void OnPagesChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ _ignoreAndroidSelection = true;
+
+ NotifyDataSetChanged();
+
+ _ignoreAndroidSelection = false;
+
+ if (_page.CurrentPage == null)
+ return;
+
+ UpdateCurrentItem();
+ }
+ }
+} \ No newline at end of file