c# - 如何使用 Xamarin 表单将图像放置在框架的一半中
问题描述
我想在我的应用程序的半帧中放置一个图像,我正在使用 xamarin 表单来执行此操作,我该怎么做
我的 Xaml
<StackLayout HorizontalOptions = "FillAndExpand" VerticalOptions="StartAndExpand" >
<ListView x:Name="lv_search" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" RowHeight="175" SeparatorColor="White">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<AbsoluteLayout HorizontalOptions = "FillAndExpand" VerticalOptions="StartAndExpand" >
<Frame BackgroundColor = "White" HorizontalOptions="FillAndExpand" VerticalOptions="StartAndExpand" Margin="20,10,0,0"
HeightRequest="75" AbsoluteLayout.LayoutBounds="0.01,0.9,1,1" AbsoluteLayout.LayoutFlags="All">
<Image Source = "img_frm" BackgroundColor="#14559a" AbsoluteLayout.LayoutBounds="0.009,0.9,0.3,0.6" AbsoluteLayout.LayoutFlags="All" />
<StackLayout Orientation = "Horizontal" HorizontalOptions="FillAndExpand" VerticalOptions="CenterAndExpand">
<AbsoluteLayout HorizontalOptions = "StartAndExpand" >
<Image Source="ellipse_1" VerticalOptions="CenterAndExpand" HorizontalOptions="Start" AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0.01,0.4,1,1" HeightRequest="100" WidthRequest="100" BackgroundColor="White"/>
<Image Source = "{Binding Image}" AbsoluteLayout.LayoutBounds="0.02,0.4,1,1" AbsoluteLayout.LayoutFlags="All"
HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" ></Image>
</AbsoluteLayout>
<Label x:Name="lbl_categories" HorizontalOptions="FillAndExpand" VerticalOptions="CenterAndExpand" Margin="10,0,0,0"
TextColor="Black" Text="{Binding Title}" LineBreakMode="WordWrap" HorizontalTextAlignment="Start"
FontSize="Medium" FontAttributes="Bold" AbsoluteLayout.LayoutBounds="0.3,0.3,1,1" AbsoluteLayout.LayoutFlags="All"/>
<Image HorizontalOptions = "EndAndExpand" VerticalOptions="Center" Source="arrow" AbsoluteLayout.LayoutBounds="0.9,0.3,0.3,0.3"
AbsoluteLayout.LayoutFlags="All" />
</StackLayout>
</Frame>
</AbsoluteLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
但它并没有开发出我想要的设计。
其实我想要这样的设计
但是我得到了这样的设计,如何将设计修改为上图
解决方案
我讨厌这样说,但是对于您想要达到的结果,您的 xaml 是一场噩梦。不仅因为您的可视化树中有过多的元素,还因为您在 ListView 中使用了 AbsoluteLayout。
尽管这在技术上是可行的,但它会导致您的应用程序性能下降,尤其是当您的 ListView 填充了很多项目时。
其次,为那个蓝色方块创建一个图像也是一种内存浪费,并且会导致更多的性能下降,如果您的 ListView 包含许多条目,最终可能会导致 Android 上的 OutOfMemoryExceptions。
您可以将其替换为从框视图继承的自定义视图,并使用自定义渲染器来渲染圆角。
还要避免在 ListView 中使用 StackLayout,因为它也会导致性能问题,因为 StackLayout 在布局时会进行大量计算。
正如 Dennis 已经提到的,您要走的路是使用 Grid 进行布局,请记住,添加到网格中的所有元素将按照它们在 xaml 定义中的添加顺序相互叠加。
尤其是在使用 ListViews 时,尽量少用元素,避免需要大量布局传递的元素。
尽管我在示例中没有使用它,但我想添加一些信息,即您也可以使用负边距值进行高级元素定位。
这是一个简短的示例,我一起破解:
<ListView VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" RowHeight="80">
<ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<!-- quick hack to make the list view populate items without having to write model classes -->
<x:String>Entry 1</x:String>
<x:String>Entry 2</x:String>
<x:String>Entry 3</x:String>
<x:String>Entry 4</x:String>
</x:Array>
</ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" >
<BoxView BackgroundColor="LightGray" Margin="19,9,9,9" />
<Grid Margin="20,10,10,10" BackgroundColor="White">
<Label Text="{Binding .}" VerticalOptions="Center" FontSize="18" Margin="25,0,0,0"/>
<!-- insert icons, labels, etc here -->
</Grid>
<customs:RoundedBoxView BackgroundColor="DarkBlue" CornerRadius="6" WidthRequest="15" VerticalOptions="FillAndExpand" HorizontalOptions="Start" Margin="10,20,0,20" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
RoundedBoxView 类如下所示:
public class RoundedBoxView : BoxView
{
readonly BindableProperty CornerRadiusProperty = BindableProperty.Create("CornerRadius", typeof(double), typeof(double), 0.0);
public double CornerRadius
{
get { return (double)GetValue(CornerRadiusProperty); }
set { SetValue(CornerRadiusProperty, value); }
}
}
这将是 android 的自定义渲染器:
[assembly: ExportRenderer(typeof(RoundedBoxView), typeof(RoundedBoxViewRenderer))]
namespace TestApp.Droid
{
public class RoundedBoxViewRenderer : BoxRenderer
{
public RoundedBoxViewRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<BoxView> e)
{
base.OnElementChanged(e);
SetWillNotDraw(false);
Invalidate();
}
public override void Draw(Canvas canvas)
{
var box = Element as RoundedBoxView;
var rect = new Rect();
var paint = new Paint()
{
Color = box.BackgroundColor.ToAndroid(),
AntiAlias = true,
};
GetDrawingRect(rect);
var radius = (float)(box.CornerRadius);
canvas.DrawRoundRect(new RectF(rect), radius, radius, paint);
}
}
对于 iOS:
[assembly: ExportRenderer(typeof(RoundedBoxView), typeof(RoundedBoxViewRenderer))]
namespace TestApp.iOS
{
public class RoundedBoxViewRenderer: BoxRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<BoxView> e)
{
base.OnElementChanged(e);
if (Element != null)
{
Layer.MasksToBounds = true;
UpdateCornerRadius(e.NewElement as RoundedBoxView);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == CircleView.WidthProperty.PropertyName || e.PropertyName == CircleView.HeightProperty.PropertyName)
{
UpdateCornerRadius(Element as RoundedBoxView);
}
}
void UpdateCornerRadius(RoundedBoxView box)
{
Layer.CornerRadius = (nfloat)(box.CornerRadius);
CGRect bounds = new CGRect(0, 0, box.Width, box.Width);
Layer.Bounds = bounds;
Layer.Frame = bounds;
}
}
这将呈现如下:
推荐阅读
- arrays - 将 2 个数组数据类型列转换为 Snowflake 中的行
- mysql - mariadb 无法远程连接,或者如果提供了 IP,则无法从同一台机器连接
- string - Rust 中的 `str` 有什么用处吗?
- macos - “STM32CubeIDE”已损坏,无法打开。你应该把它移到废纸篓。(在 Mac 上)
- oracle - 从 Oracle 中的 Timestamp 数据类型列中删除数据不起作用
- python - 模式匹配与 Python 中的字符/数字模式
- vue.js - Vue 组件在部署后不渲染插槽内容
- kdb - KDB 中的分页选项
- vhdl - VHDL 错误 - 未解决的信号“dec”是多重驱动的,这个错误是什么?
- python - pip 安装成功但命令不起作用