Ячейка Xamarin Forms iOS listview автоматически изменяет размер своего содержимого (изображение из URL) - PullRequest
0 голосов
/ 08 октября 2019

В Xamarin Forms на iOS есть просмотр списка. Клетки состоит из изображения и текста. Изображения имеют разные размеры и соотношение, например, 300х200 и 300х350. Я хочу, чтобы содержимое ячеек автоматически изменяло размер содержимого, чтобы изображения соответствовали ширине всей ячейки, тогда высота ячейки будет автоматически изменяться в зависимости от высоты изображения.

Одним из способов является вычисление высоты строки в зависимости от высоты изображения - это рабочее решение, но оно медленное при загрузке изображений с сервера. Намного более быстрый способ - установить 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 голосов
/ 08 октября 2019

Вы можете обновить высоту ячейки во время выполнения после загрузки удаленного образа. Вам нужно вызвать 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.

...