Quantcast
Channel: Xamarin.Forms — Xamarin Community Forums
Viewing all articles
Browse latest Browse all 75885

CarouselPage with ContentPages in ItemTemplate doesn't support UseSafeArea

$
0
0

I have a CarouselPage in my app where the items are visualized as ContentPages. I noticed that with this setup UseSafeArea doesn't work. Each ContentPage always covers the full display area on a device that should have insets. I tried the following to solve this:

First I tried to force the setting of safe area myself in OnAppearing(), with:

if (Device.RuntimePlatform == Device.iOS)
{
  On<Xamarin.Forms.PlatformConfiguration.iOS>().SetUseSafeArea(true);
}

That doesn't work.

I then checked what the framework actually reports as insets with:

if (Device.RuntimePlatform == Device.iOS)
{
  On<Xamarin.Forms.PlatformConfiguration.iOS>().SetUseSafeArea(true);
  var safeInsets = On<Xamarin.Forms.PlatformConfiguration.iOS>().SafeAreaInsets();
  this.Padding = safeInsets;
}

On devices that need insets (iPhone XR, iPad Pro, etc.) the insets are all 0.

I then tried to define UseSafeArea in the ContentPage's ItemTemplate, like so:

<CarouselPage.ItemTemplate>
    <DataTemplate>
      <ContentPage ios:UseSafeArea="True">
         ...
      </ContentPage>
    </DataTemplate>
</CarouselPage.ItemTemplate>

That didn't work either.

I finally managed to get it working by forcing the insets in code behind of my CarouselPage with an own implementation of a dependency service for safe area insets and setting the ContentPage's padding each time the current page in CarouselPage changes. It look as follows:

    public partial class ArticleXFCarouselPage : CarouselPage
    {
        ArticleCarouselViewModel _carouselVM;
        bool _isInitializing;

        public ArticleXFCarouselPage (ArticleCarouselViewModel vm)
        {
            _carouselVM = vm;
            this.BindingContext = vm;
            _isInitializing = true;
            ItemsSource = _carouselVM.Items;
            CurrentPage = Children[_carouselVM.CurrentItemIdx];
            InitializeComponent();
            _isInitializing = false;
        }

        double _width;
        double _height;
        Thickness _contentPagePadding = new Thickness();

        protected override void OnSizeAllocated(double width, double height)
        {
            base.OnSizeAllocated(width, height);
            if (Equals(_width, width) &&
                Equals(_height, height))
                return;

            var oldWidth = _width;
            _width = width;
            _height = height;

            // Has the device been rotated ?
            if (width != -1 && !Equals(width, oldWidth))
            {
                SetSafeArea(width < height ? PageOrientation.Vertical : PageOrientation.Horizontal);
            }
        }

        void SetSafeArea(PageOrientation orientation)
        {
            if (Device.RuntimePlatform == Device.iOS)
            {
                _contentPagePadding = DependencyService.Get<IPlatformService>().GetSafeAreaInset();
                if (orientation == PageOrientation.Vertical)
                {
                    _contentPagePadding.Top = 0;
                }
                CurrentPage.Padding = _contentPagePadding;
            }
        }

        protected override void OnCurrentPageChanged()
        {
            base.OnCurrentPageChanged();
            if (!_isInitializing)
            {
                CurrentPage.Padding = _contentPagePadding;
                // Tell viewmodel to load additional articles if any
                Device.BeginInvokeOnMainThread(async () =>
                {
                    var idx = Children.IndexOf(CurrentPage);
                    await _carouselVM.OnArticleBecomesVisibleAsync(idx);
                });
            }
        }
    }

The dependency service for iOS looks as follows:

    public class PlatformService : IPlatformService
    {
        public PlatformService()
        { }

        public Thickness GetSafeAreaInset()
        {
            var inset = new Thickness();
            if (UIApplication.SharedApplication.KeyWindow != null)
            {
                if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
                {
                    var safeAreaInsets = UIApplication.SharedApplication.KeyWindow.SafeAreaInsets;
                    inset.Top = safeAreaInsets.Top;
                    inset.Bottom = safeAreaInsets.Bottom;
                    inset.Left = safeAreaInsets.Left;
                    inset.Right = safeAreaInsets.Right;
                }
            }
            return inset;
        }
    }

That of course leaves me with the question: Did I overlooked something? Is there indeed an error in CarouselPage and if so are there plans to solve this?


Viewing all articles
Browse latest Browse all 75885

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>