我正在寻找的功能是可点击的标签,其中文本和位置都是绑定的,并且位置相对于也正在显示的图像。
我已经尝试了AbsoluteLayout
和RelativeLayout
,但标签似乎无法逃脱CollectionView
的限制;也就是说,标签会根据标签的大小在页面上不断迭代。我不在乎标签是否重叠。事实上,如果标签的字体足够大,并且绑定位置足够近,那么重叠标签是肯定的,并且从逻辑上讲,点击事件可能发生在该像素位置上的任何标签上。我没意见。
例如,我想显示一张640x480像素的图像。标签的文本和位置,我想放置在他们需要绑定。这是MockData
的样品。
public MockDataStore()
{
items = new List<Item>()
{
new Item { Id = Guid.NewGuid().ToString(), Text = "A" , Description="My A" , X= 85, Y=130 },
new Item { Id = Guid.NewGuid().ToString(), Text = "B" , Description="My B" , X=140, Y=150 },
new Item { Id = Guid.NewGuid().ToString(), Text = "C" , Description="My C" , X=190, Y=165 },
new Item { Id = Guid.NewGuid().ToString(), Text = "D" , Description="My D" , X=240, Y=175 },
new Item { Id = Guid.NewGuid().ToString(), Text = "E" , Description="My E" , X=290, Y=180 },
new Item { Id = Guid.NewGuid().ToString(), Text = "F" , Description="My F" , X=335, Y=185 }
};
}
这里是我正在尝试的XAML。
<Grid x:Name="grid"
x:DataType="local:ItemsViewModel">
<!--<Image Source="bg.png" Aspect="AspectFit" HorizontalOptions="Start" VerticalOptions="Start" x:Name="bg"/>-->
<RefreshView x:DataType="local:ItemsViewModel"
Command="{Binding LoadItemsCommand}"
IsRefreshing="{Binding IsBusy, Mode=TwoWay}">
<CollectionView x:Name="ItemsListView"
ItemsSource="{Binding Items}"
SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate>
<RelativeLayout Padding="10" x:DataType="model:Item">
<Label Text="{Binding Text}"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=X, Constant={Binding X}}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Y, Constant={Binding Y}}"
BackgroundColor="Transparent"
FontSize="16" />
<RelativeLayout.GestureRecognizers>
<TapGestureRecognizer
NumberOfTapsRequired="1"
Command="{Binding Source={RelativeSource AncestorType={x:Type local:ItemsViewModel}}, Path=ItemTapped}"
CommandParameter="{Binding .}">
</TapGestureRecognizer>
</RelativeLayout.GestureRecognizers>
</RelativeLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</RefreshView>
</Grid>
所发生的是标签的相对位置被放置在页面的递增位置。只要我还能得到ItemTapped
,我就不会嫁给使用CollectionView
。
我也尝试过使用BindableLayout
没有成功,虽然我不确定我理解如何正确使用该类,而且数据源是所有的文本和位置。
我想要完成的是类似于GPS应用程序如何显示地图并覆盖从数据中加载的可点击的兴趣点,并相对于地图中的坐标。
我想要完成的是什么,甚至可能使用Xamarin的XAML?
编辑:我发现RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0, Constant=0}" TranslationX="{Binding X}"
将把标签放在正确的X位置。然而,这个想法不适用于Y位置。CollectionView
在页面中保持Y位置递增。我希望CollectionView
可以设置为不做任何控件的定位,只允许我通过绑定来设置标签的x/y位置。
将标签放置在正确的X位置。但是,这个想法不适用于Y位置。
问题是你在每个中显示标签CollectionView项,但是它们有不同的RelativeLayout父元素。它有足够的宽度来设置Y值,但不能设置X值。
对于这个场景,我们建议您使用BindableLayout
组合条目。例如
<ContentPage.BindingContext>
<local:ItemsViewModel />
</ContentPage.BindingContext>
<RelativeLayout BindableLayout.ItemsSource="{Binding items}">
<BindableLayout.ItemTemplate>
<DataTemplate x:DataType="local:Item">
<Label
BackgroundColor="Transparent"
FontSize="16"
RelativeLayout.XConstraint="{Binding X}"
RelativeLayout.YConstraint="{Binding Y}"
Text="{Binding Text}" />
</DataTemplate>
</BindableLayout.ItemTemplate>
</RelativeLayout>
代码后面
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
}
public class ItemsViewModel
{
public ItemsViewModel()
{
MockDataStore();
}
public List<Item> items { get; set; }
public void MockDataStore()
{
items = new List<Item>()
{
new Item { Id = Guid.NewGuid().ToString(), Text = "A" , Description="My A" ,X = Constraint.Constant(85),Y= Constraint.Constant(130)},
new Item { Id = Guid.NewGuid().ToString(), Text = "B" , Description="My B" ,X = Constraint.Constant(140),Y= Constraint.Constant(150)},
new Item { Id = Guid.NewGuid().ToString(), Text = "C" , Description="My C" ,X = Constraint.Constant(190),Y= Constraint.Constant(165)},
new Item { Id = Guid.NewGuid().ToString(), Text = "D" , Description="My D" ,X = Constraint.Constant(240),Y= Constraint.Constant(175)},
new Item { Id = Guid.NewGuid().ToString(), Text = "E" , Description="My E" ,X = Constraint.Constant(290),Y= Constraint.Constant(180)},
new Item { Id = Guid.NewGuid().ToString(), Text = "F" , Description="My F" ,X = Constraint.Constant(335),Y= Constraint.Constant(185)}
};
}
}
public class Item
{
public string Id { get; internal set; }
public string Text { get; internal set; }
public string Description { get; internal set; }
public Constraint X { get; set; }
public Constraint Y { get; set; }
}