水平ListView Xamarin.Forms

时间:2014-06-20 14:39:20

标签: c# listview xamarin xamarin.forms

是否可以在 ListView 中创建horizontal scroll Xamarin.Forms,如图片

ListView Horizontal

这是我为垂直

所做的
var myListView = new ListView
{
    ItemTemplate = new DataTemplate(typeof(ImageCell))
};

14 个答案:

答案 0 :(得分:11)

是的,你在技术上可以。将“旋转”设置为270(所有VisualElements都具有“旋转BindableProperty”)。然而,这看起来像一个次优解决方案,因为顶部和底部都有空白区域,您必须左右拖动视图才能完全看到所有内容。

public static readonly BindableProperty RotationProperty;
public static readonly BindableProperty RotationXProperty;
public static readonly BindableProperty RotationYProperty;

上面的代码来自VisualElement类。下面的代码是我自己的一小部分样本。

                                              ∨∨∨                                                  
<ListView x:Name="MessagesListView" Rotation="270" ItemsSource="{Binding Items}" RowHeight="40">
  <ListView.ItemTemplate>
    <DataTemplate>
      <ViewCell>
        <ViewCell.View>
          <StackLayout>
            <!--mylayouthere-->
          </StackLayout>
        </ViewCell.View>
      </ViewCell>
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>

答案 1 :(得分:10)

正如其他人所说的那样,不 - Xamarin.Forms 中没有开箱即用的。

然而 - 它并没有阻止任何人编写自己的自定义渲染器来实现这种控制。

正如 Stephane Delcroix 所提到的,你可以创建一个 ScrollView ,然后创建一个 StackLayout 来创建相同的效果。

然后您需要实施: -

*)可绑定属性以接受需要创建的( IEnumerable ItemsSource 属性。

*) bindable property 以接受需要创建的( DataTemplate ItemTemplate 属性。

*)绑定代码,用于实例化 ItemTemplate 的实例,获取特定数据源项并将其呈现为 StackLayout 。您还必须考虑删除的项目等。

*)附加事件处理程序/点击手势以选择项目。

*)实施选定状态/停用其他所选项目。

......等等,以获得完整的实施。

以上所有问题都是对于相对较小的项目清单来说很好。

但是,如果您要查找很长的条目列表,那么在您创建所有视图之前,上面会有点不受欢迎。

即使你延迟加载,你仍然需要考虑所有视图内存占用

然后引入另一个可能的实施,处理虚拟物品,这是一个完全不同的故事。

答案 2 :(得分:10)

如上所述,没有标准的方法可以做到这一点,但是有一种方法可以使用标准ListView和@MillieSmiths方法。

该解决方案需要多层嵌套布局。从ListViewwe开始将旋转270度,但是也会旋转我们的项目内容,因此我们需要将其向后旋转90度。

旋转ListView创建了大量的空白,通过将ListView包装在绝对布局中我们可以解决这个问题(我们需要额外的内容视图来修复一些剪辑问题)。

最后在代码隐藏中我们需要渲染布局剪辑

看到完整的解决方案:

<AbsoluteLayout x:Name="MessagesLayoutFrame" Padding="0" HorizontalOptions="FillAndExpand">
  <ContentView x:Name="MessagesLayoutFrameInner"  Padding="0"  HorizontalOptions="FillAndExpand">
    <ListView x:Name="MessagesListView"
              ItemsSource="{Binding Images}"
              RowHeight="240"
              VerticalOptions="Start"
              HeightRequest="240"
              WidthRequest="240"
              SeparatorVisibility="None"
              Rotation="270"
              HorizontalOptions="Center">
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <ContentView Rotation="90" Padding="12">
              <Image Source="{Binding Source}" Aspect="AspectFill" />
            </ContentView>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>
  </ContentView>
</AbsoluteLayout>

对于背后的代码,我们只需要检查我们之前是否已经设置好了,如果有的话,就放手吧。基本上我们发现页面的宽度是什么(NameGrid只是其他地方的全宽容器)然后将直接ListView容器向上移动一半的空白,并将其剪切到底部的另一半)

    bool hasAppearedOnce = false;
    protected override void OnAppearing() {
        base.OnAppearing();

        if (!hasAppearedOnce) {

            hasAppearedOnce = true;
            var padding = (NameGrid.Width - MessagesListView.Height) / 2;

            MessagesListView.HeightRequest = MessagesLayoutFrame.Width;
            MessagesLayoutFrameInner.WidthRequest = MessagesLayoutFrame.Width;
            MessagesLayoutFrameInner.Padding = new Thickness(0);
            MessagesLayoutFrame.Padding = new Thickness(0);
            MessagesLayoutFrame.IsClippedToBounds = true;
            Xamarin.Forms.AbsoluteLayout.SetLayoutBounds(MessagesLayoutFrameInner, new Rectangle(0, 0 - padding, AbsoluteLayout.AutoSize, MessagesListView.Height - padding));
            MessagesLayoutFrameInner.IsClippedToBounds = true;
             // */
        } 
    }

警告 不要使用<FRAMES>来移动和旋转布局。它将在Windows Phone上崩溃。

P.S 我相信这可以包含在一个很好的UserControl中,供所有人使用。

答案 3 :(得分:8)

从Xamarin Forms 2.3开始CarouselView就是这样,等等。阅读更多here

<ContentView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
  <CarouselView ItemsSource="{Binding MyDataSource}">
    <CarouselView.ItemTemplate>
      <DataTemplate>
        <Label Text="{Binding LabelText}" />
      </DataTemplate>
    </CarouselView.ItemTemplate>
  </CarouselView>
</ContentView>

答案 4 :(得分:7)

就像其他人所说的那样,ListView不可能,我认为Xamarin对Forms有很大的疏忽。我们需要动态显示数据驱动对象,而不仅仅是列表中的内容....来吧你好!

但是,在Xamarin Labs项目中,您可以使用GridView。它仍然有点粗糙,人们正在通过选择项目来解决一些错误。

https://github.com/XForms/Xamarin-Forms-Labs

似乎某人似乎有解决这个问题的方法:

https://github.com/XForms/Xamarin-Forms-Labs/issues/236

答案 5 :(得分:6)

不,没有办法让水平ListView。您可以将水平StackLayout包装在水平ScrollView中以获得相同的视觉效果,但这并不完全相同,因为您没有DataTemplating。

答案 6 :(得分:3)

我没试过,但这可能值得一试。

https://github.com/Cheesebaron/Cheesebaron.HorizontalListView

答案 7 :(得分:2)

我已经尝试了上面提到的&#34;旋转&#34;解决方案,除了它是一个丑陋的&#34;解决方案,它还带有几个限制

  1. 列表视图WidthRequest必须与HeightRequest
  2. 相同
  3. listView行高不再正常,因为它变为单元格宽度
  4. verticalalign变为horizo​​ntalalign等,不太可维护。
  5. 更好的选择是制作自己的自定义控件,或者像我一样,使用现有的Horizo​​ntalListView https://www.nuget.org/packages/HorizontalListView1.1/这个很容易使用。您可以找到源代码和文档here

    实现:

    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
        x:Class="test.ListPage" 
        xmlns:Controls="clr-namespace:HorizontalList;assembly=HorizontalList"> 
    
    <Controls:HorizontalListView ItemsSource="{Binding Categories}" ListOrientation="Horizontal"> 
      <Controls:HorizontalListView.ItemTemplate> 
        <DataTemplate> 
        <Label Text="{Binding Name}" /> 
        </DataTemplate> 
      </Controls:HorizontalListView.ItemTemplate> 
      </Controls:HorizontalListView>
    </ContentPage>
    

答案 8 :(得分:2)

这款nuget套装非常适合您的情况。我以前用过这个,我真的很喜欢它:

https://github.com/SuavePirate/DynamicStackLayout

为了让事情变得更好,请下载这3个Nuget软件包以进行图像加载,缓存和扩展。改变你的照片。照片将被塑造成一个圆圈,但这个nuget有其他类型的变换:

Xamarin.FFImageLoading (https://github.com/luberda-molinet/FFImageLoading/wiki/Xamarin.Forms-API)
Xamarin.FFImageLoading.Forms
Xamarin.FFImageLoading.Transformations (https://github.com/luberda-molinet/FFImageLoading/wiki/Transformations-Guide)

以下是一段帮助您入门的代码:

<!--Add this code to the top of your page-->
xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
xmlns:fftransformations="clr-namespace:FFImageLoading.Transformations;assembly=FFImageLoading.Transformations"
xmlns:dynamicStackLayout="clr-namespace:SuaveControls.DynamicStackLayout;assembly=SuaveControls.DynamicStackLayout"


<!-- Here is your control inside a ScrollView. The property Photos is a list of images address (Urls)  -->

<ScrollView Orientation="Horizontal" HorizontalOptions="FillAndExpand">
    <dynamicStackLayout:DynamicStackLayout ItemsSource="{Binding Photos}" HorizontalOptions="Fill" Orientation="Horizontal" Padding="10, -0, 100, 10">
        <dynamicStackLayout:DynamicStackLayout.ItemTemplate>
            <DataTemplate>
                <StackLayout BackgroundColor="Transparent" >
                    <ffimageloading:CachedImage HorizontalOptions="Start" VerticalOptions="Center" DownsampleToViewSize="true" Aspect="AspectFit" Source="{Binding .}">
                        <ffimageloading:CachedImage.GestureRecognizers>
                            <TapGestureRecognizer Command="{Binding Path=PhotoCommand}" CommandParameter="{Binding .}" NumberOfTapsRequired="1" />
                        </ffimageloading:CachedImage.GestureRecognizers>
                        <ffimageloading:CachedImage.HeightRequest>
                            <OnPlatform x:TypeArguments="x:Double">
                                <On Platform="iOS" Value="50" />
                                <On Platform="Android" Value="60" />
                            </OnPlatform>
                        </ffimageloading:CachedImage.HeightRequest>
                        <ffimageloading:CachedImage.WidthRequest>
                            <OnPlatform x:TypeArguments="x:Double">
                                <On Platform="iOS" Value="50" />
                                <On Platform="Android" Value="60" />
                            </OnPlatform>
                        </ffimageloading:CachedImage.WidthRequest>
                        <ffimageloading:CachedImage.Transformations>
                            <fftransformations:CircleTransformation BorderHexColor="#eeeeee">
                                <fftransformations:CircleTransformation.BorderSize>
                                    <OnPlatform x:TypeArguments="x:Double">
                                        <On Platform="iOS" Value="10" />
                                        <On Platform="Android" Value="10" />
                                    </OnPlatform>
                                </fftransformations:CircleTransformation.BorderSize>
                            </fftransformations:CircleTransformation>
                        </ffimageloading:CachedImage.Transformations>
                    </ffimageloading:CachedImage>
                </StackLayout>
            </DataTemplate>
        </dynamicStackLayout:DynamicStackLayout.ItemTemplate>
    </dynamicStackLayout:DynamicStackLayout>
</ScrollView>

我希望它有所帮助:)

答案 9 :(得分:1)

在Xamarin.Forms 4.0-pre中,您可以使用CollectionView,从而简化了这种布局的设计。

示例:

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
        <ListItemsLayout>
            <x:Arguments>
                <ItemsLayoutOrientation>Horizontal</ItemsLayoutOrientation>    
            </x:Arguments>
        </ListItemsLayout>
    </CollectionView.ItemsLayout>
</CollectionView>

答案 10 :(得分:0)

据我所知,有三种方法可以实现这一点:

  1. 轮换(正如其他人提到的
    • 无需再使用标准ListView
    • ItemTemplate可用
    • 丑陋的解决方案!
  2. 自定义渲染(Android中的 RecyclerView和(我认为)iOS中的UICollectionView
    • 自定义单元格可用(我确信Android,但不确定iOS)
    • 需要更多工作和代码
  3. 网格和水平ScrollView(在ScrollView中使用水平值作为方向支柱
    • 自定义布局可用
    • 此解决方案中没有可用的CachingStrategy,因此对于巨大的列表,这可能会导致您的应用程序使用大量的RAM

答案 11 :(得分:0)

直到CollectionView用完为止,您可以使用我的Xamarin.Forms HorizontalListView

它具有:

  • 捕捉第一个或中间元素
  • 填充和项目间距
  • 处理NotifyCollectionChangedAction添加,删除和重置操作
  • 查看回收利用
  • Android上的RecyclerView
  • iOS上的UICollectionView
  • 实际上,此实现在理念和实现方面与将来提供Xamarin CollectionView的实现非常接近。

答案 12 :(得分:0)

该怎么办:https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/layout#horizontal-list

在XAML中,CollectionView可以通过将其ItemsLayout属性设置为Horizo​​ntalList来在水平列表中显示其项目:

<CollectionView ItemsSource="{Binding Monkeys}"
                ItemsLayout="HorizontalList">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <Grid Padding="10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="35" />
                    <RowDefinition Height="35" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="70" />
                    <ColumnDefinition Width="140" />
                </Grid.ColumnDefinitions>
                <Image Grid.RowSpan="2"
                       Source="{Binding ImageUrl}"
                       Aspect="AspectFill"
                       HeightRequest="60"
                       WidthRequest="60" />
                <Label Grid.Column="1"
                       Text="{Binding Name}"
                       FontAttributes="Bold"
                       LineBreakMode="TailTruncation" />
                <Label Grid.Row="1"
                       Grid.Column="1"
                       Text="{Binding Location}"
                       LineBreakMode="TailTruncation"
                       FontAttributes="Italic"
                       VerticalOptions="End" />
            </Grid>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

或者,也可以通过将ItemsLayout属性设置为LinearItemsLayout对象,并将Horizo​​ntal ItemsLayoutOrientation枚举成员指定为Orientation属性值来完成此布局:

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
        <LinearItemsLayout Orientation="Horizontal" />
    </CollectionView.ItemsLayout>
    ...
</CollectionView>

答案 13 :(得分:-1)

这已经通过一个名为ItemsView的自定义类(不要与XViewrin的ListView中的ListView中的数据模板混淆)来解决,它实现了上面提到的ScrollView / StackPanel模式,该模型已经被请求了。请参阅代码:https://gist.github.com/fonix232/b88412a976f67315f915