8000 implemented accordion · githubxiaoa/AccordionView@8dbbe0f · GitHub
[go: up one dir, main page]

Skip to content

Commit 8dbbe0f

Browse files
committed
implemented accordion
1 parent 5b89270 commit 8dbbe0f

File tree

3 files changed

+215
-108
lines changed

3 files changed

+215
-108
lines changed

Accordion/Accordion.cs

Lines changed: 44 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -8,135 +8,71 @@
88

99
namespace Accordion
1010
{
11-
public class ExpendableView : ContentView
11+
public class ShoppingCart
1212
{
13-
private bool _isExpended;
14-
15-
public ExpendableView(ScrollView parent)
16-
: this(async (view) => { await parent.ScrollToAsync(0, view.Y, true)< 8000 span class=pl-kos>; })
17-
{ }
18-
19-
20-
public ExpendableView(Action<ContentView> onSelected)
21-
{
22-
var header = new AbsoluteLayout {
23-
BackgroundColor = Color.FromHex("0067B7")
24-
};
25-
var icon =
26-
new Image
27-
{
28-
Source = ImageSource.FromFile("ic_keyboard_arrow_right_white_24dp.png"),
29-
VerticalOptions = LayoutOptions.Center
30-
};
31-
header.Children.Add(icon, new Rectangle(0, 1, .1, 1), AbsoluteLayoutFlags.All);
32-
header.Children.Add(
33-
new Label
34-
{
35-
Text = "October",
36-
TextColor = Color.White,
37-
BackgroundColor = Color.FromHex("0067B7"),
38-
VerticalTextAlignment = TextAlignment.Center,
39-
HeightRequest = 50
40-
},
41-
new Rectangle(1, 1, .9, 1),
42-
AbsoluteLayoutFlags.All);
43-
44-
var list =
45-
new StackLayout
46-
{
47-
Children = {
48-
new Label { Text = "Hello", HeightRequest = 30 },
49-
new Label { Text = "Hello", HeightRequest = 30 },
50-
new Label { Text = "Hello", HeightRequest = 30 },
51-
new Label { Text = "Hello", HeightRequest = 30 },
52-
new Label { Text = "Hello", HeightRequest = 30 },
53-
new Label { Text = "Hello", HeightRequest = 30 },
54-
new Label { Text = "Hello", HeightRequest = 30 },
55-
new Label { Text = "Hello", HeightRequest = 30 },
56-
new Label { Text = "Hello", HeightRequest = 30 }
57-
},
58-
HeightRequest = 0,
59-
60-
};
61-
62-
var layout =
63-
new StackLayout
64-
{
65-
Spacing = 0,
66-
Children = {
67-
header,
68-
list
69-
}
70-
};
13+
public DateTime Date { get; set; }
14+
public double Amount { get; set; }
15+
}
7116

72-
header.GestureRecognizers.Add(
73-
new TapGestureRecognizer
74-
{
75-
Command = new Command(() =>
76-
{
77-
if (_isExpended)
78-
{
79-
list.HeightRequest = 0;
80-
icon.Source = ImageSource.FromFile("ic_keyboard_arrow_right_white_24dp.png");
81-
_isExpended = false;
82-
}
83-
else
84-
{
85-
list.HeightRequest = list.Children.Count * 30;
86-
icon.Source = ImageSource.FromFile("ic_keyboard_arrow_down_white_24dp.png");
87-
onSelected(this);
88-
_isExpended = true;
89-
}
90-
})
91-
}
92-
);
17+
public class Section
18+
{
19+
public string Title { get; set; }
20+
public IEnumerable<ShoppingCart> List { get; set; }
21+
}
9322

94-
this.Content = layout;
95-
}
23+
public class ViewModel
24+
{
25+
public IEnumerable<Section> List { get; set; }
9626
}
9727

9828
public class AccordionViewPage : ContentPage
9929
{
10030
public AccordionViewPage()
10131
{
102-
var scrollView = new ScrollView();
32+
this.Title = "Accordion";
10333

104-
var layout =
105-
new StackLayout
106-
{
107-
Spacing = 1,
108-
Children = {
109-
new ExpendableView(scrollView),
110-
new ExpendableView(scrollView),
111-
new ExpendableView(scrollView),
112-
new ExpendableView(scrollView),
113-
new ExpendableView(scrollView),
114-
new ExpendableView(scrollView),
115-
new ExpendableView(scrollView),
116-
new ExpendableView(scrollView),
117-
new ExpendableView(scrollView),
118-
new ExpendableView(scrollView),
119-
new ExpendableView(scrollView),
120-
new ExpendableView(scrollView),
121-
new ExpendableView(scrollView)
122-
}
123-
};
34+
var template = new DataTemplate(() =>
35+
{
36+
var layout = new AbsoluteLayout { Padding = 5 };
37+
var title = new Label { HorizontalTextAlignment = TextAlignment.Start };
38+
var price = new Label { HorizontalTextAlignment = TextAlignment.End };
39+
layout.Children.Add(title, new Rectangle(0, 1, 0.5, 1), AbsoluteLayoutFlags.All);
40+
layout.Children.Add(price, new Rectangle(0, 1, 0.5, 1), AbsoluteLayoutFlags.All);
41+
title.SetBinding(Label.TextProperty, "Date", stringFormat: "{0:dd MMM yyyy}");
42+
price.SetBinding(Label.TextProperty, "Amount", stringFormat: "{0:C2}");
43+
return (object)layout;
44+
});
12445

125-
scrollView.Content = layout;
46+
var view = new AccordionView(template);
47+
view.SetBinding(AccordionView.ItemsSourceProperty, "List");
48+
view.Template.SetBinding(AccordionSectionView.TitleProperty, "Title");
49+
view.Template.SetBinding(AccordionSectionView.ItemsSourceProperty, "List");
12650

127-
this.Title = "Accordion";
128-
this.Content = scrollView;
51+
view.BindingContext =
52+
new ViewModel
53+
{
54+
List = new List<Section> {
55+
new Section
56+
{
57+
Title = "October",
58+
List = new List<ShoppingCart> {
59+
new ShoppingCart { Date = DateTime.UtcNow, Amount = 10.05 }
60+
}
61+
}
62+
}
63+
};
64+
this.Content = view;
12965
}
13066
}
13167

13268
public class App : Application
13369
{
13470
public App()
13571
{
136-
var page =
72+
var page =
13773
new TabbedPage
13874
{
139-
Children = {
75+
Children = {
14076
new AccordionViewPage(),
14177
new CustomViewTestPage()
14278
}

Accordion/Accordion.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
<Compile Include="Accordion.cs" />
3232
<Compile Include="Properties\AssemblyInfo.cs" />
3333
<Compile Include="CustomViewTestPage.cs" />
34+
<Compile Include="AccordionView.cs" />
3435
</ItemGroup>
3536
<ItemGroup>
3637
<Reference Include="Xamarin.Forms.Core">

Accordion/AccordionView.cs

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
using System;
2+
using System.Diagnostics;
3+
using System.Linq;
4+
using System.Collections;
5+
using System.Collections.Generic;
6+
using System.Windows.Input;
7+
using Xamarin.Forms;
8+
9+
namespace Accordion
10+
{
11+
public class AccordionView : ScrollView
12+
{
13+
private StackLayout _layout = new StackLayout();
14+
15+
public DataTemplate Template { get; set; }
16+
public DataTemplate SubTemplate { get; set; }
17+
18+
public static readonly BindableProperty ItemsSourceProperty =
19+
BindableProperty.Create(
20+
propertyName: "ItemsSource",
21+
returnType: typeof(IList),
22+
declaringType: typeof(AccordionSectionView),
23+
defaultValue: default(IList),
24+
propertyChanged: AccordionView.PopulateList);
25+
26+
public IList ItemsSource
27+
{
28+
get { return (IList)GetValue(ItemsSourceProperty); }
29+
set { SetValue(ItemsSourceProperty, value); }
30+
}
31+
32+
public AccordionView(DataTemplate itemTemplate)
33+
{
34+
this.SubTemplate = itemTemplate;
35+
this.Template = new DataTemplate(() => (object)(new AccordionSectionView(itemTemplate, this)));
36+
}
37+
38+
void PopulateList()
39+
{
40+
_layout.Children.Clear();
41+
42+
var template = (View)this.Template.CreateContent();
43+
foreach (object item in this.ItemsSource)
44+
{
45+
template.BindingContext = item;
46+
_layout.Children.Add(template);
47+
}
48+
}
49+
50+
static void PopulateList(BindableObject bindable, object oldValue, object newValue)
51+
{
52+
if (oldValue == newValue) return;
53+
((AccordionView)bindable).PopulateList();
54+
}
55+
}
56+
57+
public class AccordionSectionView : ContentView
58+
{
59+
private bool _isExpended = false;
60+
private Color _headerColor = Color.FromHex("0067B7");
61+
private ImageSource _arrowRight = ImageSource.FromFile("ic_keyboard_arrow_right_white_24dp.png");
62+
private ImageSource _arrowDown = ImageSource.FromFile("ic_keyboard_arrow_down_white_24dp.png");
63+
private StackLayout _list = new StackLayout();
64+
private AbsoluteLayout _header = new AbsoluteLayout();
65+
private Image _headerIcon = new Image { VerticalOptions = LayoutOptions.Center };
66+
private Label _headerTitle = new Label { TextColor = Color.White, VerticalTextAlignment = TextAlignment.Center, HeightRequest = 50 };
67+
private DataTemplate _template;
68+
69+
public static readonly BindableProperty ItemsSourceProperty =
70+
BindableProperty.Create(
71+
propertyName: "ItemsSource",
72+
returnType: typeof(IList),
73+
declaringType: typeof(AccordionSectionView),
74+
defaultValue: default(IList),
75+
propertyChanged: AccordionSectionView.PopulateList);
76+
77+
public IList ItemsSource
78+
{
79+
get { return (IList)GetValue(ItemsSourceProperty); }
80+
set { SetValue(ItemsSourceProperty, value); }
81+
}
82+
83+
public static readonly BindableProperty TitleProperty =
84+
BindableProperty.Create(
85+
propertyName: "Title",
86+
returnType: typeof(string),
87+
declaringType: typeof(AccordionSectionView),
88+
propertyChanged: AccordionSectionView.ChangeTitle);
89+
90+
public string Title
91+
{
92+
get { return (string)GetValue(TitleProperty); }
93+
set { SetValue(TitleProperty, value); }
94+
}
95+
96+
public AccordionSectionView(DataTemplate itemTemplate, ScrollView parent)
97+
{
98+
_template = itemTemplate;
99+
_headerTitle.BackgroundColor = _headerColor;
100+
_headerIcon.Source = _arrowRight;
101+
_header.BackgroundColor = _headerColor;
102+
103+
_header.Children.Add(_headerIcon, new Rectangle(0, 1, .1, 1), AbsoluteLayoutFlags.All);
104+
_header.Children.Add(_headerTitle, new Rectangle(1, 1, .9, 1), AbsoluteLayoutFlags.All);
105+
106+
var layout =
107+
new StackLayout
108+
{
109+
Spacing = 0,
110+
Children = {
111+
_header,
112+
_list
113+
}
114+
};
115+
116+
_header.GestureRecognizers.Add(
117+
new TapGestureRecognizer
118+
{
119+
Command = new Command(async () =>
120+
{
121+
if (_isExpended)
122+
{
123+
_headerIcon.Source = _arrowRight;
124+
_list.HeightRequest = 0;
125+
_isExpended = false;
126+
}
127+
else
128+
{
129+
_headerIcon.Source = _arrowDown;
130+
_list.HeightRequest = _list.Children.Count * 30;
131+
_isExpended = true;
132+
await parent.ScrollToAsync(0, layout.Y, true);
133+
}
134+
})
135+
}
136+
);
137+
138+
this.Content = layout;
139+
}
140+
141+
void ChangeTitle()
142+
{
143+
_headerTitle.Text = this.Title;
144+
}
145+
146+
void PopulateList()
147+
{
148+
_list.Children.Clear();
149+
150+
var template = (View)_template.CreateContent();
151+
foreach (object item in this.ItemsSource)
152+
{
153+
template.BindingContext = item;
154+
_list.Children.Add(template);
155+
}
156+
}
157+
158+
static void ChangeTitle(BindableObject bindable, object oldValue, object newValue)
159+
{
160+
if (oldValue == newValue) return;
161+
((AccordionSectionView)bindable).ChangeTitle();
162+
}
163+
164+
static void PopulateList(BindableObject bindable, object oldValue, object newValue)
165+
{
166+
if (oldValue == newValue) return;
167+
((AccordionSectionView)bindable).PopulateList();
168+
}
169+
}
170+
}

0 commit comments

Comments
 (0)
0