Xamarin.Forms 用戶界面——控件——ListView——Cell 外觀

Cell外觀

探索用於呈現數據的選項,同時利用ListView的便利。

PDF用於離線使用
相關樣品:

讓我們知道你對此的感受

最後更新:2016年12月

ListView提供可滾動列表,可以通過使用ViewCells 進行自定義。ViewCells可用於顯示文本和圖像,指示真/假狀態並接收用戶輸入。

從ListView單元格中可以看到兩種方法:

內置單元格

Xamarin.Forms配有內置單元格,適用於許多簡單的應用程序:

  • TextCell - 用於顯示文本
  • ImageCell - 用於顯示帶有文本的圖像。

另外兩個細胞,SwitchCellEntryCell可用,但它們不是通常與使用ListView。查看TableView有關這些單元格的更多信息。

TextCell

TextCell 是用於顯示文本的單元格,可選地具有第二行作爲詳細文本。

TextCells在運行時呈現爲本機控件,因此與自定義相比,性能非常好ViewCell。TextCells是可定製的,允許您設置:

  • Text - 第一行顯示的文字,大字體。
  • Detail - 第一行顯示的文本,字體較小。
  • TextColor - 文字的顏色。
  • DetailColor - 細節文字的顏色

的ImageCell

ImageCellTextCell可以用於顯示文本和二次詳細文本,並通過使用每個平臺的本機控件提供了很好的性能。ImageCell不同之處TextCell在於它顯示文本左側的圖像。

ImageCell當您需要顯示具有可視化方面的數據列表(例如聯繫人或電影列表)時,此功能非常有用。ImageCells是可定製的,允許您設置:

  • Text - 第一行顯示的文字,大字體
  • Detail - 第一行顯示的文本,字體較小
  • TextColor - 文字的顏色
  • DetailColor - 細節文字的顏色
  • ImageSource - 文本旁邊顯示的圖像

請注意,當定位到Windows Phone 8.1時,ImageCell默認情況下不會縮放圖像。另外請注意,默認情況下,Windows Phone 8.1是唯一以與主文本相同的顏色和字體顯示細節文本的平臺。Windows Phone 8.0呈現ImageCell如下:

自定義單元格

當內置單元格不提供所需的佈局時,自定義單元格實現了所需的佈局。例如,您可能想要呈現一個具有相同權重的兩個標籤的單元格。A LabelCell將不夠,因爲它LabelCell有一個較小的標籤。

所有自定義單元格必須從ViewCell所有內置單元格類型使用的相同基類派生。

大多數單元格自定義添加額外的只讀數據(如附加標籤,圖像或其他顯示信息)。如果添加了可以聚焦的按鈕或其他控件,則在Android上可能無法點擊單元本身。見下文,以克服這個限制。

Xamarin.Forms 2 在控件上引入了一個新的緩存行爲ListView,可以將其設置爲提高某些類型的自定義單元格的滾動性能。

這是一個自定義單元格的示例:

XAML

XAML創建上述佈局如下:

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="demoListView.ImageCellPage">
    <ContentPage.Content>
        <ListView  x:Name="listView">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout BackgroundColor="#eee"
                        Orientation="Vertical">
                            <StackLayout Orientation="Horizontal">
                                <Image Source="{Binding image}" />
                                <Label Text="{Binding title}"
                                TextColor="#f35e20" />
                                <Label Text="{Binding subtitle}"
                                HorizontalOptions="EndAndExpand"
                                TextColor="#503026" />
                            </StackLayout>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </ContentPage.Content>
</ContentPage>

上面的XAML正在做很多。我們來吧吧

  • 自定義單元格嵌套在一個DataTemplate內部ListView.ItemTemplate。這是與使用任何其他單元格相同的過程。
  • ViewCell是自定義單元格的類型。DataTemplate元素的子元素必須是或從類型導出的ViewCell
  • 注意在裏面ViewCell,佈局是由a管理的StackLayout。此佈局允許我們自定義背景顏色。請注意,任何StackLayout可綁定的屬性可以綁定到自定義單元格內,儘管此處未顯示。

C#

在C#中指定一個自定義單元格比XAML等效的更加冗長。讓我們來看看:

首先,定義一個自定義單元格類ViewCell作爲基類:

public class CustomCell : ViewCell
    {
        public CustomCell()
        {
            //instantiate each of our views
            var image = new Image ();
            StackLayout cellWrapper = new StackLayout ();
            StackLayout horizontalLayout = new StackLayout ();
            Label left = new Label ();
            Label right = new Label ();

            //set bindings
            left.SetBinding (Label.TextProperty, "title");
            right.SetBinding (Label.TextProperty, "subtitle");
            image.SetBinding (Image.SourceProperty, "image");

            //Set properties for desired design
            cellWrapper.BackgroundColor = Color.FromHex ("#eee");
            horizontalLayout.Orientation = StackOrientation.Horizontal;
            right.HorizontalOptions = LayoutOptions.EndAndExpand;
            left.TextColor = Color.FromHex ("#f35e20");
            right.TextColor = Color.FromHex ("503026");

            //add views to the view hierarchy
            horizontalLayout.Children.Add (image);
            horizontalLayout.Children.Add (left);
            horizontalLayout.Children.Add (right);
            cellWrapper.Children.Add (horizontalLayout);
            View = cellWrapper;
        }
    }

在您的頁面的構造函數中ListView,將ListView的ItemTemplate屬性設置爲新的DataTemplate

public partial class ImageCellPage : ContentPage
    {
        public ImageCellPage ()
        {
            InitializeComponent ();
            listView.ItemTemplate = new DataTemplate (typeof(CustomCell));
        }
    }

請注意,構造函數DataTemplate需要一個類型。typeof運算符獲取CLR類型CustomCell

綁定上下文更改

當綁定到自定義單元格類型的BindableProperty實例時,顯示BindableProperty值的UI控件應該使用OnBindingContextChangedoverride來設置要在每個單元格中顯示的數據,而不是單元格構造函數,如下面的代碼示例所示:

public class CustomCell : ViewCell
{
    Label nameLabel, ageLabel, locationLabel;

    public static readonly BindableProperty NameProperty =
        BindableProperty.Create ("Name", typeof(string), typeof(CustomCell), "Name");
    public static readonly BindableProperty AgeProperty =
        BindableProperty.Create ("Age", typeof(int), typeof(CustomCell), 0);
    public static readonly BindableProperty LocationProperty =
        BindableProperty.Create ("Location", typeof(string), typeof(CustomCell), "Location");

    public string Name {
        get { return(string)GetValue (NameProperty); }
        set { SetValue (NameProperty, value); }
    }

    public int Age {
        get { return(int)GetValue (AgeProperty); }
        set { SetValue (AgeProperty, value); }
    }

    public string Location {
        get { return(string)GetValue (LocationProperty); }
        set { SetValue (LocationProperty, value); }
    }
    ...

    protected override void OnBindingContextChanged ()
    {
        base.OnBindingContextChanged ();

        if (BindingContext != null) {
            nameLabel.Text = Name;
            ageLabel.Text = Age.ToString ();
            locationLabel.Text = Location;
        }
    }
}

OnBindingContextChanged倍率將被稱爲當BindingContextChanged事件觸發,響應的價值BindingContext特性改變。因此,當BindingContext更改時,顯示BindableProperty值的UI控件應設置其數據。請注意,BindingContext應該檢查一個null值,因爲這可以由Xamarin.Forms設置爲垃圾回收,這反過來將導致OnBindingContextChanged覆蓋被調用。

或者,UI控件可以綁定到BindableProperty實例以顯示其值,從而無需覆蓋該OnBindingContextChanged方法。

當覆蓋時OnBindingContextChanged,請確保OnBindingContextChanged調用基類的方法,以便註冊的代理接收BindingContextChanged事件。

在XAML中,可以將自定義單元格類型綁定到數據,如下面的代碼示例所示:

<ListView x:Name="listView">
    <ListView.ItemTemplate>
        <DataTemplate>
            <local:CustomCell Name="{Binding Name}" Age="{Binding Age}" Location="{Binding Location}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

此結合NameAgeLocation可綁定屬性在CustomCell比如,對NameAgeLocation底層集合中的每個對象的屬性。

C#中的等效綁定如下代碼示例所示:

var customCell = new DataTemplate (typeof(CustomCell));
customCell.SetBinding (CustomCell.NameProperty, "Name");
customCell.SetBinding (CustomCell.AgeProperty, "Age");
customCell.SetBinding (CustomCell.LocationProperty, "Location");

var listView = new ListView {
    ItemsSource = people,
    ItemTemplate = customCell
};

在iOS和Android上,如果ListView是循環元素,並且自定義單元格使用自定義渲染器,則自定義渲染器必須正確實現屬性更改通知。當重新使用單元格時,當綁定上下文更新爲可用單元格的屬性值時,其屬性值將更改,並PropertyChanged引發事件。有關詳細信息,請參閱自定義ViewCell。有關細胞再循環的更多信息,請參閱緩存策略

在Android上啓用行選擇

爲了允許對包含諸如按鈕之類的輸入元素的單元格進行行選擇,需要簡單custom renderer。在通用代碼中,創建一個子類,Button以便在平臺項目中添加自定義渲染器:

public class ListButton : Button { }

Android的渲染器實現只需設置Focusable允許行可選擇的屬性以及可主機可點擊的按鈕。此代碼已添加到Android應用程序項目中:

[assembly: ExportRenderer (typeof (ListButton), typeof (ListButtonRenderer))]
// ...
public class ListButtonRenderer : ButtonRenderer {
    protected override void OnElementChanged (ElementChangedEventArgs<ListButton> e) {
        base.OnElementChanged (e);
        Control.Focusable = false;
    }
}

如上所述,只有Android需要ButtonRenderer實現。iOS和Windows Phone平臺都允許單擊按鈕,而不實現自定義渲染器。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章