Xamarin.Forms に ImageButton というコントロールが追加されたので少し見てみました。
使い方は公式ドキュメントがあります。(機械翻訳がすごいですが)
■ これまでの方法との比較
Image を Button として(Button の様に)扱う方法はこれまでにもいくつかありました。
- Button の Image プロパティに画像を設定する
- Image の TapGesture の Tapped イベントを使う
これらの方法と比べて ImageButton がどうななるのか見比べてみます。
単純に並べてみる
ImageButton
という名前でソリューションを作成しました。
上から、
- Button に Image を設定。テキスト付
- Button に Image を設定。テキストなし
- ImageButton
- Image に TapGesture を設定
です。
<?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:ImageButton" x:Class="ImageButton.MainPage"> <StackLayout VerticalOptions="Center"> <Button Image="RedBull.png" Text="ボタン" HeightRequest="100" Clicked="OnTap"/> <Button Image="RedBull.png" HeightRequest="100" Clicked="OnTap"/> <ImageButton Source="RedBull.png" HeightRequest="100" Clicked="OnTap"/> <Image Source="RedBull.png" HeightRequest="100"> <Image.GestureRecognizers> <TapGestureRecognizer Tapped="OnTap"/> </Image.GestureRecognizers> </Image> </StackLayout> </ContentPage>
Button に Image を設定するパターンは正しいのですが扱いが難しそうです。ImageButton はそれっぽいですね。
[ 補足 ] 画像ファイルの追加
画像ファイルは、Android プロジェクトでは、Resources/Drawable
フォルダーに、iOS プロジェクトでは Resources
フォルダーに追加します。
■ Aspect プロパティ
ImageButton には Button の Image にはない Aspect プロパティがあります。
<?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:ImageButton" x:Class="ImageButton.MainPage"> <StackLayout VerticalOptions="Center"> <Button Image="RedBull.png" Text="ボタン" HeightRequest="100" Clicked="OnTap"/> <Button Image="RedBull.png" HeightRequest="100" Clicked="OnTap"/> <ImageButton Source="RedBull.png" HeightRequest="100" Aspect="Fill" Clicked="OnTap"/> <Image Source="RedBull.png" HeightRequest="100"> <Image.GestureRecognizers> <TapGestureRecognizer Tapped="OnTap"/> </Image.GestureRecognizers> </Image> </StackLayout> </ContentPage>
Aspect="Fill"
だと、画像の縦横の比率を維持せず領域いっぱいに表示するということなので、設定どおりの表示ですね。このあたりも Button の Image プロパティよりも扱いやすそうです。
■ 横幅も指定
Button の Image プロパティが扱いが難しそうなのは、画像の縦横と Button の縦横が合っていないからでは? という疑問もあるかもしれません。横幅も指定して試してみましょう。
<?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:ImageButton" x:Class="ImageButton.MainPage"> <StackLayout VerticalOptions="Center"> <Button Image="RedBull.png" Text="ボタン" HeightRequest="100" WidthRequest="100" HorizontalOptions="Center" Clicked="OnTap"/> <Button Image="RedBull.png" HeightRequest="100" WidthRequest="100" HorizontalOptions="Center" Clicked="OnTap"/> <ImageButton Source="RedBull.png" HeightRequest="100" WidthRequest="100" HorizontalOptions="Center" Clicked="OnTap"/> <Image Source="RedBull.png" HeightRequest="100"> <Image.GestureRecognizers> <TapGestureRecognizer Tapped="OnTap"/> </Image.GestureRecognizers> </Image> </StackLayout> </ContentPage>
とりあえず、これから作るアプリであればこれまでのやり方は捨てて ImageButton を使っておくのが良さそうです。
■ [ おまけ ] 画像を共通化する
Xamarin.Forms では画像は、プラットフォームごとのプロジェクトのリソースを使用します。
これは、正しい仕様で確かにそうあるべきです。しかし現実には画像ファイルも共通化したいという要求も多いものです。方法はあります。
特に ImageButton だけの話でもないですが、ついでに書いておきます。
※.NET Standard 方式でソリューションを作成しているものとします。
コード
IMarkupExtension インタフェースを実装した ImageResourceExtension
クラスを作ります。
using System; using Xamarin.Forms; using Xamarin.Forms.Xaml; namespace ImageButton { // 共通プロジェクトのリソース画像を表示のためのマークアップ拡張 [ContentProperty("Source")] public class ImageResourceExtension : IMarkupExtension { // リソースファイルのパスを取得または設定する public string Source { get; set; } // Source で指定されたリソース画像を取得する public object ProvideValue(IServiceProvider serviceProvider) { if (Source == null) return null; // リソースから指定のパスの画像を読み込む var imageSource = ImageSource.FromResource(Source); return imageSource; } } }
Source プロパティに ImageButton Source="{local:ImageResource ImageButton.RedBull.png}"
の様に設定します。
<?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:ImageButton" x:Class="ImageButton.MainPage"> <StackLayout VerticalOptions="Center"> <Button Image="RedBull.png" Text="ボタン" HeightRequest="100" WidthRequest="100" HorizontalOptions="Center" Clicked="OnTap"/> <Button Image="RedBull.png" HeightRequest="100" WidthRequest="100" HorizontalOptions="Center" Clicked="OnTap"/> <ImageButton Source="{local:ImageResource ImageButton.RedBull.png}" HeightRequest="100" WidthRequest="100" HorizontalOptions="Center" Clicked="OnTap"/> <Image Source="RedBull.png" HeightRequest="100"> <Image.GestureRecognizers> <TapGestureRecognizer Tapped="OnTap"/> </Image.GestureRecognizers> </Image> </StackLayout> </ContentPage>
共通部分のプロジェクトにリソースとして画像ファイルを追加します。この際、ビルドアクションを EmbeddedResource に設定する必要があります。忘れやすいので注意してください。
今回は、違いが分かるように画像に「Core」という文字を書き加えたものを追加しました。
実行するとこのように、共通部分のリソース画像が使われます。