學習目標
- ImageSource.FromUri() - 從網址讀圖
- Aspect - 圖片填滿方式
- ImageSource.FromResource() - 從 PCL 專案讀圖
由於各家平台顯示 Bitmaps 方式不太一樣。
於是 Xamrin 提供了 Image(我是類別) 來統合處理 Bitmaps 圖片的顯示。
於是 Xamrin 提供了 Image(我是類別) 來統合處理 Bitmaps 圖片的顯示。
Image 最重要的屬性為 Source,用來指定圖片的來源,其方法有四:
- ImageSource.FromUri() - 從網址載入
- ImageSource.FromResource() - 從 PCL 內嵌資源載入
- ImageSource.FromFile() - 從各平台專案內載入
- ImageSource.FromStream() - 從 .NET 提供的 Stream 載入
一般來說,FromUri() 和 FromResource() 用來讀取跟平台 無相依性 的圖片。
而 FromFile() 則用來針對不同平台取得不同的圖片,例如 MenuItem 或 ToolbarItem 的 Icon。
對應這四種方法,Image 還有三個子類別,UriImageSource、FileImageSource & StreamImageSource。
雖然在 .cs 內用 ImageSorce.FromXXX() 方法直接指定圖片來源比較方便,不過偶爾還是會在 XAML 內使用這三個子類別。
FromUri()
底下是一支從 Uri 讀取圖片的 cs 寫法:
public class WebBitmapCodePage : ContentPage { public WebBitmapCodePage() { string uri = "https://developer.xamarin.com/demo/IMG_1415.JPG"; Content = new Image { Source = ImageSource.FromUri(new Uri(uri)) }; } }
或是直接指派 Source,程式會幫你做隱含轉換:
public class WebBitmapCodePage : ContentPage { public WebBitmapCodePage() { Content = new Image { Source = "https://developer.xamarin.com/demo/IMG_1415.JPG" }; } }
或是你想寫詳細一點:
public class WebBitmapCodePage : ContentPage { public WebBitmapCodePage() { Content = new Image { Source = new UriImageSource { Uri = new Uri("https://developer.xamarin.com/demo/IMG_1415.JPG") } }; } }
執行結果:
既然用網址載圖,UriImageSource 提供了兩個快取屬性可設定:
- CachingEnabled - 是否使用快取,預設為 True
- CachingValidity - 快取保留時間,類別為 TimeSpan,預設是一天
若今天將來源圖檔寬度縮小剩 25:
Content = new Image { Source = "https://developer.xamarin.com/demo/IMG_1415.JPG?width=25" };
會變成這樣 (好像哪裡怪怪的? 下面會解釋...):
XAML 寫法:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="WebBitmapXaml.WebBitmapXamlPage"> <Image Source="https://developer.xamarin.com/demo/IMG_3256.JPG" /> </ContentPage>
詳細一點也可以寫成:
<Image> <Image.Source> <UriImageSource Uri="https://developer.xamarin.com/demo/IMG_3256.JPG" /> </Image.Source> </Image>
執行結果:
Aspect -
Image 有個屬性 - Aspect,用來設定圖片顯示於容器的方式
成員有三:
- AspectFit - 預設,依比例縮放,適應容器
- Fill - 不管比例縮放,填滿容器
- AspectFill - 依比例縮放,填滿容器 (會截圖)
上一小節的圖片即使來源圖片變小了,但預設還是 AspectFit,才會將輸出結果縮放到容器適應的大小。Fill -
<Image Source="https://developer.xamarin.com/demo/IMG_3256.JPG" Aspect="Fill" />
AspectFill -
<Image Source="https://developer.xamarin.com/demo/IMG_3256.JPG" Aspect="AspectFill" />
FromResource()
藉由 Uri 讀取圖片是一個相當方便的方法,卻也有相當多限制,例如需要網路,圖片是否存在,需要時間去下載…
為了更快速的讀取圖片,其實可以將圖片嵌入至專案內,並使用 ImageResource.FromResource() 。
我們可以先在 PCL 內新增一個 Images 的資料夾,並把你要使用的圖片放進此資料夾,接著
在 VS 的方案總管,對圖檔按右鍵 → 屬性 → 建置動作改成內嵌資源
(Embedded resources)
專案建置後就會得到一組由 專案名.資料夾.圖檔名 組成的 Resource ID
原文書的範例如下:
ResourceBitmapCode.Images.ModernUserInterface256.jpg
FromResource 使用範例:
public class ResourceBitmapCodePage : ContentPage { public ResourceBitmapCodePage() { Content = new Image { Source = ImageSource.FromResource("ResourceBitmapCode.Images.ModernUserInterface256.jpg"), VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center }; } }
執行結果:
可以發現這次圖片沒有延展,原因為:
- 當圖片比容器小,且VerticalOptions 和 HorizontalOptions 不是設定 Fill ( 或 Image 放在 StackLayout 內 )
要怎麼在 XAML 內使用 FromResource 呢?
很抱歉,目前沒有提供方法… 現今(20170410) 最簡單的方法是自己寫一個擴充標籤…
客制化擴充標籤的教學在 第十章
程式碼如下…
namespace StackedBitmap { [ContentProperty("Source")] //不用在XAML內明確的寫 "Source=" public class ImageResourceExtension : IMarkupExtension { public string Source { get; set; } public object ProvideValue(IServiceProvider serviceProvider) { if (Source == null) return null; return ImageSource.FromResource(Source); } } }
XAML 用法:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:StackedBitmap " x:Class="StackedBitmap.StackedBitmapPage"> <StackLayout> <Label Text="320 x 240 Pixel Bitmap" FontSize="Medium" VerticalOptions="CenterAndExpand" HorizontalOptions="Center" /> <!--使用 ImageResource 擴充標籤--> <Image Source="{local:ImageResource StackedBitmap.Images.Sculpture_320x240.jpg}" BackgroundColor="Aqua" SizeChanged="OnImageSizeChanged" /> <Label x:Name="label" FontSize="Medium" VerticalOptions="CenterAndExpand" HorizontalOptions="Center" /> </StackLayout> </ContentPage>
SizeChanged 事件,將 Image 的寬高顯示於前端 Label:
public partial class StackedBitmapPage : ContentPage { public StackedBitmapPage() { InitializeComponent(); } void OnImageSizeChanged(object sender, EventArgs args) { Image image = (Image)sender; label.Text = String.Format("Render size = {0:F0} x {1:F0}", image.Width, image.Height); } }
由於將 Image 背景色設定為 Aqua,很清楚地可以看到 Image 和輸出的 bitmap 關係:
由於 Image 放在 StackLayout 內,其高度會先受到限制,而 HorizontalOptions 預設是 Fill,Image 就會往左右延展。
但圖片本身預設 AspectFit,就會看到 Image 和 Bitmap 比例不同的狀況如上圖。
如果你想將 Image 的比例和 Bitmap 輸出的結果比例一樣,可以設定 HorizontalOptions = "Center"
<Image Source="{local:ImageResource StackedBitmap.Images.Sculpture_320x240.jpg}" HorizontalOptions="Center" BackgroundColor="Aqua" SizeChanged="OnImageSizeChanged" />
設定圖片寬與高
可以在 Image 發現 Width 和 Height 這兩個屬性,但在 Xamarin 內這兩個屬性是 唯獨 的!!
意思就是設定了也不會有作用...
第五章 - 單位 有提到,若要手動更改 Visual Element 寬與高要設定這兩個屬性:
- HeightRequest
- WidthRequest
https://developer.xamarin.com/demo/IMG_3256.JPG 看不見啊
回覆刪除網頁連結已失效... 自己從網路上隨便找張圖吧
刪除