Xamarin.Forms 仿照京东搜索记录控件
Xamarin.Forms 仿照京东搜索记录控件
在项目中遇到这样一个需求,仿照京东搜索记录。在Xamarin.Forms中有什么控件可以实现呢?
首先,来分析这个控件的特点:
- 数据量不大
- 每条记录字数长度不一,使得每条记录呈现的样式长度不一
经过如上分析,由于数据量不大,且界面样式并不是整齐划一,所以用不着使用ListView,查看官方文档后,发现FlexLayout即可满足我们的需求。
FlexLayout这个控件的详细说明可以看微软的官方文档。
这里主要利用了FlexLayout的一些相关特性:
- AlignContent
- AlignItems
- JustifyContent
- Wrap
demo如下代码所示:
public class FlowLayout: StackLayout
{
private FlexLayout _flexLayout;
public Action<int, object> ItemTapped;
public FlowLayout()
{
_flexLayout = new FlexLayout
{
AlignContent = FlexAlignContent.Start,
AlignItems = FlexAlignItems.Start,
JustifyContent = FlexJustify.Start,
Wrap = FlexWrap.Wrap,
};
this.Children.Add(_flexLayout);
}
#region BindableProperty
public static readonly BindableProperty ItemsSourceProperty =
BindableProperty.Create(nameof(ItemsSource), typeof(IList), typeof(FlowLayout), default(IList),propertyChanged: ItemsSourcePropertyChanged);
private static void ItemsSourcePropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
if (bindable is FlowLayout view)
{
view.UpdateViews();
}
}
public IList ItemsSource
{
get { return (IList)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
#endregion
public void UpdateViews()
{
_flexLayout.Children.Clear();
foreach(var item in ItemsSource)
{
_flexLayout.Children.Add(CreateItem(item.ToString()));
}
}
private StackLayout CreateItem(string content)
{
var label = new Label
{
Text = content,
TextColor = Color.Black,
Margin = new Thickness(10,6,10,6), FontSize = 12,
MaxLines = 1,
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.Center,
};
var stack = new StackLayout()
{
BackgroundColor = Color.LightGray,
Margin = new Thickness(0,6,12,6),
};
stack.Children.Add(label);
var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.Tapped += TapGestureRecognizer_Tapped;
stack.GestureRecognizers.Add(tapGestureRecognizer);
return stack;
}
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
try
{
var index = _flexLayout.Children.IndexOf(sender as StackLayout);
var o = ItemsSource[index];
ItemTapped?.Invoke(index, o);
}
catch { }
}
}
效果图:
这样就基本实现了搜索记录。