- ImageSource.FromStream() - 從串流讀圖
- ImageSource.FromFile() - 各平台讀圖
- 了解各平台圖片解析度
- Toolbars
十三.壹 章節介紹了讀取圖片四種方法的前兩種,這節會介紹剩下的 FromStream() 和 FromFile()。
特別是 FromFile() 方法會從不同平台讀取圖片,更需要了解各圖片解析度之特性。
先從 FromStream() 開始:
FromStream()
Stream 是 .NET 使用很久的一種類別,Xamarin.Forms 在讀圖也提供了 FromStream 的方法對應使用。
比較奇怪一點是, ImageSource.FromStream() 並不是一個 Stream 物件,而是一個會回傳 Stream 的 Func 物件 (簡單說就是一個方法)
來看程式碼,就會發現 FromStream 的寫法都會接著 Lambda 並在方法內回傳 Stream。
先在前端放兩個 Image 準備讀圖:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="ImageBrowser.ImageBrowserPage"> <StackLayout> <Image x:Name="image1" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" /> <Image x:Name="image2" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" /> </StackLayout> </ContentPage>
第一張圖從 Resource 內取出資源後塞到 Stream 內:
public BitmapStreamsPage() { InitializeComponent(); // Load embedded resource bitmap. string resourceID = "BitmapStreams.Images.IMG_0722_512.jpg"; image1.Source = ImageSource.FromStream(() => { Assembly assembly = GetType().GetTypeInfo().Assembly; Stream stream = assembly.GetManifestResourceStream(resourceID); return stream; }); }
第二張圖從 Uri 塞到 Stream 內:
public BitmapStreamsPage() { // Load web bitmap. Uri uri = new Uri("https://developer.xamarin.com/demo/IMG_0925.JPG?width=512"); WebRequest request = WebRequest.Create(uri); request.BeginGetResponse((IAsyncResult arg) => { Stream stream = request.EndGetResponse(arg).GetResponseStream(); ImageSource imageSource = ImageSource.FromStream(() => stream); Device.BeginInvokeOnMainThread(() => image2.Source = imageSource); }, null); }
用 Stream 的寫法看起來有更多的控制權,但直接使用 FromUri 的好處是會自動幫你快取,Stream 則沒有。
FromFile()
通常搭配 OnPlatform 來讀取不同平台的圖片,且會自動去取得最適解析度的檔案。
當新增一個專案時,會發現有一些預設的圖檔在各平台的專案內,Android 和 iOS 都在 Resource 資料夾內,而 Windows 在 assetes 資料夾內。
*OnPlatform 寫法已更改,請參考此篇文章
來看一下 .cs 寫法:
Xaml 寫法:
圖片解析度
上一小節程式可以看到 iOS 的圖檔叫做 Icon-Small-40.png ,但你若是將 Resource 資料夾打開,會發現有三個檔名類似但解析度不一樣的圖檔:
本書用的 iPhone6 會將此 Icon render 成 40 device-independent units。
再來看一下 Android 的 Resource 資料夾,你會發現以下圖檔:
以本書的 Nexus5 為例,icon 會 render 成 48 device-independent units,而 Nexus5 一個 device-independent units 對應三個 pixel ,所以會使用 xxdpi 這張圖。
Windows phone 就不討論了。
Android 還有其他大小:
不過你不需要產生全部解析度的圖片,一般來說 hdpi 和 xhdpi 和 xxhdpi 就夠了。
Toolbars
其中一個最常用 bitmaps 的物件為 Xamarin.Forms toolbar,通常會出現在頁面的上方作為功能列,toolbar items 是可以被點擊的。
但 Xamarin.Forms 沒有直接提供 toolbar 類別可以使用,必須先宣告一個 ToolbarItem 的集合,再指派給 Page 的 ToolbarItems 屬性。
ToolbarItem 有以下三個屬性:
Order 這個屬性管理 ToolbarItem 是否出現 image(Primary),或是 Text(Secondary)。
ToolbarItem 最重要的就是 Icon 屬性,由於各個平台讀圖不逕相同,也因為這樣才會使用 FileImageResource。
看一下 Xaml 寫法:
*OnPlatform 寫法已更改,請參考此篇文章
點擊右邊點點點:
Button images
Button 本身就有 Image 屬性可以修改,但這個特性不是用來做單張圖片的按鈕,通常是在按鈕文字的旁的圖示。
直接來看 code 和結果:
*OnPlatform 寫法已更改,請參考此篇文章
原文書上提供三種平台可下載 Icon 的地方:
Android : http://developer.android.com/design/downloads
IOS:http://smashingmagazine.com/2010/07/14/gcons-free-all-purpose-icons-for-designers-and-developers-100-icons-psd/
Win : C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v8.0\Icons
不論是從哪邊下載的 Icons,放到專案內都要確定 Build Action 有設定好。
FromFile()
通常搭配 OnPlatform 來讀取不同平台的圖片,且會自動去取得最適解析度的檔案。
當新增一個專案時,會發現有一些預設的圖檔在各平台的專案內,Android 和 iOS 都在 Resource 資料夾內,而 Windows 在 assetes 資料夾內。
*OnPlatform 寫法已更改,請參考此篇文章
來看一下 .cs 寫法:
Image image = new Image { Source = new FileImageSource { File = Device.OnPlatform(iOS: "Icon-Small-40.png", Android: "icon.png", WinPhone: "Assets/StoreLogo.png") }, HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.CenterAndExpand }
要注意的是讀取圖只需鍵入你要取得圖片的檔名。
Xaml 寫法:
<Image.Source> <OnPlatform x:TypeArguments="ImageSource" iOS="Icon-Small-40.png" Android="icon.png" WinPhone="Assets/StoreLogo.png" /> </Image.Source>
圖片解析度
上一小節程式可以看到 iOS 的圖檔叫做 Icon-Small-40.png ,但你若是將 Resource 資料夾打開,會發現有三個檔名類似但解析度不一樣的圖檔:
- Icon-Small-40.png - 40 pixels square
- Icon-Small-40@2x.png - 80 pixels square
- Icon-Small-40@3x.png - 120 pixels square
本書用的 iPhone6 會將此 Icon render 成 40 device-independent units。
而 iPhone6 一個 device-independent units 對應兩個 pixel,此時程式就會採用 Icon-Small-40@2x.png 這張圖。
同理,若是 iPad 2 會使用 Icon-Small-40@3x.png。
Xamarin 單位相關的教學可以參考 第五章
再來看一下 Android 的 Resource 資料夾,你會發現以下圖檔:
- drawable/icon.png - 72 pixels square
- drawable - hdpi/icon.png - 72 pixels square
- drawable - xdpi/icon.png - 96 pixels square
- drawable - xxdpi/icon.png - 144 pixels square
以本書的 Nexus5 為例,icon 會 render 成 48 device-independent units,而 Nexus5 一個 device-independent units 對應三個 pixel ,所以會使用 xxdpi 這張圖。
Windows phone 就不討論了。
Android 還有其他大小:
- ldpi ( 0.75 pixels to the DIU )
- mdpi ( 1 pixel to the DIU )
- hdpi ( 1.5 pixel to the DIU )
- xhdpi ( 2 pixel to the DIU )
- xxhdpi ( 3 pixel to the DIU )
- xxxhdpi ( 4 pixel to the DIU )
不過你不需要產生全部解析度的圖片,一般來說 hdpi 和 xhdpi 和 xxhdpi 就夠了。
Toolbars
其中一個最常用 bitmaps 的物件為 Xamarin.Forms toolbar,通常會出現在頁面的上方作為功能列,toolbar items 是可以被點擊的。
ToolbarItem 有以下三個屬性:
- Text - 可出現可不出現,端看平台或是 Order
- Icon - FileImageSource 來自各個平台的專案的 bitmap 物件
- Order - 有以下三個順序可以使用, Default, Primary, or Secondary
Order 這個屬性管理 ToolbarItem 是否出現 image(Primary),或是 Text(Secondary)。
ToolbarItem 最重要的就是 Icon 屬性,由於各個平台讀圖不逕相同,也因為這樣才會使用 FileImageResource。
看一下 Xaml 寫法:
*OnPlatform 寫法已更改,請參考此篇文章
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="ToolbarDemo.ToolbarDemoPage" Title="Toolbar Demo"> <Label x:Name="label" FontSize="Medium" HorizontalOptions="Center" VerticalOptions="Center" /> <ContentPage.ToolbarItems> <!--第一個 item--> <ToolbarItem Text="edit" Order="Primary" Clicked="OnToolbarItemClicked"> <ToolbarItem.Icon> <OnPlatform x:TypeArguments="FileImageSource" iOS="edit.png" Android="ic_action_edit.png" WinPhone="Images/edit.png" /> </ToolbarItem.Icon> </ToolbarItem> <!--第二個 item--> <ToolbarItem Text="search" Order="Primary" Clicked="OnToolbarItemClicked"> <ToolbarItem.Icon> <OnPlatform x:TypeArguments="FileImageSource" iOS="search.png" Android="ic_action_search.png" WinPhone="Images/feature.search.png" /> </ToolbarItem.Icon> </ToolbarItem> <!--若加入太多 Item 的話,各平台顯示的方式也不太一樣--> </ContentPage.ToolbarItems> </ContentPage>
點擊右邊點點點:
Button images
Button 本身就有 Image 屬性可以修改,但這個特性不是用來做單張圖片的按鈕,通常是在按鈕文字的旁的圖示。
直接來看 code 和結果:
*OnPlatform 寫法已更改,請參考此篇文章
<Button Text="Oh Yeah"> <Button.Image> <OnPlatform x:TypeArguments="FileImageSource" iOS="ic_action_good.png" Android="ic_action_good.png" WinPhone="Images/ic_action_good.png" /> </Button.Image> </Button>
原文書上提供三種平台可下載 Icon 的地方:
Android : http://developer.android.com/design/downloads
IOS:http://smashingmagazine.com/2010/07/14/gcons-free-all-purpose-icons-for-designers-and-developers-100-icons-psd/
Win : C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v8.0\Icons
不論是從哪邊下載的 Icons,放到專案內都要確定 Build Action 有設定好。
作者已經移除這則留言。
回覆刪除痾正想回你留言,所以問題已經解決了嗎?
刪除你好,我是最近開始在學Xamarin的新手,關於ToolbarItem這邊是不是少寫了一些東西
回覆刪除因為我的toolbar一直都是神隱的狀態。
直到去google才發現,似乎要將App.xaml.cs那邊將Mainpage改寫成:
MainPage = new NavigationPage(new MainPage());
請問除了這個方式外,還有別的方式嗎?
謝謝
當初翻譯書時沒注意到這個優先條件,目前來說還可以用 Shell
刪除可以請問一下如果是在自己新增的頁面,怎麼讓新增的頁面也有toolbar
刪除用 Shell 建立 App 或是如上所說的在 App.xaml.cs 將頁面用 NavigationPage 包起來,才會出現
刪除很感謝您的回覆,最近想透過Xamarin.Form製作一個軟體
刪除爬了很多與妳相關的文章受益良多近期也想買您出的書
想了解一下書有解說gmail認證的部分嗎?
gmail 認證是指第三方登入嗎? 書中沒講太多應用層面的東西,都是以基礎的觀念內容為主,若有需要我可以幫你研究看看
刪除