-
Notifications
You must be signed in to change notification settings - Fork 20
/
MainPageScrollingAnimationWithComponent.cs
150 lines (126 loc) · 4.63 KB
/
MainPageScrollingAnimationWithComponent.cs
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
using MauiReactor;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CollectionViewTestApp.Pages;
class MainPageScrollingAnimationWithComponentState
{
public ObservableCollection<IndexedPersonWithAddress> Persons { get; set; }
}
class MainPageScrollingAnimationWithComponent : Component<MainPageScrollingAnimationWithComponentState>
{
event EventHandler<double> Scrolled;
private static List<IndexedPersonWithAddress> GenerateSamplePersons(int count)
{
var random = new Random();
var firstNames = new[] { "John", "Jim", "Joe", "Jack", "Jane", "Jill", "Jerry", "Jude", "Julia", "Jenny" };
var lastNames = new[] { "Brown", "Green", "Black", "White", "Blue", "Red", "Gray", "Smith", "Doe", "Jones" };
var cities = new[] { "New York", "London", "Sidney", "Tokyo", "Paris", "Berlin", "Mumbai", "Beijing", "Cairo", "Rio" };
var persons = new List<IndexedPersonWithAddress>();
for (int i = 0; i < count; i++)
{
var firstName = firstNames[random.Next(0, firstNames.Length)];
var lastName = lastNames[random.Next(0, lastNames.Length)];
var age = random.Next(20, 60);
var city = cities[random.Next(0, cities.Length)];
var address = $"{city} No. {random.Next(1, 11)} Lake Park";
persons.Add(new IndexedPersonWithAddress(i, firstName, lastName, age, address));
}
return persons;
}
protected override void OnMounted()
{
State.Persons = new ObservableCollection<IndexedPersonWithAddress>(GenerateSamplePersons(100));
base.OnMounted();
}
public override VisualNode Render()
{
return new ContentPage
{
new CollectionView()
.ItemsSource(State.Persons, RenderItem)
.OnScrolled((s,e) =>
{
Scrolled?.Invoke(s, e.VerticalOffset);
System.Diagnostics.Debug.WriteLine($"Scroll {e.VerticalOffset}");
})
};
}
private VisualNode RenderItem(IndexedPersonWithAddress item)
=> new PersonComponent()
.WhenScroll(handler => Scrolled += handler)
.Item(item);
}
class PersonComponentState
{
public double ScrollY { get; set; }
}
class PersonComponent : Component<PersonComponentState>
{
IndexedPersonWithAddress _item;
private Action<EventHandler<double>> _subscribeToScrollEvent;
readonly double _itemSize = 128;
public PersonComponent Item(IndexedPersonWithAddress item)
{
_item = item;
return this;
}
public PersonComponent WhenScroll(Action<EventHandler<double>> subscribeToScrollEvent)
{
_subscribeToScrollEvent = subscribeToScrollEvent;
return this;
}
protected override void OnMounted()
{
//System.Diagnostics.Debug.WriteLine($"OnMounted (Item {_item.Index})");
_subscribeToScrollEvent?.Invoke(OnParentScrolled);
base.OnMounted();
}
void OnParentScrolled(object sender, double verticalOffset)
{
SetState(s => s.ScrollY = verticalOffset);
}
public override VisualNode Render()
{
//System.Diagnostics.Debug.WriteLine($"Render (Item {_item.Index})");
double GetPercOffset()
{
var itemScrollY = _item.Index * _itemSize;
if (itemScrollY < State.ScrollY - _itemSize)
{
return 0.0;
}
else if (itemScrollY > State.ScrollY + _itemSize)
{
return 1.0;
}
return (itemScrollY - (State.ScrollY - _itemSize)) / (_itemSize * 2);
}
return new Border
{
new VStack()
{
new Border()
.BackgroundColor(Colors.Blue)
.WidthRequest(50)
.HeightRequest(50)
.VCenter()
.HCenter()
.ScaleX(() => 1.0 + GetPercOffset()),
new Label($"Item {_item.Index}")
.TextColor(Colors.White)
.Center()
}
}
.StrokeThickness(0)
.StrokeCornerRadius(34, 34, 0, 0)
.HeightRequest(_itemSize)
.BackgroundColor(Colors.BlueViolet)
//.ScaleX(() => 0.5 + GetPercOffset() * 0.5)
.Opacity(() => 0.2 + GetPercOffset() * 0.8)
;
}
}