├── src
├── iOS
│ ├── ITunesArtwork
│ ├── ITunesArtwork@2x
│ ├── Resources
│ │ ├── pin.png
│ │ ├── Default.png
│ │ ├── Icon-76.png
│ │ ├── pin@2x.png
│ │ ├── Default@2x.png
│ │ ├── Icon-60@2x.png
│ │ ├── Icon-60@3x.png
│ │ ├── Icon-76@2x.png
│ │ ├── Icon-Small.png
│ │ ├── Default-568h@2x.png
│ │ ├── Icon-Small-40.png
│ │ ├── Icon-Small@2x.png
│ │ ├── Icon-Small@3x.png
│ │ ├── Default-Portrait.png
│ │ ├── Icon-Small-40@2x.png
│ │ ├── Icon-Small-40@3x.png
│ │ ├── Default-Portrait@2x.png
│ │ └── LaunchScreen.storyboard
│ ├── packages.config
│ ├── Entitlements.plist
│ ├── AppDelegate.cs
│ ├── Main.cs
│ ├── Renderers
│ │ └── CarouselLayoutRenderer.cs
│ ├── Info.plist
│ └── CustomLayouts.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
│ ├── Properties
│ │ ├── AndroidManifest.xml
│ │ └── AssemblyInfo.cs
│ ├── MainActivity.cs
│ ├── Assets
│ │ └── AboutAssets.txt
│ ├── Renderers
│ │ ├── CustomNavigationRenderer.cs
│ │ └── CarouselLayoutRenderer.cs
│ ├── packages.config
│ └── CustomLayouts.Droid.csproj
├── .gitignore
├── CustomLayouts
│ ├── App.cs
│ ├── HomeView.cs
│ ├── CustomLayouts.shproj
│ ├── SwitcherPage.cs
│ ├── CustomLayouts.projitems
│ ├── ViewModels
│ │ ├── SwitcherPageViewModel.cs
│ │ └── BaseViewModel.cs
│ ├── PagerIndicatorDots.cs
│ ├── Controls
│ │ └── CarouselLayout.cs
│ ├── HomePage.cs
│ └── PagerIndicatorTabs.cs
└── CustomLayouts.sln
├── Images
└── carousel_view.gif
└── README.md
/src/iOS/ITunesArtwork:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/iOS/ITunesArtwork
--------------------------------------------------------------------------------
/Images/carousel_view.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/Images/carousel_view.gif
--------------------------------------------------------------------------------
/src/iOS/ITunesArtwork@2x:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/iOS/ITunesArtwork@2x
--------------------------------------------------------------------------------
/src/iOS/Resources/pin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/iOS/Resources/pin.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/iOS/Resources/Default.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/iOS/Resources/Icon-76.png
--------------------------------------------------------------------------------
/src/iOS/Resources/pin@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/iOS/Resources/pin@2x.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Default@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/iOS/Resources/Default@2x.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/iOS/Resources/Icon-60@2x.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/iOS/Resources/Icon-60@3x.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/iOS/Resources/Icon-76@2x.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-Small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/iOS/Resources/Icon-Small.png
--------------------------------------------------------------------------------
/src/Droid/Resources/drawable/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/Droid/Resources/drawable/icon.png
--------------------------------------------------------------------------------
/src/Droid/Resources/drawable/one.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/Droid/Resources/drawable/one.jpeg
--------------------------------------------------------------------------------
/src/Droid/Resources/drawable/pin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/Droid/Resources/drawable/pin.png
--------------------------------------------------------------------------------
/src/Droid/Resources/drawable/pip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/Droid/Resources/drawable/pip.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Default-568h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/iOS/Resources/Default-568h@2x.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-Small-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/iOS/Resources/Icon-Small-40.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-Small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/iOS/Resources/Icon-Small@2x.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-Small@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/iOS/Resources/Icon-Small@3x.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Default-Portrait.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/iOS/Resources/Default-Portrait.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-Small-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/iOS/Resources/Icon-Small-40@2x.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Icon-Small-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/iOS/Resources/Icon-Small-40@3x.png
--------------------------------------------------------------------------------
/src/Droid/Resources/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/Droid/Resources/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/src/iOS/Resources/Default-Portrait@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/iOS/Resources/Default-Portrait@2x.png
--------------------------------------------------------------------------------
/src/Droid/Resources/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/Droid/Resources/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/src/Droid/Resources/drawable-xxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/Droid/Resources/drawable-xxhdpi/icon.png
--------------------------------------------------------------------------------
/src/Droid/Resources/drawable/pip_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chrisriesgo/xamarin-forms-carouselview/HEAD/src/Droid/Resources/drawable/pip_selected.png
--------------------------------------------------------------------------------
/src/iOS/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/iOS/Entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/Droid/Properties/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/iOS/AppDelegate.cs:
--------------------------------------------------------------------------------
1 |
2 | using Foundation;
3 | using UIKit;
4 |
5 | namespace CustomLayouts.iOS
6 | {
7 | [Register("AppDelegate")]
8 | public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
9 | {
10 | public override bool FinishedLaunching(UIApplication app, NSDictionary options)
11 | {
12 | global::Xamarin.Forms.Forms.Init();
13 |
14 | LoadApplication(new App());
15 |
16 | return base.FinishedLaunching(app, options);
17 | }
18 | }
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/src/iOS/Main.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | using Foundation;
6 | using UIKit;
7 |
8 | namespace CustomLayouts.iOS
9 | {
10 | public class Application
11 | {
12 | // This is the main entry point of the application.
13 | static void Main(string[] args)
14 | {
15 | // if you want to use a different Application Delegate class from "AppDelegate"
16 | // you can specify it here.
17 | UIApplication.Main(args, null, "AppDelegate");
18 | }
19 | }
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/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 |
42 | Resource.designer.cs
--------------------------------------------------------------------------------
/src/Droid/MainActivity.cs:
--------------------------------------------------------------------------------
1 |
2 | using Android.App;
3 | using Android.Content.PM;
4 | using Android.OS;
5 |
6 | namespace CustomLayouts.Droid
7 | {
8 | [Activity(Label = "CarouselView Demo", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
9 | public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
10 | {
11 | protected override void OnCreate(Bundle bundle)
12 | {
13 | base.OnCreate(bundle);
14 |
15 | global::Xamarin.Forms.Forms.Init(this, bundle);
16 |
17 | LoadApplication(new App());
18 | }
19 | }
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/src/CustomLayouts/App.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | using Xamarin.Forms;
4 |
5 | namespace CustomLayouts
6 | {
7 | public class App : Application
8 | {
9 | public App()
10 | {
11 | // The root page of your application
12 | var navPage = new NavigationPage(new SwitcherPage());
13 | navPage.Icon = null;
14 | MainPage = navPage;
15 | }
16 |
17 | protected override void OnStart()
18 | {
19 | // Handle when your app starts
20 | }
21 |
22 | protected override void OnSleep()
23 | {
24 | // Handle when your app sleeps
25 | }
26 |
27 | protected override void OnResume()
28 | {
29 | // Handle when your app resumes
30 | }
31 | }
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/src/CustomLayouts/HomeView.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xamarin.Forms;
3 |
4 | namespace CustomLayouts
5 | {
6 | public class HomeView : ContentView
7 | {
8 | public HomeView()
9 | {
10 | BackgroundColor = Color.White;
11 |
12 | var label = new Label {
13 | HorizontalTextAlignment = 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 | VerticalOptions = LayoutOptions.CenterAndExpand,
22 | Children = {
23 | label
24 | }
25 | };
26 | }
27 | }
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/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/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/CustomLayouts/CustomLayouts.shproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {77990895-4247-4E5A-9474-E3456B62A28D}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/Droid/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Xamarin.Forms CarouselView
2 |
3 | _A version of this recipe that uses the **Xamarin.Forms.CarouselView** [from NuGet](https://www.nuget.org/packages/Xamarin.Forms.CarouselView/), can be found on [this branch](https://github.com/chrisriesgo/xamarin-forms-carouselview/issues/37)._
4 |
5 | ---
6 |
7 | Thanks to my friends at [Firefly Logic](https://github.com/FireflyLogic/couchbase-connect-14) and to [Michael Watson](https://github.com/xamarin/customersuccess/tree/master/samples/Xamarin.Forms/SliderView) for the inspiration in creating this custom control.
8 |
9 | This control mirrors the functionality of the CarouselPage - except the "pages" are simply Content Views.
10 |
11 | I have examples that show the CarouselView used as:
12 |
13 | - A full-page control with no page indicators
14 | - A gallery-style control with **dots** as page indicators
15 | - A full-page control with **tabs** as page indicators
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/Droid/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using Android.App;
4 |
5 | // Information about this assembly is defined by the following attributes.
6 | // Change them to the values specific to your project.
7 |
8 | [assembly: AssemblyTitle("CustomLayouts.Droid")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("")]
13 | [assembly: AssemblyCopyright("chrisriesgo")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
18 | // The form "{Major}.{Minor}.*" will automatically update the build and revision,
19 | // and "{Major}.{Minor}.{Build}.*" will update just the revision.
20 |
21 | [assembly: AssemblyVersion("1.0.0")]
22 |
23 | // The following attributes are used to specify the signing key for the assembly,
24 | // if desired. See the Mono documentation for more information about signing.
25 |
26 | //[assembly: AssemblyDelaySign(false)]
27 | //[assembly: AssemblyKeyFile("")]
28 |
29 |
--------------------------------------------------------------------------------
/src/CustomLayouts/SwitcherPage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xamarin.Forms;
3 | using CustomLayouts.Controls;
4 |
5 | namespace CustomLayouts
6 | {
7 | public class SwitcherPage : ContentPage
8 | {
9 | public SwitcherPage()
10 | {
11 | Title = "Pager Layout w/ Indicators";
12 |
13 | var none = new Button {
14 | HorizontalOptions = LayoutOptions.Center,
15 | Text = "No pager indicator",
16 | Command = new Command(async (obj) => await Navigation.PushAsync(new HomePage(CarouselLayout.IndicatorStyleEnum.None)))
17 | };
18 | var dots = new Button {
19 | HorizontalOptions = LayoutOptions.Center,
20 | Text = "Dots",
21 | Command = new Command(async (obj) => await Navigation.PushAsync(new HomePage(CarouselLayout.IndicatorStyleEnum.Dots)))
22 | };
23 | var tabs = new Button {
24 | HorizontalOptions = LayoutOptions.Center,
25 | Text = "Tabs",
26 | Command = new Command(async (obj) => await Navigation.PushAsync(new HomePage(CarouselLayout.IndicatorStyleEnum.Tabs)))
27 | };
28 | Content = new StackLayout {
29 | Orientation = StackOrientation.Vertical,
30 | VerticalOptions = LayoutOptions.Center,
31 | Spacing = 20,
32 | Children = {
33 | none,
34 | dots,
35 | tabs
36 | }
37 | };
38 | }
39 | }
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/src/CustomLayouts/CustomLayouts.projitems:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
5 | true
6 | {77990895-4247-4E5A-9474-E3456B62A28D}
7 |
8 |
9 | CustomLayouts
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/CustomLayouts/ViewModels/SwitcherPageViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Xamarin.Forms;
5 |
6 | namespace CustomLayouts.ViewModels
7 | {
8 | public class SwitcherPageViewModel : BaseViewModel
9 | {
10 | public SwitcherPageViewModel()
11 | {
12 | Pages = new List() {
13 | new HomeViewModel { Title = "1", Background = Color.White, ImageSource = "icon.png" },
14 | new HomeViewModel { Title = "2", Background = Color.Red, ImageSource = "icon.png" },
15 | new HomeViewModel { Title = "3", Background = Color.Blue, ImageSource = "icon.png" },
16 | new HomeViewModel { Title = "4", Background = Color.Yellow, ImageSource = "icon.png" },
17 | };
18 |
19 | CurrentPage = Pages.First();
20 | }
21 |
22 | IEnumerable _pages;
23 | public IEnumerable Pages {
24 | get {
25 | return _pages;
26 | }
27 | set {
28 | SetObservableProperty (ref _pages, value);
29 | CurrentPage = Pages.FirstOrDefault ();
30 | }
31 | }
32 |
33 | HomeViewModel _currentPage;
34 | public HomeViewModel CurrentPage {
35 | get {
36 | return _currentPage;
37 | }
38 | set {
39 | SetObservableProperty (ref _currentPage, value);
40 | }
41 | }
42 | }
43 |
44 | public class HomeViewModel : BaseViewModel, ITabProvider
45 | {
46 | public HomeViewModel() {}
47 |
48 | public string Title { get; set; }
49 | public Color Background { get; set; }
50 | public string ImageSource { get; set; }
51 | }
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/src/CustomLayouts/ViewModels/BaseViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Runtime.CompilerServices;
4 | using System.Collections.Generic;
5 | using System.Threading.Tasks;
6 | using Xamarin.Forms;
7 | using System.Security.Cryptography;
8 | using System.Text;
9 |
10 | namespace CustomLayouts.ViewModels
11 | {
12 | public abstract class BaseViewModel : INotifyPropertyChanged
13 | {
14 | public INavigation Navigation { get; set; }
15 |
16 | internal virtual Task Initialize (params object[] args)
17 | {
18 | return Task.FromResult (0);
19 | }
20 |
21 | protected void OnPropertyChanged(string propertyName) {
22 | if (PropertyChanged == null) return;
23 | PropertyChanged (this, new PropertyChangedEventArgs (propertyName));
24 | }
25 |
26 | protected void SetObservableProperty(
27 | ref T field,
28 | T value,
29 | [CallerMemberName] string propertyName = "")
30 | {
31 | if (EqualityComparer.Default.Equals(field, value)) return;
32 | field = value;
33 | OnPropertyChanged (propertyName);
34 | }
35 |
36 | // string Md5Hash (string value)
37 | // {
38 | // var hash = MD5.Create ();
39 | // var data = hash.ComputeHash (Encoding.UTF8.GetBytes (value));
40 | // var builder = new StringBuilder ();
41 | // for (var i = 0; i < data.Length; i++) {
42 | // builder.Append (data [i].ToString ("x2"));
43 | // }
44 | // return builder.ToString ();
45 | // }
46 |
47 | #region INotifyPropertyChanged implementation
48 | public event PropertyChangedEventHandler PropertyChanged;
49 | #endregion
50 | }
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/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/iOS/Renderers/CarouselLayoutRenderer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xamarin.Forms;
3 | using CustomLayouts.Controls;
4 | using CustomLayouts.iOS.Renderers;
5 | using Xamarin.Forms.Platform.iOS;
6 | using UIKit;
7 | using System.ComponentModel;
8 | using System.Drawing;
9 |
10 | [assembly:ExportRenderer(typeof(CarouselLayout), typeof(CarouselLayoutRenderer))]
11 |
12 | namespace CustomLayouts.iOS.Renderers
13 | {
14 | public class CarouselLayoutRenderer : ScrollViewRenderer
15 | {
16 | UIScrollView _native;
17 |
18 | public CarouselLayoutRenderer ()
19 | {
20 | PagingEnabled = true;
21 | ShowsHorizontalScrollIndicator = false;
22 | }
23 |
24 | protected override void OnElementChanged(VisualElementChangedEventArgs e)
25 | {
26 | base.OnElementChanged(e);
27 |
28 | if (e.OldElement != null) return;
29 |
30 | _native = (UIScrollView)NativeView;
31 | _native.Scrolled += NativeScrolled;
32 | e.NewElement.PropertyChanged += ElementPropertyChanged;
33 | }
34 |
35 | void NativeScrolled (object sender, EventArgs e)
36 | {
37 | var center = _native.ContentOffset.X + (_native.Bounds.Width / 2);
38 | ((CarouselLayout)Element).SelectedIndex = ((int)center) / ((int)_native.Bounds.Width);
39 | }
40 |
41 | void ElementPropertyChanged(object sender, PropertyChangedEventArgs e) {
42 | if (e.PropertyName == CarouselLayout.SelectedIndexProperty.PropertyName && !Dragging) {
43 | ScrollToSelection (false);
44 | }
45 | }
46 |
47 | void ScrollToSelection (bool animate)
48 | {
49 | if (Element == null) return;
50 |
51 | _native.SetContentOffset (new CoreGraphics.CGPoint
52 | (_native.Bounds.Width *
53 | Math.Max(0, ((CarouselLayout)Element).SelectedIndex),
54 | _native.ContentOffset.Y),
55 | animate);
56 | }
57 |
58 | public override void Draw(CoreGraphics.CGRect rect)
59 | {
60 | base.Draw (rect);
61 | ScrollToSelection (false);
62 | }
63 | }
64 | }
65 |
66 |
--------------------------------------------------------------------------------
/src/iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDisplayName
6 | CarouselView Demo
7 | CFBundleIdentifier
8 | com.chrisriesgo.xamarin-forms-carouselview
9 | CFBundleShortVersionString
10 | 1.0
11 | CFBundleVersion
12 | 1.0
13 | LSRequiresIPhoneOS
14 |
15 | MinimumOSVersion
16 | 7.0
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/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/CustomLayouts.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2012
4 | Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "CustomLayouts", "CustomLayouts\CustomLayouts.shproj", "{77990895-4247-4E5A-9474-E3456B62A28D}"
5 | EndProject
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomLayouts.iOS", "iOS\CustomLayouts.iOS.csproj", "{E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomLayouts.Droid", "Droid\CustomLayouts.Droid.csproj", "{26422919-3EAD-440B-B516-E41B10D2AC56}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|iPhoneSimulator = Debug|iPhoneSimulator
13 | Release|iPhone = Release|iPhone
14 | Release|iPhoneSimulator = Release|iPhoneSimulator
15 | Debug|iPhone = Debug|iPhone
16 | Debug|Any CPU = Debug|Any CPU
17 | Release|Any CPU = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Debug|iPhone.ActiveCfg = Debug|Any CPU
23 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Debug|iPhone.Build.0 = Debug|Any CPU
24 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
25 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
26 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Release|Any CPU.Build.0 = Release|Any CPU
28 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Release|iPhone.ActiveCfg = Release|Any CPU
29 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Release|iPhone.Build.0 = Release|Any CPU
30 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
31 | {26422919-3EAD-440B-B516-E41B10D2AC56}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
32 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
33 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
34 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Debug|iPhone.ActiveCfg = Debug|iPhone
35 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Debug|iPhone.Build.0 = Debug|iPhone
36 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
37 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
38 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Release|Any CPU.ActiveCfg = Release|iPhone
39 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Release|Any CPU.Build.0 = Release|iPhone
40 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Release|iPhone.ActiveCfg = Release|iPhone
41 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Release|iPhone.Build.0 = Release|iPhone
42 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
43 | {E97C5E1F-83A0-4CD5-B1E1-91897B8C9F86}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
44 | EndGlobalSection
45 | EndGlobal
46 |
--------------------------------------------------------------------------------
/src/CustomLayouts/PagerIndicatorDots.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xamarin.Forms;
3 | using System.Collections;
4 | using System.Linq;
5 |
6 | namespace CustomLayouts
7 | {
8 | public interface ITabProvider
9 | {
10 | string ImageSource { get; set; }
11 | }
12 |
13 | public class PagerIndicatorDots : StackLayout
14 | {
15 | int _selectedIndex;
16 |
17 | public Color DotColor { get; set; }
18 | public double DotSize { get; set; }
19 |
20 | public PagerIndicatorDots()
21 | {
22 | HorizontalOptions = LayoutOptions.CenterAndExpand;
23 | VerticalOptions = LayoutOptions.Center;
24 | Orientation = StackOrientation.Horizontal;
25 | DotColor = Color.Black;
26 | }
27 |
28 | void CreateDot()
29 | {
30 | //Make one button and add it to the dotLayout
31 | var dot = new Button {
32 | BorderRadius = Convert.ToInt32(DotSize/2),
33 | HeightRequest = DotSize,
34 | WidthRequest = DotSize,
35 | BackgroundColor = DotColor
36 | };
37 | Children.Add(dot);
38 | }
39 |
40 | void CreateTabs()
41 | {
42 | foreach(var item in ItemsSource)
43 | {
44 | var tab = item as ITabProvider;
45 | var image = new Image {
46 | HeightRequest = 42,
47 | WidthRequest = 42,
48 | BackgroundColor = DotColor,
49 | Source = tab.ImageSource,
50 | };
51 | Children.Add(image);
52 | }
53 | }
54 |
55 | public static BindableProperty ItemsSourceProperty =
56 | BindableProperty.Create(
57 | nameof(ItemsSource),
58 | typeof(IList),
59 | typeof(PagerIndicatorDots),
60 | null,
61 | BindingMode.OneWay,
62 | propertyChanging: (bindable, oldValue, newValue) =>
63 | {
64 | ((PagerIndicatorDots)bindable).ItemsSourceChanging();
65 | },
66 | propertyChanged: (bindable, oldValue, newValue) =>
67 | {
68 | ((PagerIndicatorDots)bindable).ItemsSourceChanged();
69 | }
70 | );
71 |
72 | public IList ItemsSource {
73 | get {
74 | return (IList)GetValue(ItemsSourceProperty);
75 | }
76 | set {
77 | SetValue (ItemsSourceProperty, value);
78 | }
79 | }
80 |
81 | public static BindableProperty SelectedItemProperty =
82 | BindableProperty.Create(
83 | nameof(SelectedItem),
84 | typeof(object),
85 | typeof(PagerIndicatorDots),
86 | null,
87 | BindingMode.TwoWay,
88 | propertyChanged: (bindable, oldValue, newValue) =>
89 | {
90 | ((PagerIndicatorDots)bindable).SelectedItemChanged();
91 | }
92 | );
93 |
94 | public object SelectedItem {
95 | get {
96 | return GetValue (SelectedItemProperty);
97 | }
98 | set {
99 | SetValue (SelectedItemProperty, value);
100 | }
101 | }
102 |
103 | void ItemsSourceChanging ()
104 | {
105 | if (ItemsSource != null)
106 | _selectedIndex = ItemsSource.IndexOf (SelectedItem);
107 | }
108 |
109 | void ItemsSourceChanged ()
110 | {
111 | if (ItemsSource == null) return;
112 |
113 | // Dots *************************************
114 | var countDelta = ItemsSource.Count - Children.Count;
115 |
116 | if (countDelta > 0) {
117 | for (var i = 0; i < countDelta; i++)
118 | {
119 | CreateDot();
120 | }
121 | }
122 | else if (countDelta < 0)
123 | {
124 | for (var i = 0; i < -countDelta; i++)
125 | {
126 | Children.RemoveAt (0);
127 | }
128 | }
129 | //*******************************************
130 | }
131 |
132 | void SelectedItemChanged () {
133 |
134 | var selectedIndex = ItemsSource.IndexOf (SelectedItem);
135 | var pagerIndicators = Children.Cast