XAML in Xamarin.Forms 基礎篇 電子書

XAML in Xamarin.Forms 基礎篇 電子書
XAML in Xamarin.Forms 基礎篇 電子書

Xamarin.Forms 快速入門 電子書

Xamarin.Forms 快速入門 電子書
Xamarin.Forms 快速入門 電子書

2016/11/13

Xamarin.Forms 使用具有 GridView 特性圖片畫廊

傳統上 Xamarin.Forms 並沒有提供類似 GridView 這樣的控制項,也就是可以使用多 Column 的方式來顯示集合資料,但是其他的行為與 ListView 一樣。
在這份筆記中,將會測試與使用 DLToolkit.Forms.Controls.FlowListView 這個 NuGet 套件,就可以達成使用 GridView 控制項的圖片畫廊效果。
要使用這個功能,您需要在方案中加入這個 DLToolkit.Forms.Controls.FlowListView & Xamarin.FFImageLoading.Forms 這兩個 NuGet 套件到所有的專案內;下面螢幕截圖為實際執行結果。
XFHListView
範例專案

需要安裝 NuGet 套件

要完成這個筆記中的效果,你需要在方案中安裝底下的 NuGet 套件
Xamarin.FFImageLoading.Forms
DLToolkit.Forms.Controls.FlowListView

範例說明

首先,需要定義這個集合的資料模型。
在這個,建立了一個 SampleItems1 資料模型,裡面有 Title / Color / ImageUrl 這三個屬性。
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using Xamarin.Forms;

namespace XFHListView.Models
{
    public class SampleItems1 : BindableBase
    {

        #region Title
        private string _Title;
        /// <summary>
        /// Title
        /// </summary>
        public string Title
        {
            get { return this._Title; }
            set { this.SetProperty(ref this._Title, value); }
        }
        #endregion


        #region Color
        private Color _Color;
        /// <summary>
        /// Color
        /// </summary>
        public Color Color
        {
            get { return this._Color; }
            set { this.SetProperty(ref this._Color, value); }
        }
        #endregion


        #region ImageUrl
        private string _ImageUrl;
        /// <summary>
        /// ShowImage
        /// </summary>
        public string ImageUrl
        {
            get { return this._ImageUrl; }
            set { this.SetProperty(ref this._ImageUrl, value); }
        }
        #endregion

        public SampleItems1()
        {

        }
    }
}
接著需要在 ViewModel 內定義所有資料綁定的集合資料,並且要進行集合資料的初始化,可以參考底下程式碼。
在這個 ViewModel 內,集合資料將會使用 ObservableCollection<SampleItems1> 型別,並且儲存在 MyDatas 這個物件內。
在建構式內,呼叫了 Init() 方法,針對 MyDatas 進行產生實際物件並且進行資料初始化。
在進行 MyDatas 物件初始化的過程中,會透過一個靜態屬性 RandomColor.PickColor 來得到動態的顏色物件。而圖片的 URL 則是會透過一個 images 陣列來取得
另外,也定義了一個命令 使用者點選Command,定義了當使用者點選某個特定項目之後,就會顯示出他選取的項目內容。
using Prism.Commands;
using Prism.Mvvm;
using Prism.Services;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using XFHListView.Helper;
using XFHListView.Models;

namespace XFHListView.ViewModels
{
    public class SimpleGalleryPageViewModel : BindableBase
    {
        string[] images = {
                "https://farm9.staticflickr.com/8625/15806486058_7005d77438.jpg",
                "https://farm5.staticflickr.com/4011/4308181244_5ac3f8239b.jpg",
                "https://farm8.staticflickr.com/7423/8729135907_79599de8d8.jpg",
                "https://farm3.staticflickr.com/2475/4058009019_ecf305f546.jpg",
                "https://farm6.staticflickr.com/5117/14045101350_113edbe20b.jpg",
                "https://farm2.staticflickr.com/1227/1116750115_b66dc3830e.jpg",
                "https://farm8.staticflickr.com/7351/16355627795_204bf423e9.jpg",
                "https://farm1.staticflickr.com/44/117598011_250aa8ffb1.jpg",
                "https://farm8.staticflickr.com/7524/15620725287_3357e9db03.jpg",
                "https://farm9.staticflickr.com/8351/8299022203_de0cb894b0.jpg",
            };

        #region MyDatas
        private ObservableCollection<SampleItems1> _MyDatas;
        /// <summary>
        /// MyDatas
        /// </summary>
        public ObservableCollection<SampleItems1> MyDatas
        {
            get { return _MyDatas; }
            set { SetProperty(ref _MyDatas, value); }
        }
        #endregion

        #region 使用者點選項目
        private SampleItems1 _使用者點選項目;
        /// <summary>
        /// 使用者點選項目
        /// </summary>
        public SampleItems1 使用者點選項目
        {
            get { return this._使用者點選項目; }
            set { this.SetProperty(ref this._使用者點選項目, value); }
        }
        #endregion

        public DelegateCommand 使用者點選Command { get; set; }

        public readonly IPageDialogService _dialogService;
        public SimpleGalleryPageViewModel(IPageDialogService dialogService)
        {

            _dialogService = dialogService;
            Init();

            使用者點選Command = new DelegateCommand(() =>
            {
                _dialogService.DisplayAlertAsync("訊息", $"你選取的是 {使用者點選項目.Title}", "OK");
            });
        }

        public void Init()
        {
            MyDatas = new ObservableCollection<SampleItems1>();

            var howMany = new Random().Next(100, 500);

            for (int i = 0; i < howMany; i++)
            {
                var foo = i % 10;
                MyDatas.Add(new SampleItems1() {
                    Title = string.Format("項目 {0}", i),
                    ImageUrl = images[foo],
                    Color = RandomColor.PickColor
                });
            }
        }
    }
}
有的 Model / ViewModel,接下來,就是要定義 View,可以參考底下 XAML 。
這個頁面 XAML 內容相當的簡單,根項目為 ContentPage,並且其兒子為 FlowListView;不過,由於這個 FlowListView 控制項並不是 Xamarin.Forms 預設命名空間所提供的,因此,需要在跟項目內另外定義一個命名空間 xmlns:flv="clr-namespace:DLToolkit.Forms.Controls;assembly=DLToolkit.Forms.Controls.FlowListView",這樣,就可以使用前置詞 flv 來引用 FlowListView 這個控制項。
FlowListView 這個控制項內,使用了 FlowColumnCount="3" 宣告了這個 GridView 效果共有三個 Column,並且每筆紀錄並沒有使用分隔線,這是使用了這個宣告:SeparatorVisibility="None"
另外,使用了 HasUnevenRows="True" 設定依據當時記錄本身顯示的高度作為高度;當使用者點選了清單內的某個項目,可以使用 FlowItemTappedCommand 來綁定 ViewModel 內的某個 DelegateCommand ,就可以在 ViewModel 內撰寫相關點擊後的處理邏輯;而使用者點選後的項目,也會透過 FlowLastTappedItem 這個屬性,將其綁定到 ViewModel 內的某個屬性,也就是說,當使用者點選某個項目,就可以透過該 ViewModel 內的屬性,取得使用者當時點選的項目內容;最後,該 FlowListView 要顯示的資料清單內容,將會透過 FlowItemsSource 屬性來進行資料綁定。
最後,與 ListView 相同,每筆資料,可以透過 FlowListView.FlowColumnTemplate 來設定這些資料項目要使用何種格式來顯示。
關於在每個紀錄上要顯示圖片的時候,不使用 Xamarin.Forms 的 Image 檢視,而是使用了 CachedImage,要使用這個檢視,必須要在根項目內定義新的前置詞與命名空間(FFImageLoading) 這樣才能夠在該頁面中引用。這個 ffimageloading:CachedImage 檢視增加了許多功能,例如, LoadingPlaceholder & ErrorPlaceholder 則是可以放置一個圖片名稱,用於當圖片尚未被載入到頁面的時候與讀取發生錯誤的時候要顯示的圖片;RetryCount 這個屬性用於當取得圖片發生錯誤的時候,需要重新再度讀取的次數;CacheDuration 則是設定這個圖片需要快取的保存期限;DownsampleHeight & DownsampleWidth 若有設定的話,會自動依據這兩個屬性設定值,縮放成為其定義大小,不過,若 DownsampleUseDipUnits 設定為 False,則表示要縮放的單為 Pixel,若設定為 True,則表示要縮放的單位為 DIP。DownsampleToViewSize若設定為 True,則會自動縮放大小成為當時 View 的大小。
<?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:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             xmlns:flv="clr-namespace:DLToolkit.Forms.Controls;assembly=DLToolkit.Forms.Controls.FlowListView"
             xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
             x:Class="XFHListView.Views.SimpleGalleryPage"
             Title="圖片畫廊">

    <flv:FlowListView
        FlowColumnCount="3"
        SeparatorVisibility="None"
        HasUnevenRows="True"
        FlowItemTappedCommand="{Binding 使用者點選Command}"
        FlowLastTappedItem="{Binding 使用者點選項目}"
        FlowItemsSource="{Binding MyDatas}"
        FlowColumnMinWidth="110"
        >
        <flv:FlowListView.FlowColumnTemplate>
            <DataTemplate>
                <Grid Padding="3">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>

                    <ffimageloading:CachedImage 
                        HeightRequest="100" 
                        Aspect="AspectFill"
                        DownsampleHeight="100" DownsampleUseDipUnits="false" 
                        LoadingPlaceholder="image_loading.png" ErrorPlaceholder="image_error.png"
                        Source="{Binding ImageUrl}"/>

                    <Label x:Name="Label" HorizontalOptions="Fill" HorizontalTextAlignment="Center" VerticalOptions="End"
                        BackgroundColor="Black" Opacity="0.5" 
                           TextColor="{Binding Color}"
                           Text="{Binding Title}"/>
                </Grid>
            </DataTemplate>
        </flv:FlowListView.FlowColumnTemplate>

    </flv:FlowListView>
</ContentPage>

沒有留言:

張貼留言