Xamarin.FormsアプリではImageコントロールのSourceプロパティを使用することで、URLを指定して画像を表示できる。
対象:Visual Studio 2015以降
Xamarin.Formsは、XAMLとC#を使ってAndroid/iOS/Windows向けのクロスプラットフォーム開発を行える開発環境だ。
本稿では、Xamarin.FormsアプリでWebから画像を取得して表示する方法を解説する。
Imageコントロール(Xamarin.Forms名前空間)のSourceプロパティに、ImageSourceオブジェクト(Xamarin.Forms名前空間)をセットすればよい。ImageSourceオブジェクトの作り方には、いろいろなやり方がある。
XAMLでは、次のコードのように書ける。
<!-- 簡単な書き方 -->
<Image Source="/ait/images/gyoumu_link_btn.gif" />
<!-- 冗長な書き方 -->
<Image>
<Image.Source>
<UriImageSource
Uri="/ait/images/gyoumu_link_btn.gif" />
</Image.Source>
</Image>
上のXAMLコードの「冗長な書き方」を見てもらうと、ImageコントロールのSourceプロパティに(前述したImageSourceオブジェクトではなく)UriImageSourceオブジェクトを設定している。
UriImageSourceクラスはImageSourceクラスを継承しており、Uriプロパティが追加されている。上のコードのようにURIを指定するだけで使えるのだ(ImageSourceクラスにはUriプロパティがないので、上のコードのような記述はできない)。
コードビハインドでは、次のコードのように書ける。
// XAMLコード側には、「Image1」という名前のImageコントロールが配置してある
// 表示したい画像のURL
string url = "……省略……";
// 簡単な書き方
Image1.Source = ImageSource.FromUri(new Uri(url));
// UriImageSourceを使ってもよい
Image1.Source = new UriImageSource
{
CachingEnabled = true,
Uri = new Uri(url)
};
// 暗黙の型変換が働くので、次のようにURL文字列を直接与えてもよい
Image1.Source = url;
コードビハインドでは、ImageSourceクラスのFromUriメソッドを使うと簡単である。FromUriメソッドは、ImageSourceオブジェクトを返す。
また、暗黙の型変換が用意されているので、上のコードの最後にあるように、URL文字列をImageコントロールのSourceプロパティに直接代入するコードも書ける。
XAMLコードと同様にUriImageSourceクラスを使ってもよいが、ちょっと冗長になる。UriImageSourceクラスを使う場合にはキャッシュの制御ができる(ただし本稿執筆時点では、CachingEnabled=falseにすると例外になってしまった)。
なお、ImageコントロールのSourceプロパティへの代入は、非同期に実行される。代入し終わってから、非同期にWebアクセスが実行されるのだ。そのWebアクセス中にはIsLoadingプロパティがtrueになる。それを利用して、画像が取得されるまでの間にプレースホルダーを表示することも可能だ(コード例は後述)。
実際の例として、以上で説明したコードを試してみよう。
ソリューションを新しく作るときに[Blank Xaml App (Xamarin.Forms Portable)]を選ぶ。そのPCLプロジェクトにあるMainPage.xamlファイルの内容を次のように変更する。
<?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:local="clr-namespace:dotNetTips1159"
x:Class="dotNetTips1159.MainPage">
<!--<Label Text="Welcome to Xamarin Forms!"
VerticalOptions="Center"
HorizontalOptions="Center" />-->
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness" iOS="0,20,0,0" />
</ContentPage.Padding>
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Image">
<Setter Property="Aspect" Value="AspectFit" />
<Setter Property="HeightRequest" Value="50" />
<Setter Property="VerticalOptions" Value="StartAndExpand" />
</Style>
<Style TargetType="Label">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="VerticalOptions" Value="EndAndExpand" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
<Label Text="Xamlで表示" />
<Image Source="/ait/images/gyoumu_link_btn.gif" />
<Label Text="コードで表示" />
<Image x:Name="Image1" />
</StackLayout>
</ContentPage>
次に、コードビハインドのMainPage.xaml.csファイルに次のようなコードを追加する。ここでは、Webアクセス中にプレースホルダーとしてImageコントロールの背景色を変えている。
public MainPage()
{
InitializeComponent();
string url = "/ait/subtop/features/"
+ "dotnet/images/dotnettips_index/title.png";
SetImageAsync(url);
}
private async void SetImageAsync(string url)
{
// Sourceプロパティへのセットは非同期に実行される
Image1.Source = ImageSource.FromUri(new Uri(url));
// プレースホルダーの表示
await Task.Delay(300); // 300ミリ秒待って、
if (Image1.IsLoading) // Webアクセス中だったら、
{
Image1.BackgroundColor = Color.Green; // Imageコントロールの背景色を緑にする
while (Image1.IsLoading) // Webアクセスが続いている間は、
await Task.Delay(100); // 100ミリ秒ずつ待機し、
Image1.BackgroundColor = Color.Transparent; // 完了したら背景色を透明に戻す
}
}
上のコードのSetImageAsyncメソッドの中で、Webから画像を取得して表示している。さらに、Webアクセスしている間は、Imageコントロールの背景色を緑色に変えている。
ImageコントロールのSourceプロパティへのセットは非同期に実行される。しかし、その後のコードでIsLoadingプロパティの監視をしようとすると、その部分は自前で非同期処理を書かねばならない。XamarinのC#もasync/await構文に対応しているので、上のコードのように簡単に書ける。
これで実行してみると、次の画像のようになる。この画像では分からないが、下側のImageコントロールは画像が出てくるまで緑色になっている(初回実行時のみ。2回目以降はキャッシュから表示するので直ちに画像が出る)。
URLを指定してImageコントロールに画像を表示するには、XAMLコードではSource属性にURLを書くだけでよい。コードビハインドでも同様だが、IsLoadingプロパティを活用してプレースホルダーを表示したりできる。
利用可能バージョン:Visual Studio 2015以降
カテゴリ:Xamarin 処理対象:Xamarin.Forms
関連TIPS:Xamarin.Forms:プロジェクトにXamlページを追加するには?
関連TIPS:Xamarin.Forms:プラットフォームに応じて画面の一部を変えるには?
関連TIPS:Xamarin.Forms:コントロールを等間隔に配置するには?
Copyright© Digital Advantage Corp. All Rights Reserved.