這份筆記將會描述 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使用等比例的放大,讓圖片不會失真,但是,會導致有些區域留下空白的內容。