- Sabtu, 18 November 2017

Tutorial Xamarin Form : Membuat Carousel View Indocator dengan Image




Hello, sesuai dengan permintaan dari sebuah komentar, dimana dia sedang membutuhkan tutorial membuat CarouselView dengan Image indicator. Nah pada kesempatan kali ini saya akan membuatnya. Tentunya ini juga hasil kolaborasi dari beberapa tutorial yang saya temukan di github hehe.

Ada beberapa langkah untuk membuat Carousel View pada Xamarin Forms dengan Indikator. Namun anda wajib memiliki beberapa file sebagai berikut :

  1. Image selected_indikator.png dan unselected_indicator.png
  2. Image untuk carousel view saya bjat 4 image jpg.
  3. Packages Xamarin.Forms CarouselView yang harus terinstal di Forms dan Android / Ios kamu ya.
Oh iya untuk imagenya boleh kamu taruh di folder drawable nya xamarin android kamu ya. Untuk gambarnya bisa di download disini ya .

Okeh, selanjutnya ikuti langkah-langkah berikut :

Langkah 1 :
Buat sebuah Project baru dengan nama LatCarousel dengan xamarin forms kamu, pilih Portable ya. 

Langkah 2 :
Instal Packages dengan nama Xamarin.Forms.CarouselView di Forms dan xamarin android kamu.

Langkah 3:
Buat sebuah file baru Content Page Xaml dengan nama MainPage. Disana anda akan mendapatkan file MainPage.xaml.cs dan MainPage.xaml.

Langkah 4:
Buka App.xaml.cs kemudian arahkan navigasi halaman pertama ke MainPage.xaml dengan code sebagai berikut :


using Xamarin.Forms;

namespace LatCarousel
{
 public partial class App : Application
 {
  public App()
  {
   InitializeComponent();

   MainPage = new NavigationPage(new MainPage());
  }

  protected override void OnStart()
  {
   // Handle when your app starts
  }

  protected override void OnSleep()
  {
   // Handle when your app sleeps
  }

  protected override void OnResume()
  {
   // Handle when your app resumes
  }
 }
}

Langkah 5:
Buat sebuah class baru dengan nama CarouselData.cs 
Tugas file ini adalah untuk menampung data Image yang dapat kita panggil pada View di MainPage.axml


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LatCarousel
{
 public class CarouselData
 {
  public string Image { get; set; }
 }
  
}

Langkah 6:
Buat class baru untuk mengatur indikator  CarouselIndicator.cs
Tugas file ini adalah untuk membuat indicator pada CarouselView anda.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace LatCarousel
{
 public class CarouselIndicators : Grid
 {
  private ImageSource UnselectedImageSource = null;
  private ImageSource SelectedImageSource = null;
  private readonly StackLayout _indicators = new StackLayout() { Orientation = StackOrientation.Horizontal, HorizontalOptions = LayoutOptions.CenterAndExpand };

  public CarouselIndicators()
  {
   this.HorizontalOptions = LayoutOptions.CenterAndExpand;
   this.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
   this.Children.Add(_indicators);   
  }

  public static readonly BindableProperty PositionProperty = BindableProperty.Create(nameof(Position), typeof(int), typeof(CarouselIndicators), 0, BindingMode.TwoWay, propertyChanging: PositionChanging);
  public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(nameof(ItemsSource), typeof(IEnumerable), typeof(CarouselIndicators), Enumerable.Empty<object>(), BindingMode.OneWay, propertyChanged: ItemsChanged);
  public static readonly BindableProperty SelectedIndicatorProperty = BindableProperty.Create(nameof(SelectedIndicator), typeof(string), typeof(CarouselIndicators), "", BindingMode.OneWay);
  public static readonly BindableProperty UnselectedIndicatorProperty = BindableProperty.Create(nameof(UnselectedIndicator), typeof(string), typeof(CarouselIndicators), "", BindingMode.OneWay);
  public static readonly BindableProperty IndicatorWidthProperty = BindableProperty.Create(nameof(IndicatorWidth), typeof(double), typeof(CarouselIndicators), 0.0, BindingMode.OneWay);
  public static readonly BindableProperty IndicatorHeightProperty = BindableProperty.Create(nameof(IndicatorHeight), typeof(double), typeof(CarouselIndicators), 0.0, BindingMode.OneWay);


  public string SelectedIndicator
  {
   get { return (string)this.GetValue(SelectedIndicatorProperty); }
   set { this.SetValue(SelectedIndicatorProperty, value); }
  }

  public string UnselectedIndicator
  {
   get { return (string)this.GetValue(UnselectedIndicatorProperty); }
   set { this.SetValue(UnselectedIndicatorProperty, value); }
  }

  public double IndicatorWidth
  {
   get { return (double)this.GetValue(IndicatorWidthProperty); }
   set { this.SetValue(IndicatorWidthProperty, value); }
  }

  public double IndicatorHeight
  {
   get { return (double)this.GetValue(IndicatorHeightProperty); }
   set { this.SetValue(IndicatorHeightProperty, value); }
  }

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

  public IEnumerable ItemsSource
  {
   get { return (IEnumerable)this.GetValue(ItemsSourceProperty); }
   set { this.SetValue(ItemsSourceProperty, (object)value); }
  }

  private void Clear()
  {
   _indicators.Children.Clear();
  }

  private void Init(int position)
  {

   if (UnselectedImageSource == null)
    UnselectedImageSource = ImageSource.FromFile(UnselectedIndicator);

   if (SelectedImageSource == null)
    SelectedImageSource = ImageSource.FromFile(SelectedIndicator);

   if (_indicators.Children.Count > 0)
   {
    for (int i = 0; i < _indicators.Children.Count; i++)
    {
     if (((Image)_indicators.Children[i]).ClassId == nameof(State.Selected) && i != position)
      _indicators.Children[i] = BuildImage(State.Unselect, i);
     else if (((Image)_indicators.Children[i]).ClassId == nameof(State.Unselect) && i == position)
      _indicators.Children[i] = BuildImage(State.Selected, i);
    }
   }
   else
   {
    var enumerator = ItemsSource.GetEnumerator();
    int count = 0;
    while (enumerator.MoveNext())
    {
     Image image = null;
     if (position == count)
      image = BuildImage(State.Selected, count);
     else
      image = BuildImage(State.Unselect, count);

     _indicators.Children.Add(image);

     count++;
    }
   }
  }

  private Image BuildImage(State state, int position)
  {
   var image = new Image()
   {
    WidthRequest = IndicatorWidth,
    HeightRequest = IndicatorHeight,
    ClassId = state.ToString()
   };

   switch (state)
   {
    case State.Selected:
     image.Source = SelectedImageSource;
     break;
    case State.Unselect:
     image.Source = UnselectedImageSource;
     break;
    default:
     throw new Exception("Invalid state selected");
   }

   image.GestureRecognizers.Add(new TapGestureRecognizer() { Command = new Command(() => { Position = position; }) });

   return image;
  }

  private static void PositionChanging(object bindable, object oldValue, object newValue)
  {
   var carouselIndicators = bindable as CarouselIndicators;

   carouselIndicators.Init(Convert.ToInt32(newValue));
  }

  private static void ItemsChanged(object bindable, object oldValue, object newValue)
  {
   var carouselIndicators = bindable as CarouselIndicators;

   carouselIndicators.Clear();
   carouselIndicators.Init(0);
  }

  public enum State
  {
   Selected,
   Unselect  
  }
 }
}


Langkah 7 :
Pada MainPage.xaml.cs ketikan kode seperti berikut

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace LatCarousel
{
 public partial class MainPage : ContentPage, INotifyPropertyChanged
 {
  public MainPage()
  {
   InitializeComponent();
   Title = "Welcome Carousel";

   MyDataSource = new List<CarouselData>() { new CarouselData() { Image="gambarone.jpg" },
                                                      new CarouselData() { Image="gambartwo.jpg" },
                                                      new CarouselData() { Image="gambarthree.jpg" },
               new CarouselData() { Image="gambarfour.jpg" }
   };

            BindingContext = this;
  }

  public List<CarouselData> MyDataSource { get; set; }

  private int _position;
  public int Position { get { return _position; } set { _position = value; OnPropertyChanged(); } }
 }
}

Langkah 8:
Pada file MainPage.xaml ketikan code seperti berikut :

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:LatCarousel"
             xmlns:control="clr-namespace:Xamarin.Forms;assembly=Xamarin.Forms.CarouselView"
    xmlns:forms="clr-namespace:Xamarin.Forms;assembly=Xamarin.Forms.CarouselView"
             x:Class="LatCarousel.MainPage"
             BackgroundColor="Gray">

  <ContentView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
    <StackLayout Padding="20">
      <control:CarouselView ItemsSource="{Binding MyDataSource}" Position="{Binding Position, Mode=TwoWay}">
        <control:CarouselView.ItemTemplate>
           <DataTemplate>
            <Image Source="{Binding Image}" />
   </DataTemplate>

        </control:CarouselView.ItemTemplate>
      </control:CarouselView>
      <local:CarouselIndicators IndicatorHeight="16" IndicatorWidth="16" UnselectedIndicator="unselected_circle.png" SelectedIndicator="selected_circle.png" Position="{Binding Position}" ItemsSource="{Binding MyDataSource}" />
    </StackLayout>
    
  </ContentView>

</ContentPage>


Source Code : https://github.com/banyucenter/LatCarousel