如何使用Xamarin表单将图像放置在半帧中

时间:2018-06-21 06:52:50

标签: c# listview xamarin.forms relativelayout

我想在我的应用中将图像放置在半帧中,我正在使用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>

但是它并没有开发出我想要的设计。

实际上我想要这样的设计

enter image description here

但是我得到这样的设计,如何将设计修改成上面的图像

enter image description here

2 个答案:

答案 0 :(得分:3)

我不想这么说,但是对于您想要实现的结果,您的xaml是一场噩梦。不仅因为视觉树中元素过多,而且还因为在ListView中使用AbsoluteLayout。

即使从技术上讲这是可行的,但它仍会导致您的应用程序性能下降,尤其是在ListView中填充了很多项目的情况下。

第二,为该蓝色正方形创建图像也会浪费内存,并且会导致更多性能下降,并且如果ListView包含许多条目,最终可能会导致Android出现OutOfMemoryExceptions。

您可以将其替换为从框视图继承的自定义视图,并使用自定义渲染器渲染圆角。

还避免在ListView中使用StackLayout,因为这也会导致性能问题,因为StackLayout在进行布局时会进行大量计算。

正如丹尼斯已经提到的,您要走的路是牢记使用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;
    }
}

哪个会这样渲染:

enter image description here}

答案 1 :(得分:1)

您可以使用Grid代替AbsoluteLayout

我没有对此进行测试,但是尝试如下操作:

<Grid 
    HorizontalOptions="FillAndExpand" 
    VerticalOptions="StartAndExpand">
    <Frame 
        Grid.Row="0"
        Grid.Column="0"
        BackgroundColor="White" 
        HorizontalOptions="FillAndExpand" 
        VerticalOptions="StartAndExpand" 
        Margin="20,10,0,0"
        HeightRequest="75">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"></ColumnDefinition>
                <ColumnDefinition Width="Auto"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="Auto"></ColumnDefinition>
            </Grid.ColumnDefinitions>

            <Image 
                Grid.Row="0"
                Grid.Column="0"
                Source="ellipse_1" 
                VerticalOptions="CenterAndExpand" 
                HorizontalOptions="Start" 
                HeightRequest="100" 
                WidthRequest="100" 
                BackgroundColor="White">
            </Image>
            <Image 
                Grid.Row="0"
                Grid.Column="1"
                Source="{Binding Image}" 
                HorizontalOptions="CenterAndExpand" 
                VerticalOptions="CenterAndExpand">
            </Image>
            <Label 
                Grid.Row="0"
                Grid.Column="2"
                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">
            </Label>
            <Image 
                Grid.Row="0"
                Grid.Column="3" 
                HorizontalOptions="EndAndExpand" 
                VerticalOptions="Center" 
                Source="arrow">
            </Image>
        </Grid>
    </Frame>
    <Image 
        Margin="10,10,0,0"
        Grid.Row="0"
        Grid.Column="0"
        Source="img_frm" 
        BackgroundColor="#14559a">
    </Image>
</Grid>

由于Image是在您的XML中的Frame之后创建的,因此它与Frame重叠。您可能需要根据需要更改Frame和蓝色方形Image的边距。