【问题标题】:How to place a image in the half of a frame using Xamarin forms如何使用 Xamarin 表单将图像放置在框架的一半中
【发布时间】:2018-06-21 06:52:49
【问题描述】:

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

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

其实我想要这样的设计

但是我得到了这样的设计,如何将设计修改为上图

【问题讨论】:

  • 我不明白你想要什么。你能试着解释一下吗?并显示您(错误)结果的屏幕截图?
  • @DennisSchröer 我更新了我的问题,请你帮帮我。
  • 你的意思是控制图片的大小只占Frame高度的50%?
  • @DennisSchröer 我想将方形蓝色图像替换为框架的一半,如第一个设计所示,

标签: c# listview xamarin xamarin.forms


【解决方案1】:

我不想这么说,但是对于您想要达到的结果,您的 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;
    }
}

会这样渲染:

}

【讨论】:

    【解决方案2】:

    您可以使用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 是在您的 xaml 中的 Frame 之后创建的,所以它与 Frame 重叠。您可能需要根据需要更改Frame 和蓝色方形Image 的边距。

    【讨论】:

    • 我试过了,但是框架隐藏了一半的图像,我想要框架上方的图像
    猜你喜欢
    • 2015-08-13
    • 2022-11-27
    • 1970-01-01
    • 2020-07-19
    • 2015-06-29
    • 2019-04-27
    • 2016-09-19
    • 2018-03-17
    • 1970-01-01
    相关资源
    最近更新 更多