XAML in Xamarin.Forms 基礎篇 電子書

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

Xamarin.Forms 快速入門 電子書

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

2016/09/15

Xamarin.Forms Image 圖片控制項的特色與使用說明

這份筆記將會描述 Xamarin.Forms 內的 XAML Image 控制項的各項使用方式與其相關屬性設定方式。
在 Image 控制項,其圖片來源是透過 Source 屬性來設定,基本上,您可以使用文字來說明這個圖片是從網路上而得到,或者這個圖片是位於每個專屬專案內。若您想要從核心PCL專案內或者從您應用程式檔案系統內取得,則需要搭配其他方式來做到。
當然,上述的各種不同圖片來源各有不同的效果,原則上,若是採用後兩者(PCL / 本機檔案系統),則這些圖片是可以在不同平台上進行共用的;底下將會進行說明。
這份筆記的範例專案可以從底下取得

圖片來源

c sharp 的用法

圖片資源可以透過 ImageSource 類別提供的四個靜態方法來取得圖片
  • ImageSource.FromFile
    這個方法可以取得個專屬平台下的圖片檔案
  • ImageSource.FromUri
    這個方法是透過一個網址,取得網路上的圖片資源
  • ImageSource.FromeResource
    這個方法可以讓您取得核心PCL專案內的圖片檔案
  • ImageSource.FromStream
    這個方法可以讓您取得本機應用程式下載後的圖片檔案

XAML 的用法

  • 取得個專屬平台下的圖片檔案
    在 Source 屬性內,直接定義一個在專屬平台內的圖片檔案名稱,就可以從每個專屬專案平台下取得這個圖片檔案;若每個專案平台的圖片檔案路徑或者檔案名稱不同,可以使用 OnPlatform 來指定不同平台下的實際圖片檔案名稱與路徑。
<Image Grid.Row="1" Grid.Column="0" Source="platformImage.jpg" />
  • 取得網路上的圖片資源
    在 Source 屬性內,可以使用一個網址字串,就會讓 Image 自動從網路下載這個圖片
<Image Source="https://developer.xamarin.com/demo/IMG_3256.JPG?width=640" />
  • 取得核心PCL專案內的圖片檔案
    若想要在取得 PCL 專案內的圖片檔案,您需要客製化一個有建置 IMarkupExtension 介面的類別,並且在 XAML 內提供取得 PCL 內的圖片檔案。
<Image Grid.Row="0" Grid.Column="1" Source="{extMark:ImageResource XFImage.Assets.platformImage.jpg}"/>
該 IMarkupExtension 的類別的程式碼,如下所示,在 ImageResourceExtension 類別中,使用了ImageSource.FromResource 取出 PCL 內的圖片檔案並且轉換成為 ImageSource
    public class ImageResourceExtension : IMarkupExtension
    {
        public string Source { get; set; }
        public object ProvideValue(IServiceProvider serviceProvider)
        {
            if (Source == null) return null;
            return ImageSource.FromResource(Source);
        }
    }
  • 取得本機應用程式下載後的圖片檔案
    這裡有兩種方法,一個是在 ViewModel 定義一個 ImageSource 的可綁定屬性,透過 ViewModel 內的方法,取得本機檔案的圖片檔案;在這裡,使用了 PCL Storage 這個套件,讓您可以在 PCL 專案內,取得本機檔案。
 <Image Grid.Row="1" Grid.Column="1" Source="{Binding MyImageSource}" />
ViewModel 內的可綁定 ImageSource 屬性
        private ImageSource myImageSource;
        public ImageSource MyImageSource
        {
            get { return myImageSource; }
            set { SetProperty(ref myImageSource, value); }
        }
底下的為在 ViewModel 內的某個 RelayCommand 方法,當按下這個按鈕,就會使用 HttpClient 物件來下載網路上的圖片,並且使用 PCL Storage 將這個圖片檔案儲存到本機上。
接著,使用 ImageSource.FromStream(() => fooTargetReadStream) 方法,取得這個圖片檔案的 ImageSource 物件,以便可以顯示在頁面上。
            #region 從網路下載後,先儲存到本機檔案系統內,接著再讀出來,進行圖片資料綁定
            HttpClient client = new HttpClient();
            IFolder rootFolder = FileSystem.Current.LocalStorage;
            IFolder folder = await rootFolder.CreateFolderAsync("Images", CreationCollisionOption.OpenIfExists);
            IFile file = await folder.CreateFileAsync("MyLocalImage.jpg", CreationCollisionOption.ReplaceExisting);
            using (var fooTargetStream = await file.OpenAsync(FileAccess.ReadAndWrite))
            {
                using (var fooSourceString = await client.GetStreamAsync("https://developer.xamarin.com/demo/IMG_3256.JPG?width=640"))
                {
                    await fooSourceString.CopyToAsync(fooTargetStream);
                }
            }

            file = await folder.GetFileAsync("MyLocalImage.jpg");
            var fooTargetReadStream = await file.OpenAsync(FileAccess.Read);
            MyImageSource = ImageSource.FromStream(() => fooTargetReadStream);
            #endregion
另外一個方法就是使用數值轉換器 Value Converter,使用這個解決方案,您需要定義一個新類別,且建置IValueConverter 介面,如下所示:
這段數值轉換器使用了 PCL Storage 套件,取得該該圖片檔案的內容,接著透過 ImageSource.FromStream靜態方法取得 ImageSource 物件。
    class StringToLocalImage : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string foo1 = value as string;
            ImageSource fooImageSource=null;

            if (string.IsNullOrEmpty(foo1) == false)
            {
                IFolder rootFolder = FileSystem.Current.LocalStorage;
                IFolder folder;
                IFile file;
                folder = rootFolder.CreateFolderAsync("Images", CreationCollisionOption.OpenIfExists).Result;
                file = folder.GetFileAsync(foo1).Result;
                var fooStream = file.OpenAsync(FileAccess.Read).Result;
                Debug.WriteLine($"Length: {fooStream.Length}");

                fooImageSource = ImageSource.FromStream(() => fooStream);
            }
            else
            {
            }

            //fooImageSource= ImageSource.FromUri(new Uri("https://developer.xamarin.com/demo/IMG_1415.JPG?height=640"));

            return fooImageSource;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
在 XAML 下,可以使用這樣的方式來宣告
    <Image Grid.Row="2" Grid.Column="1"
          Source="{Binding LocalImage2, Converter={StaticResource StringToLocalImage}}" />

Aspect

這個屬性是用來控制圖片要顯示何種大小,這裡需要使用 Aspect 的屬性。
  • Fill
    會自動將圖片充滿整個容器內,這可能會導致圖片會失真。
  • AspectFill
    使用等比例的放大,讓圖片不會失真,但是,會導致有些圖片區域無法顯示出來。
  • AspectFit
    使用等比例的放大,讓圖片不會失真,但是,會導致有些區域留下空白的內容。

沒有留言:

張貼留言