Carousel View Page Indicators

I previously blogged about the CarouselView and how it is taking over the CarouselPage in 2.2.0. One of the first things that I needed from the new Carousel View were some page indicators. While there is a feature request for this, it will probably be some time before its implemented. As such I thought I would implement my own.

PageIndicators

Carousel View Indicator

First I created a view indicator control, that is just a grid and it hosts an image per indicator. At the moment it only allows an image to be an indicator, however I think some good enhancements would be to make the page indicator a data template that you could add anything to.

Binding Carousel View Indicator

Now we just need to bind the Indicator to a common Position and ItemsSource. This allows the CarouselView to update the Position in the indicator and we need the ItemsSource to get the count of the items.

If you want the images I used here they are

https://xamarinhelp.com/wp-content/uploads/2016/04/selected_circle.png

https://xamarinhelp.com/wp-content/uploads/2016/04/unselected_circle.png

Summary

If Xamarin implement this feature in the future it will most likely be a lot easier to use since it can be tied up to the internal events. In the meantime enjoy this extension.

Example Project: CarouselView Sample

 


XAMARIN WEEKLY NEWSLETTER

Subscribe to a hand-picked round up of the best Xamarin development links every week. Published every Friday. Free.

Signup to Weekly Xamarin

* I do not maintain or run this newsletter, but I do recommend it.

38 Comments

    1. Adam Pedley

      Position is just the position (zero based index) in the list of pages in the CarouselView. When you look at the Binding of the Position in the last bit of code, it is just wiring up the Bindable Property Position from the CarouselView to the Indicator, so that changes in the CarouselView are reflected in the Indicator and push back if they click the indicator.

      1. John Williams

        Can you post some example code of this please.

        Also how did you hide the scrollbar in the carousel view?

        1. Adam Pedley

          Hi John

          What example code did you want me to produce, or what are you trying to achieve?

          The scrollbars should be invisible if the content doesn’t go beyond the visible area of the screen, or are you seeing them when there is no content bigger than the screen? If so, what platform(s) are you seeing this on?

      2. Harry Dong

        Hi Adam,

        I think John is seeing what looks to be a native page indicator in IOS. It looks like an opaque bar sitting below the content. That indicator is showing along with the indicator that you built, in the IOS platform. Any chance, that you know how to get rid of it?

  1. Harry Dong

    We solved it using a custom renderer for IOS

    public class CustomCarouselView : CarouselViewRenderer
    {
    protected override void OnElementChanged(ElementChangedEventArgs e)
    {
    base.OnElementChanged(e);
    //Removes the Native IOS page indicator
    Control.ShowsHorizontalScrollIndicator = false;

    }
    }

      1. fairouz

        is this working wel on ios plateform? i tasted with windows it’s okay but in ios it’s just showing me the indicators without the carrousel .
        So after reading the comment of @Harry Dong , me too i tried to follow and to add the renderer on ios and the OnElementChanged not accepted yet.
        any solution for that please ?

    1. jula

      hello did you add this renderer in the ios project ? because void OnElementChanged(ElementChangedEventArgs e) was not accepted
      thks

  2. Alexandre

    Thanks Adam for this post,

    I’m trying to implement you indicator solution, but as I’m new to this whole binding thing, the indicator displays with the right number of circles (meaning that the item sources binding is working) but the position doesn’t as the indicator selected circle remains the first one while swiping.

    Here is my code :

    The view I use:
    public class ActualityView
    {
    public List Actualities { set; get; }
    public int Position { set; get;}

    public ActualityView()
    {

    //Set up the carousel view
    Actualities = new List
    {
    new Actuality
    {
    title = “Title”,
    content = “Content”,
    description = “”,
    imageBackground = “imageparis.png”,
    link = “http://wolrdsummit/fr-fr/”
    }
    };
    }

    In the page class:
    public HomePage()
    {
    //Init component
    InitializeComponent();

    //Display actualities
    BindingContext = new ActualityView();
    }

    And xaml :

    Thanks for your help !

    1. Adam Pedley

      I cant see your xaml as my commenting system doesnt really allow it. Can you post your question on stackoverflow, then you can tweet me with a link to your question.

      1. Alexandre

        Maybe that’s not need: my issue is that I don’t know how to create a “bindable Position integer”.

        I’ve been searching for example, but I see that for Integers, I need to create a converter or something. Would you have any resources on this topic ?

        Thanks a lot for your help !

        1. Adam Pedley

          Just add this to your ViewModel to create a bindable Position Property.

          public static readonly BindableProperty PositionProperty = BindableProperty.Create(nameof(Position), typeof(int), typeof(MyViewModel));

          public int Position
          {
          get { return (int)this.GetValue(PositionProperty); }
          set { this.SetValue(PositionProperty, value); }
          }

            1. Jose

              Hey! Can you please tell me where exactly did you add those lines ? I have the same problem the number of dots is the same as the number of images, but the indicator doesn’t change when I swipe over an image..

          1. Jose

            Hey Adam!, Those lines you mention are already located in CarouselIndicators.cs right ?, is it necessary to add them on my viewmodel too ? I have exactly the same problem as Alexandre. It´s like if the indicators weren’t detecting the image swiping..

    1. Adam Pedley

      You need to set your DataSource default value to something as if its null and the page is bound it will result in this error. I personally think this is a bug and the control should just display nothing if the list is null.

  3. Guilherme Bezerra

    Hello, I’m new with development in xamarin.forms, I’m a bit confused by the example, as it’s missing some classes.

    Would you have a sample project on GitHub?

    Thank you for bringing this solution, it was very important!

  4. Martin Rhodes

    Awesome – very easy to modify for use with the Iconize Controls Plugin to use icons for your indicators rather than images!

    Thanks for sharing Adam

  5. Chandu

    First of all its a great article and saved my time a lot. I have successfully Implemented in my project but I have around 100-200 carousel items in. when I swipe through items the selected indicator is moved out of screen. is there anyway that you could show how to make it visible?

    Thanks in advance

    1. Adam Pedley

      For 200 items, indicators like above might be of little use.

      You might want to change it to a scrollbar of some kind, that way it shows progress through the list and makes it easier for them to move back and forth.

  6. Santosh

    How can i have carousel views of different controls ?
    In your exam, you are binding to same datatype.

  7. Mel De Soysa

    Hi Adam,

    I’ve implemented the indicators and they are always showing below the images in my carousel. I would like them to show on the image (just on the bottom) like in most apps.

    The carousel view and the indicators are in a stacklayout as in your example xaml.

    1. Adam Pedley

      In this case create a Grid, with 2 rows, the image to overlap and the indicators at the bottom.

      <Grid>
      <Grid.RowDefinitions>
      <RowDefinition Height=”*” />
      <RowDefinition Height=”Auto” />
      </Grid.RowDefinitions>

      <CarouselView Grid.RowSpan=”2″ />

      <control:CarouselIndicators Grid.Row=”1″ />

      </Grid>

  8. Robert McLeish

    Hi Adam, i am not sure how to ensure that the carousel indicators item source changes when the associated carousel view’s item source changes. My code allows the user to add or remove items from the list (an observable collection) via an edit screen. When i return back to the screen with the carousel view on it, the carousel view knows about the update to the items source collection but the carousel indicators does not.
    Any ideas on how i inform the carousel indicators about the change in the collection?

    1. Adam Pedley

      The indicators only update when the whole list is changed, hence why it’s not picking up the new or removed items.

      Off the top of my head, you would have to look at the ItemChanged method, convert the list to an observable, then add event handlers to the collection. When an item is added or remove, you would want to call Init. Probably with the same position it’s already in, taking into account the added or removed items.

  9. Frein

    Hi Adam, I have Visual Studio 2013. The problem it’s with this Visual Studio can’t use nameof. Is there another way without using another Visual Studio version?

    Thanks Adam!

    1. Adam Pedley

      Wow, VS2013, blast from the past 🙂

      nameof just takes what is inside of it and turns it into a string.

      So nameof(SomeClass) can just be converted to “SomeClass”

      It’s just turning the class name inside to a string.