Xamarin.Forms イメージ

2015.12.30

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

1 はじめに

Xamarin.Formsの、ビューの1つであるImageは、画像を表示するためのコントロールです。

参考:Xamarin Developers Guide 「Working with Images」
http://developer.xamarin.com/guides/cross-platform/xamarin-forms/working-with/images/

2 イメージの指定 Source

プロパティSource(ImageSource型)には、表示する画像を指定します。

指定の方法は、画像の配置場所によって次の3種類があります。

各プラットフォーム(ローカル) 各プラットフォームのプロジェクトにリソースとして配置します。
インターネット インターネット上に配置し、ダウンロードして使用します。
共有プロジェクト(ローカル) 共有プロジェクト(PCL)にリソースとして配置します。

(1) 各プラットフォーム上に配置する場合

App.cs

public class App : Application {
    public App() {
        MainPage = new MyPage();
    }
}

class MyPage : ContentPage {
    public MyPage() {
        Content = new Image {
            Source = "classmethod.png"

            //この書き方でもOK
            //Source = ImageSource.FromFile("classmethod.png")

            //この書き方でもOK
            //Source = FileImageSource.FromFile("classmethod.png")
        };
    }
}
Android iOS Windows Phone
001 002 003

ローカルの画像ファイルは、Androidの場合は、Resources/Drawableの階層下、iOSの場合は、Resourcesの階層下に配置します。WindowsPhoneではカレントになりますが、特定のフォルダにまとめることも可能です。

なおコードは、PCL(一か所)で書けますが、画像ファイルは、プラットフォームごと(3か所)に置く必要があります。

Android iOS Windows Phone
005 004 006

(2) インターネット上に配置する場合

App.cs

public class App : Application {
    public App() {
        MainPage = new MyPage();
    }
}

class MyPage : ContentPage{
    class MyPage : ContentPage {
        public MyPage() {
            var uri = "http://www.sapporoworks.ne.jp/main.jpg";
            Content = new Image {
                Source = ImageSource.FromUri(new Uri(uri))

                //この書き方でもOK
                //Source = uri

                //この書き方でもOK
                //Source = new UriImageSource {
                //    Uri = new Uri(uri),
                //    CachingEnabled = false
                //}
           };
        }
    }
}

UriImageSourceには、キャッシュ機能があります。

Android iOS Windows Phone
007 008 009

(3) 共有プロジェクトに配置する場合

PCLのリソースとして定義すると、画像の配置も一か所だけでよくなります。

ディレクトリなどの階層下にまとめるのも自由なので、Formsを使用するなら、この要領が一番お薦めです。

App.cs

public class App : Application {
        public App() {
            MainPage = new MyPage();
        }
    }
    class MyPage : ContentPage {
        public MyPage() {
            Content = new Image {
                Source = ImageSource.FromResource("App1.Images.classmethod.png")
            };
        }
    }

なお、画像のビルドアクションは、「埋め込まれたリソース」に設定する必要があります。 ビルドアクションは、画像を右クリックして指定できます。

010

Android iOS Windows Phone
011 012 013

3 イメージの配置 Aspect

Imageのエリアに画像をどのように展開するかを、プロパティAspectに設定します。

Aspect.AspectFill(デフォルト) 画像の縦横比を保持したまま、Imageに収まるように縮小する
Aspect.AspectFit 画像の縦横比を保持したまま、Image全体に表示する(画像の一部が欠ける)
Aspect.Fill 画像の縦横比を無視して、Image全体に表示する(画像の縦横比が壊れる)

サンプルは、3種類のAspect値によるImageの比較です。

App.cs

public class App : Application {
    public App() {
        MainPage = new MyPage();
    }
}

class MyPage : ContentPage {
    public MyPage() {
        var width = Device.OnPlatform(360, 360, 480);
        var height = Device.OnPlatform(120, 120, 180);
        var layout = new AbsoluteLayout();
        const int x = 10;
        var y = 30;
        foreach (Aspect aspect in Enum.GetValues(typeof(Aspect))) {
            layout.Children.Add(new Label { Text = aspect.ToString() }, new Point(x, y));
            y += 30;
            layout.Children.Add(CreateImage(aspect), new Rectangle(x, y, width, height));
            y += height + 30;
        }
        Content = layout;
    }

    static Image CreateImage(Aspect aspect) {
        var image = new Image {
            Source = ImageSource.FromResource("App1.Images.classmethod.png"),
            BackgroundColor = Color .FromRgb(240,240,240),
            Aspect = aspect
       };
       return image;
    }
}
Android iOS Windows Phone
014 015 016

透明度 Opacity

プロパティOpacity(0.0~1.0)で画像の透明度を指定します。 サンプルは、同じ画像を5段階の透明度で配置したものです。

App.cs

public class App : Application {
    public App() {
        MainPage = new MyPage();
    }
}

class MyPage : ContentPage {
    public MyPage() {
        //アブソレートレイアウトの生成
        var layout = new AbsoluteLayout();

        //画像とラベルを5個配置
        var y = 40;
        var x = 20;//左余白
        const int size = 120; // 画像のサイズ
        for (var i = 0; i < 5; i++) {
            var opacity = 0.25 * i; //透明度
            //透明度を表示するためのラベルを生成
            var label = new Label {
                Text = String.Format("Opacity={0}", opacity)
            };
            //ラベルをレイアウトに配置
            layout.Children.Add(label, new Point(x, y));
            y += 10; // ラベルの分のオフセットを移動
            //前景画像の作成
            var imageFront = new Image {
                Source = ImageSource.FromResource("App1.Images.classmethod.png"),
                Aspect = Aspect.Fill,
                Opacity = opacity,//透明度
            };
            //前景画像をレイアウトに配置
            layout.Children.Add(imageFront, new Rectangle(x, y,size,size));
            // 配置のオフセットを移動
            y += size-50; 
            x += 50;
        }
        Content = layout; //アブソレートレイアウトをContentにセットする
    }
}
Android iOS Windows Phone
018 017 019

4 レイアウト OptionLayout

レイアウトは、イメージに固有のプロパティではありませんが、参考のため列挙させて頂きます。

(1) Center・End・Fill・Start

HorizontalOptions(横方向)及びVerticalOptions(縦方向)にLayoutOptionを指定することで、その配置を指定できます。

  • Center 中央揃え
  • End 最終(右)揃え
  • Fill 全部使用
  • Start 最初(左)揃え

次のサンプルは、HorizontalOptions(横方向)に各レイアウトを指定したものです。

App.cs

public class App : Application {
    public App() {
        MainPage = new MyPage();
    }
}

class MyPage : ContentPage {
    public MyPage() {
        var ar = new[]{
            LayoutOptions.Center,
            LayoutOptions.End,
            LayoutOptions.Fill,
            LayoutOptions.Start};


        var layout = new StackLayout();
        foreach (var op in ar) {
            layout.Children.Add(new Label {
                Text = op.Alignment.ToString(), // LayoutOption名を表示する
            });
            var img = new Image {
                Source = ImageSource.FromResource("App1.Images.classmethod.png"),
                BackgroundColor = Color.FromRgb(240,240,240),
                HorizontalOptions = op, // 4種類のLayoutOptionをそれぞれ設定する
                WidthRequest = 100,
                HeightRequest = 100
            };
            layout.Children.Add(img);
        }

        Padding = new Thickness(0, Device.OnPlatform(20, 0, 0), 0, 0);
            Content = layout;
   }
}
Android iOS Windows Phone
020 021 022

(2) Fill・FillAndExpand

レイアウトオプションには、AndExpandが付いたものと、そうでないものがありますが、この違いは、余白を埋めるかどうかにあります。

次の例は、スタックレイアウトに同じイメージを3つ並べ、真ん中のイメージに、Fillを指定した場合とFillAndExpandを指定した場合の違いを示したものです。

App.cs

public class App : Application {
    public App() {
        MainPage = new MyPage();
    }
}

class MyPage : ContentPage {
    public MyPage() {
        var layout = new StackLayout();
        for (var i = 0; i < 3; i++) {
           var img = new Image {
               Source = ImageSource.FromResource("App1.Images.classmethod.png"),
               BackgroundColor = Color.FromRgb(240, 240, 240)
           };
           if (i == 1) {
               img.VerticalOptions = LayoutOptions.Fill; // Fillの場合
               //img.VerticalOptions = LayoutOptions.FillAndExpand; // FillAndExpandの場合
           }
           layout.Children.Add(img);
        }
        Content = layout;
    }
}
Fillの場合 FillAndExpandの場合
023 024

5 まとめ

今回は、Xamarin.Fomrsにおけるイメージビューについて確認してみました。 イメージについては、枯れているというか、必要な機能は網羅されているので、これをレンダラー拡張して・・・というようなパターンは少ないかと思います。

また、「ImageSource.FromResource」でリソース指定することで、共通プロジェクトだけで画像リソースを管理できるので、できれはこの方法を積極的に使用するべきではと思います。

本記事は、2015年12月29日現在で最新の Xamarin.Forms 2.0.0.6490を使用して作成されています。

6 参考リンク


この辺でXamarin導入による 効果と限界をしっかり把握してみよう MVP Community Camp 2015
Xamarin記事一覧(SAPPOROWORKSの覚書)