Xamarin Forms iOS listview的单元格会自动调整其内容的大小(URL中的图像)

时间:2019-10-08 07:59:54

标签: ios forms listview xamarin autosize

在iOS端的Xamarin Forms中,有一个listview。单元格由图像和文本组成。图像具有不同的大小和比例f.e. 300x200和300x350。我想使单元格自动调整内容大小,以便图像将适合整个单元格的宽度,然后根据图像的高度自动调整单元格的高度。

一种方法是计算行的高度取决于图像的高度-这是可行的解决方案,但是从服务器加载图像时速度很慢。更快的方法是将ItemsSource设置为图像url,我想采用这种方式。

我正在尝试图像处理,ffimageloading,hasUnevenRows,Aspect,将ffimageloading放入网格,缓存策略,但是图像两侧留有白带,或者图像被裁切,图像很小,滚动后将它们调整为更大的尺寸。

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
             xmlns:ffimageloadingsvg="clr-namespace:FFImageLoading.Svg.Forms;assembly=FFImageLoading.Svg.Forms"
             x:Class="Layout.xxx.Views.iOS.CategoryPage"
             x:Name="CategoryPageName">
    <StackLayout>
        <ListView x:Name="CategoryArticles" SeparatorVisibility="None" ItemsSource="{Binding Articles}" HasUnevenRows="True" CachingStrategy="RetainElement">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Frame  CornerRadius="5" Margin="5,10,5,10" Padding="0">
                            <Grid Margin="0" Padding="0">
                                <StackLayout Margin="0" Orientation="Vertical" HorizontalOptions="FillAndExpand" Grid.Row="0">
                                    <Grid HorizontalOptions="FillAndExpand" Margin="0,0,0,0">
                                        <Grid  Grid.Row="0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"  >
                                            <ffimageloading:CachedImage Margin="0"  Source="{Binding PictureUrl}" Aspect="AspectFit" ErrorPlaceholder="default_image.jpg" DownsampleToViewSize="True" />
                                        </Grid>
                                        <BoxView BackgroundColor="Black" HorizontalOptions="FillAndExpand" Grid.Row="0" />
                                        <Grid HorizontalOptions="FillAndExpand" Margin="5,10,5,10" VerticalOptions="Center" Grid.Row="0" >
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width=".3*"/>
                                                <ColumnDefinition Width="*"/>
                                                <ColumnDefinition Width=".3*"/>
                                            </Grid.ColumnDefinitions>
                                            <ffimageloadingsvg:SvgCachedImage HeightRequest="50" WidthRequest="50" Aspect="AspectFit" Source="minus_article.svg" Grid.Column="0"/>
                                            <Label Text="{Binding Quantity}" TextColor="White" HorizontalOptions="Center" FontSize="50" Margin="10,0,10,0" Grid.Column="1"/>
                                            <ffimageloadingsvg:SvgCachedImage x:Name="AddImage" HeightRequest="50" WidthRequest="50" Aspect="AspectFit" Source="plus.svg" Grid.Column="2"/>
                                        </Grid>
                                    </Grid>
                                    <StackLayout Padding="10" Orientation="Vertical" HorizontalOptions="FillAndExpand">
                                        <Grid HorizontalOptions="FillAndExpand" VerticalOptions="Start">
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="*" />
                                                <ColumnDefinition Width="Auto" />
                                            </Grid.ColumnDefinitions>
                                            <Label Text="{Binding Name}" Margin="0,0,10,0"  HorizontalOptions="StartAndExpand" Grid.Column="0"/>
                                            <Label Text="{Binding PriceLabel}" HorizontalOptions="End" Margin="0,0,5,0" Grid.Column="1"/>
                                        </Grid>
                                    </StackLayout>
                                </StackLayout>
                            </Grid>
                        </Frame>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

您还有其他想法吗?也许可以为ffimageloading定制渲染器?

1 个答案:

答案 0 :(得分:0)

您可以在加载远程图像后在运行时更新单元格的高度。您需要调用cell.ForceUpdateSize();来更新单元格的大小。

因此,我们使用TriggerAction来更改此值,并告诉ViewCell更新其大小。

public class ForceUpdateSizeTriggerAction : TriggerAction<VisualElement>
{
    public static readonly BindableProperty HeighRequestProperty = BindableProperty.Create(
                nameof(HeighRequest),
                typeof(double),
                typeof(ForceUpdateSizeTriggerAction ),
                60);

    public double HeighRequest{
          get { return (double)GetValue (HeighRequestProperty ); }
          set { SetValue (HeighRequestProperty , value); }
    }

    public ForceUpdateSizeTriggerAction() : base()
    {

    }
    protected override void Invoke(VisualElement sender)
    {
        var parent = sender.Parent;
        while (parent != null && !(parent is ViewCell))
        {
            parent = parent.Parent;
        }
        if (parent is ViewCell cell)
        {
            Device.BeginInvokeOnMainThread(() =>
            {
                sender.HeightRequest = HeighRequest;
                cell.ForceUpdateSize();
            });
        }
    }
}
<Grid.Style>
   <Style TargetType="Grid">
      <Setter Property="HeightRequest" Value="60"/>
      <Style.Triggers>
        <DataTrigger TargetType="Grid" Binding="{Binding IsLoadFinished}" Value="True">
            <DataTrigger.EnterActions>
                <local:ForceUpdateSizeTriggerAction HeighRequest="{Binding NewHeight}" />
            </DataTrigger.EnterActions>

            <DataTrigger.ExitActions>
                <local:ForceUpdateSizeTriggerAction HeighRequest="60" />
            </DataTrigger.ExitActions>
        </DataTrigger>
      </Style.Triggers>
   </Style>
</Grid.Style>

您可以在模型中添加 IsLoadFinished NewHeight 。完成从url加载图像后,更改值。