Skip to content

Commit

Permalink
Added ability to swipe between views with setting context by user
Browse files Browse the repository at this point in the history
No need to set Items Context
  • Loading branch information
AndreiMisiukevich committed Jan 23, 2018
1 parent 5655b37 commit 511bc6e
Show file tree
Hide file tree
Showing 6 changed files with 240 additions and 33 deletions.
130 changes: 98 additions & 32 deletions PanCardView/CardsView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@ public class CardsView : AbsoluteLayout
bindable.AsCardView().SetCurrentView();
});

public static readonly BindableProperty CurrentContextProperty = BindableProperty.Create(nameof(CurrentContext), typeof(object), typeof(CardsView), null, BindingMode.OneWay, propertyChanged: (bindable, oldValue, newValue) => {
if(newValue != null && bindable.AsCardView()._currentView == null)
{
bindable.AsCardView().SetCurrentView();
}
});

public static readonly BindableProperty NextContextProperty = BindableProperty.Create(nameof(NextContext), typeof(object), typeof(CardsView), null, BindingMode.OneWay);

public static readonly BindableProperty PrevContextProperty = BindableProperty.Create(nameof(PrevContext), typeof(object), typeof(CardsView), null, BindingMode.OneWay);

public static readonly BindableProperty MoveDistanceProperty = BindableProperty.Create(nameof(MoveDistance), typeof(double), typeof(CardsView), -1.0);

public static readonly BindableProperty IsOnlyForwardDirectionProperty = BindableProperty.Create(nameof(IsOnlyForwardDirection), typeof(bool), typeof(CardsView), false);
Expand All @@ -56,7 +67,7 @@ public class CardsView : AbsoluteLayout

public static readonly BindableProperty MaxChildrenCountProperty = BindableProperty.Create(nameof(MaxChildrenCount), typeof(int), typeof(CardsView), 18);

public static readonly BindableProperty DesiredMaxChildrenCountProperty = BindableProperty.Create(nameof(DesiredMaxChildrenCount), typeof(int), typeof(CardsView), 12);
public static readonly BindableProperty DesiredMaxChildrenCountProperty = BindableProperty.Create(nameof(DesiredMaxChildrenCount), typeof(int), typeof(CardsView), 9);

public static readonly BindableProperty PanStartedCommandProperty = BindableProperty.Create(nameof(PanStartedCommand), typeof(ICommand), typeof(CardsView), null);

Expand Down Expand Up @@ -132,6 +143,24 @@ public CardViewItemFactory ItemViewFactory
set => SetValue(ItemViewFactoryProperty, value);
}

public object CurrentContext
{
get => GetValue(CurrentContextProperty);
set => SetValue(CurrentContextProperty, value);
}

public object NextContext
{
get => GetValue(NextContextProperty);
set => SetValue(NextContextProperty, value);
}

public object PrevContext
{
get => GetValue(PrevContextProperty);
set => SetValue(PrevContextProperty, value);
}

public double MoveDistance
{
get
Expand Down Expand Up @@ -206,7 +235,7 @@ public ICommand PositionChangedCommand

public void OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
if (_itemsCount < 0)
if (_itemsCount < 0 && CurrentContext == null)
{
return;
}
Expand Down Expand Up @@ -234,7 +263,7 @@ public void OnPanUpdated(object sender, PanUpdatedEventArgs e)

private void SetCurrentView()
{
if (Items != null && CurrentIndex < _itemsCount)
if ((Items != null && CurrentIndex < _itemsCount) || CurrentContext != null)
{
_currentView = GetView(CurrentIndex, PanItemPosition.Current);
}
Expand Down Expand Up @@ -312,27 +341,16 @@ private async void OnTouchEnded()

if (absDiff > MoveDistance)
{
var indexDelta = -Math.Sign(CurrentDiff);
if (IsOnlyForwardDirection)
var index = GetNewIndexFromDiff();
if(index < 0)
{
indexDelta = Math.Abs(indexDelta);
}
var newIndex = CurrentIndex + indexDelta;

if (newIndex < 0 || newIndex >= _itemsCount)
{
if (!IsRecycled)
{
return;
}

newIndex = GetRecycledIndex(newIndex);
return;
}

SwapViews();
ShouldIgnoreSetCurrentView = true;

CurrentIndex = newIndex;
CurrentIndex = index;

FirePanEnded(CurrentDiff < 0);

Expand Down Expand Up @@ -376,6 +394,33 @@ await Task.WhenAll(
}
}

private int GetNewIndexFromDiff()
{
if(CurrentContext != null)
{
return 0;
}

var indexDelta = -Math.Sign(CurrentDiff);
if (IsOnlyForwardDirection)
{
indexDelta = Math.Abs(indexDelta);
}
var newIndex = CurrentIndex + indexDelta;

if (newIndex < 0 || newIndex >= _itemsCount)
{
if (!IsRecycled)
{
return - 1;
}

newIndex = GetRecycledIndex(newIndex);
}

return newIndex;
}

private bool TrySetSelectedBackView(double diff)
{
View invisibleView;
Expand Down Expand Up @@ -423,23 +468,11 @@ private void SwapViews()

private View GetView(int index, PanItemPosition panIntemPosition)
{
if(_itemsCount < 0)
var context = GetContext(index, panIntemPosition);
if(context == null)
{
return null;
}

if(index < 0 || index >= _itemsCount)
{
if(!IsRecycled || (panIntemPosition != PanItemPosition.Current && _itemsCount < 2))
{
return null;
}

index = GetRecycledIndex(index);

}

var context = Items[index];

var rule = ItemViewFactory?.GetRule(context);
if(rule == null)
Expand Down Expand Up @@ -478,6 +511,39 @@ private View GetView(int index, PanItemPosition panIntemPosition)
return view;
}

private object GetContext(int index, PanItemPosition panIntemPosition)
{
if (CurrentContext != null)
{
switch (panIntemPosition)
{
case PanItemPosition.Current:
return CurrentContext;
case PanItemPosition.Next:
return NextContext;
case PanItemPosition.Prev:
return PrevContext;
}
}

if (_itemsCount < 0)
{
return null;
}

if (index < 0 || index >= _itemsCount)
{
if (!IsRecycled || (panIntemPosition != PanItemPosition.Current && _itemsCount < 2))
{
return null;
}

index = GetRecycledIndex(index);
}

return Items[index];
}

private void SetBackViewLayerPosition(View view)
{
if(view == null)
Expand Down
9 changes: 9 additions & 0 deletions PanCardView/Factory/CardViewFactoryRule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ namespace PanCardView.Factory
{
public sealed class CardViewFactoryRule
{
public CardViewFactoryRule()
{
}

public CardViewFactoryRule(Func<View> creator)
{
Creator = creator;
}

public Func<View> Creator { get; set; }
}
}
8 changes: 7 additions & 1 deletion PanCardViewSample/PanCardViewSample/PanCardViewSample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,16 @@ public class StartPage : ContentPage
{
public StartPage()
{
var toCardsBtn = new Button { Text = "CardsView" };
var toCardsBtn = new Button { Text = "CardsView Items" };
toCardsBtn.Clicked += (sender, e) => {
this.Navigation.PushAsync(new CardsSampleView());
};

var toCardsBtnCustom = new Button { Text = "CardsView CustomContexts" };
toCardsBtnCustom.Clicked += (sender, e) => {
this.Navigation.PushAsync(new CardsSampleCustomView());
};

var toCarouselBtn = new Button { Text = "CarouselView" };
toCarouselBtn.Clicked += (sender, e) => {
this.Navigation.PushAsync(new CarouselSampleView());
Expand All @@ -29,6 +34,7 @@ public StartPage()
{
Children = {
toCardsBtn,
toCardsBtnCustom,
toCarouselBtn
}
};
Expand Down
2 changes: 2 additions & 0 deletions PanCardViewSample/PanCardViewSample/PanCardViewSample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
<Compile Include="Views\CarouselSampleView.cs" />
<Compile Include="ViewModels\CardSampleViewModel.cs" />
<Compile Include="CardsFactory\RuleHolder.cs" />
<Compile Include="Views\CardsSampleCustomView.cs" />
<Compile Include="ViewModels\SharedSampleCustomViewModel.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\PanCardView\PanCardView.csproj">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using System.Collections.ObjectModel;
using System.ComponentModel;
using Xamarin.Forms;
using System;
using System.Collections.Generic;
using System.Windows.Input;
using System.Linq;

namespace PanCardViewSample.ViewModels
{
public sealed class SharedSampleCustomViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

private int _ImageCount = 500;

private Stack<object> _contextStack = new Stack<object>();

public SharedSampleCustomViewModel()
{
PrevContext = CreateContext();
CurrentContext = CreateContext();
NextContext = CreateContext();

_contextStack.Push(PrevContext);

PanStartedCommand = new Command(() =>
{
if (_contextStack.Any() && PrevContext == null)
{
PrevContext = _contextStack.Peek();
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(PrevContext)));
}
if (NextContext == null)
{
NextContext = new { Source = CreateSource(), Color = CreateColor() };
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(NextContext)));
}

});

PanPositionChangedCommand = new Command((p) =>
{
var isNext = (bool)p;
if(isNext)
{
_contextStack.Push(CurrentContext);
PrevContext = CurrentContext;
CurrentContext = NextContext;
NextContext = CreateContext();
}
else
{
NextContext = CurrentContext;
CurrentContext = PrevContext;
_contextStack.Pop();
PrevContext = _contextStack.Any() ? _contextStack.Peek() : null;
}

PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentContext)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(NextContext)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(PrevContext)));
});
}

public object CurrentContext { get; set; }
public object NextContext { get; set; }
public object PrevContext { get; set; }

public ICommand PanStartedCommand { get; }
public ICommand PanPositionChangedCommand { get; }


private object CreateContext()
{
return new { Source = CreateSource(), Color = CreateColor() };
}

private string CreateSource()
{
return $"http://lorempixel.com/300/300/animals/text{++_ImageCount}/";
}

private Color CreateColor()
{
var rnd = new Random();
return Color.FromRgb(rnd.Next(0, 255), rnd.Next(0, 255), rnd.Next(0, 255));
}
}
}
34 changes: 34 additions & 0 deletions PanCardViewSample/PanCardViewSample/Views/CardsSampleCustomView.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using FFImageLoading.Forms;
using PanCardView;
using PanCardView.Factory;
using Xamarin.Forms;
using PanCardView.Processors;
using PanCardViewSample.ViewModels;
using PanCardViewSample.CardsFactory;

namespace PanCardViewSample.Views
{
public class CardsSampleCustomView : ContentPage
{
public CardsSampleCustomView()
{
var cardsView = new CardsView()
{
ItemViewFactory = new CardViewItemFactory(RuleHolder.Rule),
BackgroundColor = Color.Black.MultiplyAlpha(.9),
IsPanInCourse = true
};

cardsView.SetBinding(CardsView.CurrentContextProperty, nameof(SharedSampleCustomViewModel.CurrentContext));
cardsView.SetBinding(CardsView.NextContextProperty, nameof(SharedSampleCustomViewModel.NextContext));
cardsView.SetBinding(CardsView.PrevContextProperty, nameof(SharedSampleCustomViewModel.PrevContext));

cardsView.SetBinding(CardsView.PanStartedCommandProperty, nameof(SharedSampleCustomViewModel.PanStartedCommand));
cardsView.SetBinding(CardsView.PositionChangedCommandProperty, nameof(SharedSampleCustomViewModel.PanPositionChangedCommand));

Title = "CardsView";
Content = cardsView;
BindingContext = new SharedSampleCustomViewModel();
}
}
}

0 comments on commit 511bc6e

Please sign in to comment.