├── src
├── iOS
│ ├── ITunesArtwork
│ ├── ITunesArtwork@2x
│ ├── Resources
│ │ ├── pin.png
│ │ ├── pin@2x.png
│ │ ├── Default.png
│ │ ├── Icon-76.png
│ │ ├── Default@2x.png
│ │ ├── Icon-60@2x.png
│ │ ├── Icon-60@3x.png
│ │ ├── Icon-76@2x.png
│ │ ├── Icon-Small.png
│ │ ├── Icon-Small-40.png
│ │ ├── Icon-Small@2x.png
│ │ ├── Icon-Small@3x.png
│ │ ├── Default-568h@2x.png
│ │ ├── Default-Portrait.png
│ │ ├── Icon-Small-40@2x.png
│ │ ├── Icon-Small-40@3x.png
│ │ ├── Default-Portrait@2x.png
│ │ └── LaunchScreen.storyboard
│ ├── packages.config
│ ├── Entitlements.plist
│ ├── Main.cs
│ ├── AppDelegate.cs
│ ├── Info.plist
│ ├── Renderers
│ │ └── CarouselLayoutRenderer.cs
│ └── SwippableBottomTabView.iOS.csproj
├── Droid
│ ├── Resources
│ │ ├── drawable
│ │ │ ├── icon.png
│ │ │ ├── one.jpeg
│ │ │ ├── pin.png
│ │ │ ├── pip.png
│ │ │ └── pip_selected.png
│ │ ├── drawable-hdpi
│ │ │ └── icon.png
│ │ ├── drawable-xhdpi
│ │ │ └── icon.png
│ │ ├── drawable-xxhdpi
│ │ │ └── icon.png
│ │ ├── AboutResources.txt
│ │ └── Resource.designer.cs
│ ├── packages.config
│ ├── Properties
│ │ ├── AndroidManifest.xml
│ │ └── AssemblyInfo.cs
│ ├── MainActivity.cs
│ ├── Assets
│ │ └── AboutAssets.txt
│ ├── Renderers
│ │ ├── CustomNavigationRenderer.cs
│ │ └── CarouselLayoutRenderer.cs
│ └── SwippableBottomTabView.Droid.csproj
├── repositories.config
├── SwippableBottomTabView
│ ├── ViewModels
│ │ ├── ICarouselViewModel.cs
│ │ ├── TabOneViewModel.cs
│ │ ├── TabTwoViewModel.cs
│ │ ├── TabbedPageViewModel.cs
│ │ ├── BaseViewModel.cs
│ │ └── SwitcherPageViewModel.cs
│ ├── DynamicTemplateLayout.cs
│ ├── TabPageOne.cs
│ ├── TabPageTwo.cs
│ ├── App.cs
│ ├── HomeView.cs
│ ├── SwippableBottomTabView.shproj
│ ├── SwitcherPage.cs
│ ├── SwippableBottomTabView.projitems
│ ├── PagerIndicatorDots.cs
│ ├── PagerIndicatorTabs.cs
│ ├── Controls
│ │ └── CarouselLayout.cs
│ └── HomePage.cs
├── .gitignore
└── SwippableBottomTabView.sln
├── README.md
└── LICENSE.md
/src/iOS/ITunesArtwork:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/iOS/ITunesArtwork
--------------------------------------------------------------------------------
/src/iOS/ITunesArtwork@2x:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/iOS/ITunesArtwork@2x
--------------------------------------------------------------------------------
/src/iOS/Resources/pin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/iOS/Resources/pin.png
--------------------------------------------------------------------------------
/src/iOS/Resources/pin@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/iOS/Resources/pin@2x.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/iOS/Resources/Default.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/iOS/Resources/Icon-76.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Default@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/iOS/Resources/Default@2x.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/iOS/Resources/Icon-60@2x.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/iOS/Resources/Icon-60@3x.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/iOS/Resources/Icon-76@2x.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-Small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/iOS/Resources/Icon-Small.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-Small-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/iOS/Resources/Icon-Small-40.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-Small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/iOS/Resources/Icon-Small@2x.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-Small@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/iOS/Resources/Icon-Small@3x.png
--------------------------------------------------------------------------------
/src/Droid/Resources/drawable/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/Droid/Resources/drawable/icon.png
--------------------------------------------------------------------------------
/src/Droid/Resources/drawable/one.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/Droid/Resources/drawable/one.jpeg
--------------------------------------------------------------------------------
/src/Droid/Resources/drawable/pin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/Droid/Resources/drawable/pin.png
--------------------------------------------------------------------------------
/src/Droid/Resources/drawable/pip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/Droid/Resources/drawable/pip.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Default-568h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/iOS/Resources/Default-568h@2x.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Default-Portrait.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/iOS/Resources/Default-Portrait.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-Small-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/iOS/Resources/Icon-Small-40@2x.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-Small-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/iOS/Resources/Icon-Small-40@3x.png
--------------------------------------------------------------------------------
/src/Droid/Resources/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/Droid/Resources/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/src/Droid/Resources/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/Droid/Resources/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Default-Portrait@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/iOS/Resources/Default-Portrait@2x.png
--------------------------------------------------------------------------------
/src/Droid/Resources/drawable-xxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/Droid/Resources/drawable-xxhdpi/icon.png
--------------------------------------------------------------------------------
/src/Droid/Resources/drawable/pip_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imgen/XamarinForms.SwippableBottomTabView/HEAD/src/Droid/Resources/drawable/pip_selected.png
--------------------------------------------------------------------------------
/src/iOS/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/repositories.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/iOS/Entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/SwippableBottomTabView/ViewModels/ICarouselViewModel.cs:
--------------------------------------------------------------------------------
1 | using Xamarin.Forms;
2 |
3 | namespace SwippableBottomTabView.ViewModels
4 | {
5 | public interface ICarouselViewModel
6 | {
7 | ContentView View { get; }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/Droid/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/Droid/Properties/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/SwippableBottomTabView/ViewModels/TabOneViewModel.cs:
--------------------------------------------------------------------------------
1 | using Xamarin.Forms;
2 |
3 | namespace SwippableBottomTabView.ViewModels
4 | {
5 | class TabOneViewModel : BaseViewModel, ICarouselViewModel
6 | {
7 | public Color PageOneColor
8 | {
9 | get { return Color.Red; }
10 | }
11 |
12 | public ContentView View
13 | {
14 | get { return new TabPageOne(); }
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/iOS/Main.cs:
--------------------------------------------------------------------------------
1 | using UIKit;
2 |
3 | namespace SwippableBottomTabView.iOS
4 | {
5 | public class Application
6 | {
7 | // This is the main entry point of the application.
8 | private static void Main(string[] args)
9 | {
10 | // if you want to use a different Application Delegate class from "AppDelegate"
11 | // you can specify it here.
12 | UIApplication.Main(args, null, "AppDelegate");
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/src/SwippableBottomTabView/ViewModels/TabTwoViewModel.cs:
--------------------------------------------------------------------------------
1 | using Xamarin.Forms;
2 |
3 | namespace SwippableBottomTabView.ViewModels
4 | {
5 | class TabTwoViewModel: BaseViewModel, ICarouselViewModel
6 | {
7 | public ContentView View
8 | {
9 | get { return new TabPageTwo(); }
10 | }
11 |
12 | public string PageTwoTitle
13 | {
14 | get
15 | {
16 | return "This is a title";
17 | }
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/iOS/AppDelegate.cs:
--------------------------------------------------------------------------------
1 | using Foundation;
2 | using UIKit;
3 |
4 | namespace SwippableBottomTabView.iOS
5 | {
6 | [Register("AppDelegate")]
7 | public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
8 | {
9 | public override bool FinishedLaunching(UIApplication app, NSDictionary options)
10 | {
11 | global::Xamarin.Forms.Forms.Init();
12 |
13 | LoadApplication(new App());
14 |
15 | return base.FinishedLaunching(app, options);
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/src/SwippableBottomTabView/DynamicTemplateLayout.cs:
--------------------------------------------------------------------------------
1 | using SwippableBottomTabView.ViewModels;
2 | using Xamarin.Forms;
3 |
4 | namespace SwippableBottomTabView
5 | {
6 | public class DynamicTemplateLayout : ViewCell
7 | {
8 | protected override void OnBindingContextChanged()
9 | {
10 | base.OnBindingContextChanged();
11 |
12 | var vm = BindingContext as ICarouselViewModel;
13 | var page = vm.View;
14 | page.BindingContext = vm;
15 | View = page;
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/.gitignore:
--------------------------------------------------------------------------------
1 | #Autosave files
2 | *~
3 |
4 | #build
5 | [Oo]bj/
6 | [Bb]in/
7 | packages/
8 | TestResults/
9 |
10 | # globs
11 | Makefile.in
12 | *.DS_Store
13 | *.sln.cache
14 | *.suo
15 | *.cache
16 | *.pidb
17 | *.userprefs
18 | *.usertasks
19 | config.log
20 | config.make
21 | config.status
22 | aclocal.m4
23 | install-sh
24 | autom4te.cache/
25 | *.user
26 | *.tar.gz
27 | tarballs/
28 | test-results/
29 | Thumbs.db
30 |
31 | #Mac bundle stuff
32 | *.dmg
33 | *.app
34 |
35 | #resharper
36 | *_Resharper.*
37 | *.Resharper
38 |
39 | #dotCover
40 | *.dotCover
41 |
--------------------------------------------------------------------------------
/src/SwippableBottomTabView/TabPageOne.cs:
--------------------------------------------------------------------------------
1 | using SwippableBottomTabView.ViewModels;
2 | using Xamarin.Forms;
3 |
4 | namespace SwippableBottomTabView
5 | {
6 | class TabPageOne: ContentView
7 | {
8 | public TabPageOne()
9 | {
10 | var box = new BoxView()
11 | {
12 | WidthRequest = 100,
13 | HeightRequest = 100,
14 | };
15 | box.SetBinding(BoxView.ColorProperty, vm => vm.PageOneColor);
16 | Content = box;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/SwippableBottomTabView/TabPageTwo.cs:
--------------------------------------------------------------------------------
1 | using SwippableBottomTabView.ViewModels;
2 | using Xamarin.Forms;
3 |
4 | namespace SwippableBottomTabView
5 | {
6 | class TabPageTwo: ContentView
7 | {
8 | public TabPageTwo()
9 | {
10 | BackgroundColor = Color.White;
11 | var label = new Label()
12 | {
13 | FontAttributes = Xamarin.Forms.FontAttributes.Bold,
14 | };
15 | label.TextColor = Color.Blue;
16 | label.SetBinding(Label.TextProperty, vm => vm.PageTwoTitle);
17 |
18 | Content = label;
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # XamarinForms.SwippableBottomTabView
2 | This is a Tab control based off Chris Riesgo's excellent Carousel View
3 |
4 | https://github.com/chrisriesgo/xamarin-forms-carouselview
5 | https://gist.github.com/chrisriesgo/2e9c88fa346e57745e73
6 |
7 | with his point of direction of how to implement a Tab View
8 |
9 | One caveat: this code is not very reusable, meaning it's not something you can drop into your project and it will work right away. You still need to do some work to integrate it into your project.
10 | Also, there is no transiton of the tabs when swiping like View Indicator in Android. The tab will be changed after the swipe is in place.
11 |
--------------------------------------------------------------------------------
/src/Droid/MainActivity.cs:
--------------------------------------------------------------------------------
1 | using Android.App;
2 | using Android.Content.PM;
3 | using Android.OS;
4 |
5 | namespace SwippableBottomTabView.Droid
6 | {
7 | [Activity(Label = "TabView Demo", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
8 | public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
9 | {
10 | protected override void OnCreate(Bundle bundle)
11 | {
12 | base.OnCreate(bundle);
13 |
14 | global::Xamarin.Forms.Forms.Init(this, bundle);
15 |
16 | LoadApplication(new App());
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/src/Droid/Assets/AboutAssets.txt:
--------------------------------------------------------------------------------
1 | Any raw assets you want to be deployed with your application can be placed in
2 | this directory (and child directories) and given a Build Action of "AndroidAsset".
3 |
4 | These files will be deployed with your package and will be accessible using Android's
5 | AssetManager, like this:
6 |
7 | public class ReadAsset : Activity
8 | {
9 | protected override void OnCreate (Bundle bundle)
10 | {
11 | base.OnCreate (bundle);
12 |
13 | InputStream input = Assets.Open ("my_asset.txt");
14 | }
15 | }
16 |
17 | Additionally, some Android functions will automatically load asset files:
18 |
19 | Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
20 |
--------------------------------------------------------------------------------
/src/SwippableBottomTabView/App.cs:
--------------------------------------------------------------------------------
1 | using Xamarin.Forms;
2 |
3 | namespace SwippableBottomTabView
4 | {
5 | public class App : Application
6 | {
7 | public App()
8 | {
9 | // The root page of your application
10 | var navPage = new NavigationPage(new SwitcherPage());
11 | navPage.Icon = null;
12 | MainPage = navPage;
13 | }
14 |
15 | protected override void OnStart()
16 | {
17 | // Handle when your app starts
18 | }
19 |
20 | protected override void OnSleep()
21 | {
22 | // Handle when your app sleeps
23 | }
24 |
25 | protected override void OnResume()
26 | {
27 | // Handle when your app resumes
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/src/SwippableBottomTabView/HomeView.cs:
--------------------------------------------------------------------------------
1 | using Xamarin.Forms;
2 |
3 | namespace SwippableBottomTabView
4 | {
5 | public class HomeView : ContentView
6 | {
7 | public HomeView()
8 | {
9 | BackgroundColor = Color.White;
10 |
11 | var label = new Label
12 | {
13 | XAlign = TextAlignment.Center,
14 | TextColor = Color.Black
15 | };
16 |
17 | label.SetBinding(Label.TextProperty, "Title");
18 | this.SetBinding(ContentView.BackgroundColorProperty, "Background");
19 |
20 | Content = new StackLayout
21 | {
22 | VerticalOptions = LayoutOptions.CenterAndExpand,
23 | Children = {
24 | label
25 | }
26 | };
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/src/Droid/Renderers/CustomNavigationRenderer.cs:
--------------------------------------------------------------------------------
1 | using Android.App;
2 | using Android.Graphics.Drawables;
3 | using Xamarin.Forms;
4 | using Xamarin.Forms.Platform.Android;
5 | using CustomLayouts.Droid.Renderers;
6 |
7 | [assembly: ExportRenderer(typeof(NavigationPage), typeof(CustomNavigationRenderer))]
8 |
9 | namespace CustomLayouts.Droid.Renderers
10 | {
11 | public class CustomNavigationRenderer : NavigationRenderer
12 | {
13 | protected override void OnElementChanged(ElementChangedEventArgs e)
14 | {
15 | base.OnElementChanged (e);
16 |
17 | RemoveAppIconFromActionBar ();
18 | }
19 |
20 | void RemoveAppIconFromActionBar()
21 | {
22 | // http://stackoverflow.com/questions/14606294/remove-icon-logo-from-action-bar-on-android
23 | var actionBar = ((Activity)Context).ActionBar;
24 | actionBar.SetIcon (new ColorDrawable(Color.Transparent.ToAndroid()));
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/src/SwippableBottomTabView/SwippableBottomTabView.shproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {77990895-4247-4E5A-9474-E3456B62A28D}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/Droid/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 |
3 | // Information about this assembly is defined by the following attributes.
4 | // Change them to the values specific to your project.
5 |
6 | [assembly: AssemblyTitle("SwippableBottomTabView.Droid")]
7 | [assembly: AssemblyDescription("")]
8 | [assembly: AssemblyConfiguration("")]
9 | [assembly: AssemblyCompany("")]
10 | [assembly: AssemblyProduct("")]
11 | [assembly: AssemblyCopyright("chrisriesgo")]
12 | [assembly: AssemblyTrademark("")]
13 | [assembly: AssemblyCulture("")]
14 |
15 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
16 | // The form "{Major}.{Minor}.*" will automatically update the build and revision,
17 | // and "{Major}.{Minor}.{Build}.*" will update just the revision.
18 |
19 | [assembly: AssemblyVersion("1.0.0")]
20 |
21 | // The following attributes are used to specify the signing key for the assembly,
22 | // if desired. See the Mono documentation for more information about signing.
23 |
24 | //[assembly: AssemblyDelaySign(false)]
25 | //[assembly: AssemblyKeyFile("")]
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Hailin Shu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/SwippableBottomTabView/ViewModels/TabbedPageViewModel.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 |
4 | namespace SwippableBottomTabView.ViewModels
5 | {
6 | public class TabbedPageViewModel: BaseViewModel
7 | {
8 | public TabbedPageViewModel()
9 | {
10 | Pages = new List
11 | {
12 | new TabOneViewModel(),
13 | new TabTwoViewModel()
14 | };
15 | }
16 |
17 | private IEnumerable _pages;
18 |
19 | public IEnumerable Pages
20 | {
21 | get
22 | {
23 | return _pages;
24 | }
25 | set
26 | {
27 | SetObservableProperty(ref _pages, value);
28 | CurrentPage = Pages.FirstOrDefault();
29 | }
30 | }
31 |
32 | private ICarouselViewModel _currentPage;
33 |
34 | public ICarouselViewModel CurrentPage
35 | {
36 | get
37 | {
38 | return _currentPage;
39 | }
40 | set
41 | {
42 | SetObservableProperty(ref _currentPage, value);
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/SwippableBottomTabView/SwitcherPage.cs:
--------------------------------------------------------------------------------
1 | using SwippableBottomTabView.Controls;
2 | using Xamarin.Forms;
3 |
4 | namespace SwippableBottomTabView
5 | {
6 | public class SwitcherPage : ContentPage
7 | {
8 | public SwitcherPage()
9 | {
10 | Title = "Pager Layout w/ Indicators";
11 |
12 | var none = new Button
13 | {
14 | HorizontalOptions = LayoutOptions.Center,
15 | Text = "No pager indicator",
16 | Command = new Command((obj) => Navigation.PushAsync(new HomePage(CarouselLayout.IndicatorStyleEnum.None)))
17 | };
18 | var dots = new Button
19 | {
20 | HorizontalOptions = LayoutOptions.Center,
21 | Text = "Dots",
22 | Command = new Command((obj) => Navigation.PushAsync(new HomePage(CarouselLayout.IndicatorStyleEnum.Dots)))
23 | };
24 | var tabs = new Button
25 | {
26 | HorizontalOptions = LayoutOptions.Center,
27 | Text = "Tabs",
28 | Command = new Command((obj) => Navigation.PushAsync(new HomePage(CarouselLayout.IndicatorStyleEnum.Tabs)))
29 | };
30 | Content = new StackLayout
31 | {
32 | Orientation = StackOrientation.Vertical,
33 | VerticalOptions = LayoutOptions.Center,
34 | Spacing = 20,
35 | Children = {
36 | none,
37 | dots,
38 | tabs
39 | }
40 | };
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/src/SwippableBottomTabView/ViewModels/BaseViewModel.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using System.Runtime.CompilerServices;
4 | using System.Threading.Tasks;
5 | using Xamarin.Forms;
6 |
7 | namespace SwippableBottomTabView.ViewModels
8 | {
9 | public abstract class BaseViewModel : INotifyPropertyChanged
10 | {
11 | public INavigation Navigation { get; set; }
12 |
13 | internal virtual Task Initialize(params object[] args)
14 | {
15 | return Task.FromResult(0);
16 | }
17 |
18 | protected void OnPropertyChanged(string propertyName)
19 | {
20 | if (PropertyChanged == null) return;
21 | PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
22 | }
23 |
24 | protected void SetObservableProperty(
25 | ref T field,
26 | T value,
27 | [CallerMemberName] string propertyName = "")
28 | {
29 | if (EqualityComparer.Default.Equals(field, value)) return;
30 | field = value;
31 | OnPropertyChanged(propertyName);
32 | }
33 |
34 | // string Md5Hash (string value)
35 | // {
36 | // var hash = MD5.Create ();
37 | // var data = hash.ComputeHash (Encoding.UTF8.GetBytes (value));
38 | // var builder = new StringBuilder ();
39 | // for (var i = 0; i < data.Length; i++) {
40 | // builder.Append (data [i].ToString ("x2"));
41 | // }
42 | // return builder.ToString ();
43 | // }
44 |
45 | public event PropertyChangedEventHandler PropertyChanged;
46 | }
47 | }
--------------------------------------------------------------------------------
/src/Droid/Resources/AboutResources.txt:
--------------------------------------------------------------------------------
1 | Images, layout descriptions, binary blobs and string dictionaries can be included
2 | in your application as resource files. Various Android APIs are designed to
3 | operate on the resource IDs instead of dealing with images, strings or binary blobs
4 | directly.
5 |
6 | For example, a sample Android app that contains a user interface layout (main.axml),
7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
8 | would keep its resources in the "Resources" directory of the application:
9 |
10 | Resources/
11 | drawable/
12 | icon.png
13 |
14 | layout/
15 | main.axml
16 |
17 | values/
18 | strings.xml
19 |
20 | In order to get the build system to recognize Android resources, set the build action to
21 | "AndroidResource". The native Android APIs do not operate directly with filenames, but
22 | instead operate on resource IDs. When you compile an Android application that uses resources,
23 | the build system will package the resources for distribution and generate a class called "R"
24 | (this is an Android convention) that contains the tokens for each one of the resources
25 | included. For example, for the above Resources layout, this is what the R class would expose:
26 |
27 | public class R {
28 | public class drawable {
29 | public const int icon = 0x123;
30 | }
31 |
32 | public class layout {
33 | public const int main = 0x456;
34 | }
35 |
36 | public class strings {
37 | public const int first_string = 0xabc;
38 | public const int second_string = 0xbcd;
39 | }
40 | }
41 |
42 | You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main
43 | to reference the layout/main.axml file, or R.strings.first_string to reference the first
44 | string in the dictionary file values/strings.xml.
45 |
--------------------------------------------------------------------------------
/src/SwippableBottomTabView/ViewModels/SwitcherPageViewModel.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using Xamarin.Forms;
4 |
5 | namespace SwippableBottomTabView.ViewModels
6 | {
7 | public class SwitcherPageViewModel : BaseViewModel
8 | {
9 | public SwitcherPageViewModel()
10 | {
11 | Pages = new List() {
12 | new HomeViewModel { Title = "1", Background = Color.White, ImageSource = "icon.png" },
13 | new HomeViewModel { Title = "2", Background = Color.Red, ImageSource = "icon.png" },
14 | new HomeViewModel { Title = "3", Background = Color.Blue, ImageSource = "icon.png" },
15 | new HomeViewModel { Title = "4", Background = Color.Yellow, ImageSource = "icon.png" },
16 | };
17 |
18 | CurrentPage = Pages.First();
19 | }
20 |
21 | private IEnumerable _pages;
22 |
23 | public IEnumerable Pages
24 | {
25 | get
26 | {
27 | return _pages;
28 | }
29 | set
30 | {
31 | SetObservableProperty(ref _pages, value);
32 | CurrentPage = Pages.FirstOrDefault();
33 | }
34 | }
35 |
36 | private HomeViewModel _currentPage;
37 |
38 | public HomeViewModel CurrentPage
39 | {
40 | get
41 | {
42 | return _currentPage;
43 | }
44 | set
45 | {
46 | SetObservableProperty(ref _currentPage, value);
47 | }
48 | }
49 | }
50 |
51 | public class HomeViewModel : BaseViewModel, ITabProvider
52 | {
53 | public HomeViewModel()
54 | {
55 | }
56 |
57 | public string Title { get; set; }
58 |
59 | public Color Background { get; set; }
60 |
61 | public ImageSource ImageSource { get; set; }
62 | }
63 | }
--------------------------------------------------------------------------------
/src/SwippableBottomTabView/SwippableBottomTabView.projitems:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
5 | true
6 | {77990895-4247-4E5A-9474-E3456B62A28D}
7 |
8 |
9 | SwippableBottomTabView
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDisplayName
6 | TabView Demo
7 | CFBundleIdentifier
8 | com.chrisriesgo.xamarin-forms-tabview
9 | CFBundleShortVersionString
10 | 1.0
11 | CFBundleVersion
12 | 1.0
13 | LSRequiresIPhoneOS
14 |
15 | MinimumOSVersion
16 |
17 | UIDeviceFamily
18 |
19 | 1
20 | 2
21 |
22 | UIRequiredDeviceCapabilities
23 |
24 | armv7
25 |
26 | UISupportedInterfaceOrientations
27 |
28 | UIInterfaceOrientationPortrait
29 | UIInterfaceOrientationLandscapeLeft
30 | UIInterfaceOrientationLandscapeRight
31 |
32 | UISupportedInterfaceOrientations~ipad
33 |
34 | UIInterfaceOrientationPortrait
35 | UIInterfaceOrientationPortraitUpsideDown
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | CFBundleIconFiles
40 |
41 | Icon-60@2x
42 | Icon-60@3x
43 | Icon-76
44 | Icon-76@2x
45 | Default
46 | Default@2x
47 | Default-568h
48 | Default-568h@2x
49 | Default-Landscape
50 | Default-Landscape@2x
51 | Default-Portrait
52 | Default-Portrait@2x
53 | Icon-Small-40
54 | Icon-Small-40@2x
55 | Icon-Small-40@3x
56 | Icon-Small
57 | Icon-Small@2x
58 | Icon-Small@3x
59 |
60 | UILaunchStoryboardName
61 | LaunchScreen
62 |
63 |
64 |
--------------------------------------------------------------------------------
/src/iOS/Renderers/CarouselLayoutRenderer.cs:
--------------------------------------------------------------------------------
1 | using SwippableBottomTabView.Controls;
2 | using SwippableBottomTabView.iOS.Renderers;
3 | using System;
4 | using System.ComponentModel;
5 | using UIKit;
6 | using Xamarin.Forms;
7 | using Xamarin.Forms.Platform.iOS;
8 |
9 | [assembly: ExportRenderer(typeof(CarouselLayout), typeof(CarouselLayoutRenderer))]
10 |
11 | namespace SwippableBottomTabView.iOS.Renderers
12 | {
13 | public class CarouselLayoutRenderer : ScrollViewRenderer
14 | {
15 | private UIScrollView _native;
16 |
17 | public CarouselLayoutRenderer()
18 | {
19 | PagingEnabled = true;
20 | ShowsHorizontalScrollIndicator = false;
21 | }
22 |
23 | protected override void OnElementChanged(VisualElementChangedEventArgs e)
24 | {
25 | base.OnElementChanged(e);
26 |
27 | if (e.OldElement != null) return;
28 |
29 | _native = (UIScrollView)NativeView;
30 | _native.Scrolled += NativeScrolled;
31 | e.NewElement.PropertyChanged += ElementPropertyChanged;
32 | }
33 |
34 | private void NativeScrolled(object sender, EventArgs e)
35 | {
36 | var center = _native.ContentOffset.X + (_native.Bounds.Width / 2);
37 | ((CarouselLayout)Element).SelectedIndex = ((int)center) / ((int)_native.Bounds.Width);
38 | }
39 |
40 | private void ElementPropertyChanged(object sender, PropertyChangedEventArgs e)
41 | {
42 | if (e.PropertyName == CarouselLayout.SelectedIndexProperty.PropertyName && !Dragging)
43 | {
44 | ScrollToSelection(false);
45 | }
46 | }
47 |
48 | private void ScrollToSelection(bool animate)
49 | {
50 | if (Element == null) return;
51 |
52 | _native.SetContentOffset(new CoreGraphics.CGPoint
53 | (_native.Bounds.Width *
54 | Math.Max(0, ((CarouselLayout)Element).SelectedIndex),
55 | _native.ContentOffset.Y),
56 | animate);
57 | }
58 |
59 | public override void Draw(CoreGraphics.CGRect rect)
60 | {
61 | base.Draw(rect);
62 | ScrollToSelection(false);
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/src/Droid/Resources/Resource.designer.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable 1591
2 | //------------------------------------------------------------------------------
3 | //
4 | // This code was generated by a tool.
5 | // Runtime Version:4.0.30319.34209
6 | //
7 | // Changes to this file may cause incorrect behavior and will be lost if
8 | // the code is regenerated.
9 | //
10 | //------------------------------------------------------------------------------
11 |
12 | [assembly: global::Android.Runtime.ResourceDesignerAttribute("SwippableBottomTabView.Droid.Resource", IsApplication=true)]
13 |
14 | namespace SwippableBottomTabView.Droid
15 | {
16 |
17 |
18 | [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")]
19 | public partial class Resource
20 | {
21 |
22 | static Resource()
23 | {
24 | global::Android.Runtime.ResourceIdManager.UpdateIdValues();
25 | }
26 |
27 | public static void UpdateIdValues()
28 | {
29 | global::Xamarin.Forms.Platform.Resource.String.ApplicationName = global::SwippableBottomTabView.Droid.Resource.String.ApplicationName;
30 | global::Xamarin.Forms.Platform.Resource.String.Hello = global::SwippableBottomTabView.Droid.Resource.String.Hello;
31 | }
32 |
33 | public partial class Attribute
34 | {
35 |
36 | static Attribute()
37 | {
38 | global::Android.Runtime.ResourceIdManager.UpdateIdValues();
39 | }
40 |
41 | private Attribute()
42 | {
43 | }
44 | }
45 |
46 | public partial class Drawable
47 | {
48 |
49 | // aapt resource value: 0x7f020000
50 | public const int icon = 2130837504;
51 |
52 | // aapt resource value: 0x7f020001
53 | public const int pin = 2130837505;
54 |
55 | static Drawable()
56 | {
57 | global::Android.Runtime.ResourceIdManager.UpdateIdValues();
58 | }
59 |
60 | private Drawable()
61 | {
62 | }
63 | }
64 |
65 | public partial class String
66 | {
67 |
68 | // aapt resource value: 0x7f030001
69 | public const int ApplicationName = 2130903041;
70 |
71 | // aapt resource value: 0x7f030000
72 | public const int Hello = 2130903040;
73 |
74 | static String()
75 | {
76 | global::Android.Runtime.ResourceIdManager.UpdateIdValues();
77 | }
78 |
79 | private String()
80 | {
81 | }
82 | }
83 | }
84 | }
85 | #pragma warning restore 1591
86 |
--------------------------------------------------------------------------------
/src/iOS/Resources/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/SwippableBottomTabView.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.31101.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SwippableBottomTabView", "SwippableBottomTabView\SwippableBottomTabView.shproj", "{77990895-4247-4E5A-9474-E3456B62A28D}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwippableBottomTabView.iOS", "iOS\SwippableBottomTabView.iOS.csproj", "{E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwippableBottomTabView.Droid", "Droid\SwippableBottomTabView.Droid.csproj", "{26422919-3EAD-440B-B516-E41B10D2AC56}"
11 | EndProject
12 | Global
13 | GlobalSection(SharedMSBuildProjectFiles) = preSolution
14 | SwippableBottomTabView\SwippableBottomTabView.projitems*{77990895-4247-4e5a-9474-e3456b62a28d}*SharedItemsImports = 13
15 | SwippableBottomTabView\SwippableBottomTabView.projitems*{e97c5e1f-83a0-4cd5-b1e1-91897b8c9f86}*SharedItemsImports = 4
16 | SwippableBottomTabView\SwippableBottomTabView.projitems*{26422919-3ead-440b-b516-e41b10d2ac56}*SharedItemsImports = 4
17 | EndGlobalSection
18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
19 | Debug|Any CPU = Debug|Any CPU
20 | Debug|iPhone = Debug|iPhone
21 | Debug|iPhoneSimulator = Debug|iPhoneSimulator
22 | Release|Any CPU = Release|Any CPU
23 | Release|iPhone = Release|iPhone
24 | Release|iPhoneSimulator = Release|iPhoneSimulator
25 | EndGlobalSection
26 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
27 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
28 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
29 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Debug|iPhone.ActiveCfg = Debug|iPhone
30 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Debug|iPhone.Build.0 = Debug|iPhone
31 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
32 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
33 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Release|Any CPU.ActiveCfg = Release|iPhone
34 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Release|Any CPU.Build.0 = Release|iPhone
35 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Release|iPhone.ActiveCfg = Release|iPhone
36 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Release|iPhone.Build.0 = Release|iPhone
37 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
38 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
39 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
40 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Debug|Any CPU.Build.0 = Debug|Any CPU
41 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
42 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Debug|iPhone.ActiveCfg = Debug|Any CPU
43 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Debug|iPhone.Build.0 = Debug|Any CPU
44 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
45 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
46 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Release|Any CPU.ActiveCfg = Release|Any CPU
47 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Release|Any CPU.Build.0 = Release|Any CPU
48 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Release|iPhone.ActiveCfg = Release|Any CPU
49 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Release|iPhone.Build.0 = Release|Any CPU
50 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
51 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
52 | EndGlobalSection
53 | GlobalSection(SolutionProperties) = preSolution
54 | HideSolutionNode = FALSE
55 | EndGlobalSection
56 | EndGlobal
57 |
--------------------------------------------------------------------------------
/src/SwippableBottomTabView/PagerIndicatorDots.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Linq;
4 | using Xamarin.Forms;
5 |
6 | namespace SwippableBottomTabView
7 | {
8 | public interface ITabProvider
9 | {
10 | ImageSource ImageSource { get; set; }
11 | }
12 |
13 | public class PagerIndicatorDots : StackLayout
14 | {
15 | private int _dotCount = 1;
16 | private int _selectedIndex;
17 |
18 | public Color DotColor { get; set; }
19 |
20 | public double DotSize { get; set; }
21 |
22 | public PagerIndicatorDots()
23 | {
24 | HorizontalOptions = LayoutOptions.CenterAndExpand;
25 | VerticalOptions = LayoutOptions.Center;
26 | Orientation = StackOrientation.Horizontal;
27 | DotColor = Color.Black;
28 | }
29 |
30 | private void CreateDot()
31 | {
32 | //Make one button and add it to the dotLayout
33 | var dot = new Button
34 | {
35 | BorderRadius = Convert.ToInt32(DotSize / 2),
36 | HeightRequest = DotSize,
37 | WidthRequest = DotSize,
38 | BackgroundColor = DotColor
39 | };
40 | Children.Add(dot);
41 | }
42 |
43 | private void CreateTabs()
44 | {
45 | foreach (var item in ItemsSource)
46 | {
47 | var tab = item as ITabProvider;
48 | var image = new Image
49 | {
50 | HeightRequest = 42,
51 | WidthRequest = 42,
52 | BackgroundColor = DotColor,
53 | Source = tab.ImageSource,
54 | };
55 | Children.Add(image);
56 | }
57 | }
58 |
59 | public static BindableProperty ItemsSourceProperty =
60 | BindableProperty.Create(
61 | pi => pi.ItemsSource,
62 | null,
63 | BindingMode.OneWay,
64 | propertyChanging: (bindable, oldValue, newValue) =>
65 | {
66 | ((PagerIndicatorDots)bindable).ItemsSourceChanging();
67 | },
68 | propertyChanged: (bindable, oldValue, newValue) =>
69 | {
70 | ((PagerIndicatorDots)bindable).ItemsSourceChanged();
71 | }
72 | );
73 |
74 | public IList ItemsSource
75 | {
76 | get
77 | {
78 | return (IList)GetValue(ItemsSourceProperty);
79 | }
80 | set
81 | {
82 | SetValue(ItemsSourceProperty, value);
83 | }
84 | }
85 |
86 | public static BindableProperty SelectedItemProperty =
87 | BindableProperty.Create(
88 | pi => pi.SelectedItem,
89 | null,
90 | BindingMode.TwoWay,
91 | propertyChanged: (bindable, oldValue, newValue) =>
92 | {
93 | ((PagerIndicatorDots)bindable).SelectedItemChanged();
94 | });
95 |
96 | public object SelectedItem
97 | {
98 | get
99 | {
100 | return GetValue(SelectedItemProperty);
101 | }
102 | set
103 | {
104 | SetValue(SelectedItemProperty, value);
105 | }
106 | }
107 |
108 | private void ItemsSourceChanging()
109 | {
110 | if (ItemsSource != null)
111 | _selectedIndex = ItemsSource.IndexOf(SelectedItem);
112 | }
113 |
114 | private void ItemsSourceChanged()
115 | {
116 | if (ItemsSource == null) return;
117 |
118 | // Dots *************************************
119 | var countDelta = ItemsSource.Count - Children.Count;
120 |
121 | if (countDelta > 0)
122 | {
123 | for (var i = 0; i < countDelta; i++)
124 | {
125 | CreateDot();
126 | }
127 | }
128 | else if (countDelta < 0)
129 | {
130 | for (var i = 0; i < -countDelta; i++)
131 | {
132 | Children.RemoveAt(0);
133 | }
134 | }
135 | //*******************************************
136 | }
137 |
138 | private void SelectedItemChanged()
139 | {
140 | var selectedIndex = ItemsSource.IndexOf(SelectedItem);
141 | var pagerIndicators = Children.Cast