2017-08-24 6 views
1

Xamarin.Forms ListViewの下から上に要素が表示されるようにしたいので、要素が少ないときにListViewの下部に要素が表示されます。説明は画像を参照してください。これは、手動でListViewのHeightRequestを設定することなく行うことができますか? (HeightRequestを手動で設定する必要がある場合は、HasUnevenRows=trueを使用しているときにListViewの子要素の高さを計算するにはどうすればよいですか?)リストにアイテムが少ない場合、ListViewアイテムを画面の一番下に揃えるにはどうすればいいですか?

ここではどのように見たいのですか?権利);参考のため

Desired behavior for few items to the left; many items to the right.

、ここでいくつかの項目がある場合、リストビューが正常に動作する方法である:

Current behavior for few items.

答えて

3

ListViewが必須ではなく、テンプレートサポートで反復可能なコントロールが必要な場合は、ItemsControlを使用できます。パネルとしてStackLayoutを使用しているため、必要な高さにしか拡大しません。だから、あなたはそれの高さを計算する必要はありません。 ご注意くださいItemsControlには非常に基本的な仮想化の動作(リサイクル)があります。そのため、多くのアイテムがある場合は、仮想化をサポートするようにコントロールを変更する必要があります。

第二に、あなたは自動的に下のコンテンツのサイズごとにAutoまたはStarに2つ目のRowDefinitionを設定するGridを拡張することができます。つまり、デフォルトではAutoのままにしますが、コンテンツサイズがビューポートの高さの50%を超える場合は、RowDefinitionStarにリセットしてください。例えばのために、あなたは、カスタムSplitterGrid作成することができます。

public class SplitterGrid : Grid 
{ 
    public SplitterGrid() 
    { 
     RowDefinitions = new RowDefinitionCollection() 
     { 
      new RowDefinition { Height = GridLength.Star }, 
      new RowDefinition { Height = GridLength.Auto } 
     }; 
    } 

    void Content2_SizeChanged(object sender, EventArgs e) 
    { 
     if (Height == 0 && Width == 0) 
      return; 

     Content2.SizeChanged -= Content2_SizeChanged; 
     if (Content2.Height > Height/2) 
      RowDefinitions[1].Height = GridLength.Star; 
     else 
      RowDefinitions[1].Height = GridLength.Auto; 
    } 

    public static readonly BindableProperty Content1Property = 
     BindableProperty.Create(
     "Content1", typeof(View), typeof(SplitterGrid), 
     defaultValue: null, propertyChanged: OnContent1Changed); 

    public View Content1 
    { 
     get { return (View)GetValue(Content1Property); } 
     set { SetValue(Content1Property, value); } 
    } 

    private static void OnContent1Changed(BindableObject bindable, object oldValue, object newValue) 
    { 
     ((SplitterGrid)bindable).OnContent1ChangedImpl((View)oldValue, (View)newValue); 
    } 

    void OnContent1ChangedImpl(View oldValue, View newValue) 
    { 
     if (oldValue == null) 
      Children.Add(Content1); 
    } 

    public static readonly BindableProperty Content2Property = 
     BindableProperty.Create(
     "Content2", typeof(View), typeof(SplitterGrid), 
     defaultValue: null, propertyChanged: OnContent2Changed); 

    public View Content2 
    { 
     get { return (View)GetValue(Content2Property); } 
     set { SetValue(Content2Property, value); } 
    } 

    private static void OnContent2Changed(BindableObject bindable, object oldValue, object newValue) 
    { 
     ((SplitterGrid)bindable).OnContent2ChangedImpl((View)oldValue, (View)newValue); 
    } 

    void OnContent2ChangedImpl(View oldValue, View newValue) 
    { 
     if (oldValue == null) 
     { 
      Children.Add(Content2); 
      Content2.SizeChanged += Content2_SizeChanged; 
      Grid.SetRow(Content2, 1); 
     } 
     else 
      Content2.SizeChanged -= Content2_SizeChanged; 
    } 
} 

をそして、使い方は次のようになります動作するようには思えない残念ながら

<local:SplitterGrid Margin="0,20,0,0"> 
    <local:SplitterGrid.Content1> 
     <ContentView Padding="10" BackgroundColor="#E4E4E4"> 
      <Label Text="This page contains about 3 items." /> 
     </ContentView> 
    </local:SplitterGrid.Content1> 
    <local:SplitterGrid.Content2> 
     <ScrollView VerticalOptions="End"> 
      <local:ItemsControl> 
       <local:ItemsControl.ItemTemplate> 
        <DataTemplate> 
         <Label FontAttributes="Bold" FontSize="40" Text="{Binding .}" /> 
        </DataTemplate> 
       </local:ItemsControl.ItemTemplate> 
       <local:ItemsControl.ItemsSource> 
        <x:Array Type="{x:Type x:String}"> 
         <x:String>Item 1</x:String> 
         <x:String>Item 2</x:String> 
         <x:String>Item 3</x:String> 
        </x:Array> 
       </local:ItemsControl.ItemsSource> 
      </local:ItemsControl> 
     </ScrollView> 
    </local:SplitterGrid.Content2> 
</local:SplitterGrid> 

enter image description here

+1

ありがとうございます、ItemsControlはすばらしい働きをしています([リサイクルのバグ](https://github.com/xamarinhq/xamu-infrastructure/pull/7)は保存しています)。 – cmeeren

+0

私はそれが簡単に修正できるはずだと信じています。 ItemsSource変更リスナーで明確なメソッドを追加する(新しいコレクションの数が以前より少ない場合) – Ada

+1

はい、それを修正するPRにリンクしました。 – cmeeren

0

私は2つの行は、「1つのセットで定義されたグリッドとなるだろう* "、またはピクセル単位の高さ、および下端の値を" Auto "に設定し、リストビューVerticalOptionsを" End "に設定します。

+0

。 ListViewの 'Auto'行の展開が' * '行の展開よりも優先されるようです。結果は私が始めた場所とほぼ同じでした。 – cmeeren

関連する問題