Created
January 6, 2016 20:01
-
-
Save RedTahr/9474b7b1fd5c305b5e20 to your computer and use it in GitHub Desktop.
My copy of chrisriesgo / xamarin-forms-carouselview using Montemagno's FrenchPressTimer (see gist > Timer.cs)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Linq; | |
// using System.Timers; | |
using Xamarin.Forms; | |
namespace ....Core.Control | |
{ | |
public class CarouselLayout : ScrollView, IDisposable | |
{ | |
public enum IndicatorStyleEnum | |
{ | |
None, | |
Dots, | |
Tabs | |
} | |
readonly StackLayout stack; | |
Timer selectedItemTimer; | |
int selectedIndex; | |
readonly int timerDelayWhenSliding = 300; | |
public CarouselLayout() | |
{ | |
Orientation = ScrollOrientation.Horizontal; | |
stack = new StackLayout | |
{ | |
Orientation = StackOrientation.Horizontal, | |
Spacing = 0 | |
}; | |
Content = stack; | |
selectedItemTimerStop(); | |
selectedItemTimerStart(); | |
//_selectedItemTimer = new Timer | |
//{ | |
// AutoReset = false, | |
// Interval = 300 | |
//}; | |
//_selectedItemTimer.Elapsed += SelectedItemTimerElapsed; | |
} | |
public IndicatorStyleEnum IndicatorStyle { get; set; } | |
public IList<Xamarin.Forms.View> Children { | |
get { | |
return stack.Children; | |
} | |
} | |
private bool _layingOutChildren; | |
protected override void LayoutChildren(double x, double y, double width, double height) | |
{ | |
base.LayoutChildren(x, y, width, height); | |
if (_layingOutChildren) return; | |
_layingOutChildren = true; | |
foreach (var child in Children) child.WidthRequest = width; | |
_layingOutChildren = false; | |
} | |
public static readonly BindableProperty SelectedIndexProperty = | |
BindableProperty.Create<CarouselLayout, int>( | |
carousel => carousel.SelectedIndex, | |
0, | |
BindingMode.TwoWay, | |
propertyChanged: (bindable, oldValue, newValue) => { | |
((CarouselLayout)bindable).UpdateSelectedItem(); | |
} | |
); | |
public int SelectedIndex { | |
get { | |
return (int)GetValue(SelectedIndexProperty); | |
} | |
set { | |
SetValue(SelectedIndexProperty, value); | |
} | |
} | |
void UpdateSelectedItem() | |
{ | |
selectedItemTimerStop(); | |
selectedItemTimerStart(); | |
//_selectedItemTimer.Stop(); | |
//_selectedItemTimer.Start(); | |
} | |
void SelectedItemTimerCallback(object args) | |
{ | |
// check children has a count, otherwise windows phone throws an out of range exception, why the others don't I'm not sure, haven't looked into it. | |
SelectedItem = SelectedIndex > -1 && Children?.Count > 0 ? Children[SelectedIndex].BindingContext : null; | |
selectedItemTimerStop(); | |
} | |
//void SelectedItemTimerElapsed(object sender, ElapsedEventArgs e) | |
//{ | |
// SelectedItem = SelectedIndex > -1 ? Children[SelectedIndex].BindingContext : null; | |
//} | |
public static readonly BindableProperty ItemsSourceProperty = | |
BindableProperty.Create<CarouselLayout, IList>( | |
view => view.ItemsSource, | |
null, | |
propertyChanging: (bindableObject, oldValue, newValue) => { | |
((CarouselLayout)bindableObject).ItemsSourceChanging(); | |
}, | |
propertyChanged: (bindableObject, oldValue, newValue) => { | |
((CarouselLayout)bindableObject).ItemsSourceChanged(); | |
} | |
); | |
public IList ItemsSource { | |
get { | |
return (IList)GetValue(ItemsSourceProperty); | |
} | |
set { | |
SetValue(ItemsSourceProperty, value); | |
} | |
} | |
void ItemsSourceChanging() | |
{ | |
if (ItemsSource == null) return; | |
selectedIndex = ItemsSource.IndexOf(SelectedItem); | |
} | |
void ItemsSourceChanged() | |
{ | |
stack.Children.Clear(); | |
foreach (var item in ItemsSource) | |
{ | |
var view = (Xamarin.Forms.View)ItemTemplate.CreateContent(); | |
var bindableObject = view as BindableObject; | |
if (bindableObject != null) | |
bindableObject.BindingContext = item; | |
stack.Children.Add(view); | |
} | |
if (selectedIndex >= 0) SelectedIndex = selectedIndex; | |
} | |
public DataTemplate ItemTemplate { | |
get; | |
set; | |
} | |
public static readonly BindableProperty SelectedItemProperty = | |
BindableProperty.Create<CarouselLayout, object>( | |
view => view.SelectedItem, | |
null, | |
BindingMode.TwoWay, | |
propertyChanged: (bindable, oldValue, newValue) => { | |
((CarouselLayout)bindable).UpdateSelectedIndex(); | |
} | |
); | |
public object SelectedItem { | |
get { | |
return GetValue(SelectedItemProperty); | |
} | |
set { | |
SetValue(SelectedItemProperty, value); | |
} | |
} | |
void UpdateSelectedIndex() | |
{ | |
if (SelectedItem == BindingContext) return; | |
SelectedIndex = Children | |
.Select(c => c.BindingContext) | |
.ToList() | |
.IndexOf(SelectedItem); | |
} | |
private void selectedItemTimerStop() | |
{ | |
if (selectedItemTimer != null) | |
{ | |
selectedItemTimer.Dispose(); | |
selectedItemTimer = null; | |
} | |
} | |
private void selectedItemTimerStart() | |
{ | |
if (selectedItemTimer == null) | |
{ | |
selectedItemTimer = new Timer(SelectedItemTimerCallback, null, timerDelayWhenSliding, timerDelayWhenSliding); | |
} | |
} | |
public void Dispose() | |
{ | |
Dispose(true); | |
GC.SuppressFinalize(this); | |
} | |
protected virtual void Dispose(bool flag) | |
{ | |
selectedItemTimer.Dispose(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment