ディーバ Blog

大阪発 C#の会社、株式会社ディーバの Blog です。

共通のコードで iOS/Android/UWP のダイアログを表示できる ACR User Dialogs for Xamarin and Windows

ACR User Dialogs for Xamarin and Windows

ACR User Dialogs for Xamarin and Windows を使うと、MvvmCrossMVVM パターンの ViewModel のコード(PCL プロジェクト側)から、ダイアログを表示するコードを簡単に書けます。MvvmCross 用のプラグインもあり MvvmCross のサイトからも紹介されいています

ダイアログ (Alert) だけでなく、ローディング画面なども呼び出せます。機能は次の通り。

  • Action Sheet (multiple choice menu)
  • Alert
  • Confirm
  • Loading
  • Login
  • Progress
  • Prompt
  • Toasts

NuGet からプロジェクトにインストールします。ViewModel 側(PCL プロジェクト)と、View 側の各プラットフォームのプロジェクトそれぞれにインストールします。

公式のサンプルコードは GitHub の examples にあります。

Dialog

using using Acr.UserDialogs;

UserDialogs.Instance.Alert("たこ焼きです", "確認", "OK");

f:id:jz5_diva:20160421102435p:plain

Action Sheet

using using Acr.UserDialogs;

var config = new ActionSheetConfig();
config.Title = "メニュー";
config.Add("たこ焼き", () => {/* Do something */ });
config.Add("お好み焼き", () => {/* Do something */ });
UserDialogs.Instance.ActionSheet(config);

f:id:jz5_diva:20160421103041p:plain

Confirm

using using Acr.UserDialogs;

var config = new ConfirmConfig();
config.Title = "確認";
config.Message = "たこ焼きを購入します";
config.OnConfirm = (result) =>
{
    /* Do something */
};
config.OkText = "購入";
config.CancelText = "キャンセル";
UserDialogs.Instance.Confirm(config);

f:id:jz5_diva:20160421102456p:plain

おわりに

上記以外にももう少し細かなオプションや、非同期呼び出しなども用意されています。使用感として、View 側に一切コードが不要のため手軽で便利ですが、Android ではスタイルを適用できないなど、少しこだわったアプリでは使いづらいところもあります。

Xamarin.iOS の Google Maps で独自マーカーと情報ウィンドウの表示

Xamarin.iOS の Google Maps でマーカー画像の変更と、カスタムした情報ウィンドウ (InfoWindow) の表示方法です。

Google Maps の表示方法 はこちらから。

マーカーと情報ウィンドウの表示

デフォルトのマーカーと情報ウィンドウの場合。Title・Snippet プロパティを指定すれば情報ウィンドウもタップ時に表示されます。

var marker1 = new Marker()
{
    Title = "株式会社ディーバ",
    Snippet = "大阪発 C# の会社",
    Position = new CLLocationCoordinate2D(34.686564, 135.503155),
    Map = mapView
};

f:id:diva_osaka:20160419162542p:plain

マーカーの画像の変更

Icon プロパティを変更するだけです。InfoWindowAnchor プロパティで、情報ウィンドウの表示位置を調整できます。

var marker1 = new Marker()
{
    Title = "株式会社ディーバ",
    Snippet = "大阪発 C#の会社",
    Position = new CLLocationCoordinate2D(34.686564, 135.503155),
    Icon = UIImage.FromBundle("ic_place_48pt"),
    InfoWindowAnchor = new CGPoint(0.5, 0),
    Map = mapView
};

f:id:diva_osaka:20160419162552p:plain

カスタムした情報ウィンドウの表示

すべて置き換え

情報ウィンドウすべてを独自に置き換える場合は、MarkerInfoWindow プロパティを使って View を返すメソッドを指定します。

mapView.MarkerInfoWindow = new GMSInfoFor((view, marker) =>
{
    var label = new UILabel();
    label.Text = marker.Title;
    label.BackgroundColor = UIColor.Red;
    label.SizeToFit();
    return label;
});

f:id:diva_osaka:20160419164322p:plain

xib ファイルに見た目を定義して、View として返すには、次のようになります(参考: Using the View .xib Template - Xamarin)。

mapView.MarkerInfoContents = new GMSInfoFor((view, marker) =>
{
    var arr = NSBundle.MainBundle.LoadNib("InfoWindowView", null, null);
    return Runtime.GetNSObject<UIView>(arr.ValueAt(0));
});

中身のみ置き換え

情報ウィンドウの中身のみ独自に置き換える場合は、MarkerInfoContents プロパティを使って View を返すメソッドを指定しますが、吹き出しが隠れてしまうことがあり、いい感じにできません。

mapView.MarkerInfoContents = new GMSInfoFor((view, marker) =>
{
    var v = new UIView();
    v.Frame = new CGRect(0, 0, 200, 100);
    v.BackgroundColor = UIColor.Red;
    return v;
});

f:id:diva_osaka:20160419165306p:plain

解決方法は、不明です。View が正方形であれば(?)、正しく吹き出し内に表示されるようです。

Xamarin.iOS で Google Maps の表示

Google Maps SDK for iOS を利用できる Xamarin.Google.iOS.Maps ライブラリを NuGet からインストールします。

古くから Xamarin 用コンポーネントがあったようですが、一時期 Google Maps のアップデートに対応できず使えない状態だったようです。

API Key の設定

Google Developer Console から Google Maps SDK for iOS を有効にし、iOS API キーを取得します。

キーは、AppDelegate 内で設定します。

using Google.Maps;

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    MapServices.ProvideAPIKey("iOS API Key");
    ...
}

地図の表示

ViewController 内で生成して View に表示します。

using Google.Maps;
using CoreGraphics;

private MapView mapView;

public override void ViewDidLoad()
{
    base.ViewDidLoad();

    var camera = CameraPosition.FromCamera(34.686564, 135.503155, 6);
    mapView = MapView.FromCamera(CGRect.Empty, camera);

    View = mapView;
}

古いコードサンプルでは、mapView の StartRendering, StopRendering メソッドを記載していますが、deprecated のメソッドで不要のようです。

マーカーの表示

var marker1 = new Marker()
{
    Title = "株式会社ディーバ",
    Position = new CLLocationCoordinate2D(34.686564, 135.503155),
    Map = mapView
};

f:id:jz5_diva:20160419102955p:plain

リンク

Xamarin.Android + MvvmCross でアイコン付きリスト形式の AlertDialog を表示

Xamarin.Android と MvvmCross 4 でリスト形式の AlertDialog を表示します。

リスト形式の AlertDialog

普通のリスト形式の場合。MvvmCross は関係ありません。

f:id:jz5_diva:20160418154254p:plain

var alert = new AlertDialog.Builder(this);
alert.SetTitle("Title");

var items = new string[]
{
    "Item 1",
    "Item 2",
    "Item 3",
};

alert.SetItems(items, (s, a) =>
{
    var selectedItem = items[a.Which];
});

alert.Show();

アイコン付きリスト形式の AlertDialog

f:id:jz5_diva:20160418154259p:plain

AlertDialog の表示

呼び出し部分から。

var alert = new AlertDialog.Builder(this);
alert.SetTitle("Title");

var items = new List<ListItem>()
{
    new ListItem("Item 1", "res:ic_call_black"),
    new ListItem("Item 2", "res:ic_chat_black"),
    new ListItem("Item 3", "res:ic_email_black"),
};

var adapter = new ListAdapter(this, (IMvxAndroidBindingContext)BindingContext);

adapter.ItemsSource = items;

alert.SetAdapter(adapter, (s, a) =>
{
    var selectedItem = items[a.Which];
});

alert.Show();

MvxImageView の ImageUrl にリソース画像を指定するには「res:」を付けます。

リスト項目の View

アイコンとテキストを表示する MvxImageView と TextView を配置した axml ファイルを用意します。ImageUrl と Text プロパティを Binding 指定しています。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="56dp">
    <MvxImageView
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        android:layout_marginLeft="24dp"
        android:layout_width="40dp"
        android:layout_height="40dp"
        local:MvxBind="ImageUrl ImageUrl" />
    <TextView
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="24dp"
        android:gravity="center_vertical"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:ellipsize="end"
        android:text="example"
        local:MvxBind="Text Text"
        android:textColor="@color/primary_text"
        android:textSize="16sp" />
</LinearLayout>

リスト項目の Class

リストの項目を表すクラスを作ります。

private class ListItem
{
    public string Text { get; set; }

    public string ImageUrl { get; set; }

    public ListItem(string text, string imageUrl)
    {
        this.Text = text;
        this.ImageUrl = imageUrl;
    }
}

カスタム Adapter

カスタム Adapter を作り、GetView 内で作成した View の Resource ID を指定します。

private class ListAdapter : MvxAdapter
{
    public ListAdapter(Context context, IMvxAndroidBindingContext bindingContext) : base(context, bindingContext)
    {
    }

    protected override View GetView(int position, View convertView, ViewGroup parent, int templateId)
    {
        templateId = Resource.Layout.ListItem; // 作成したリスト項目の View
        return base.GetView(position, convertView, parent, templateId);
    }
}

オレたちと Visual Studio との関係を話そう

2016/3/5 開催の VSUG DAY ~THE FINAL~ で、株式会社ディーバ 代表取締役 青柳臣一が、パネルディスカッション「オレたちとVisual Studioとの関係を話そう」に参加いたしました。

http://event.shoeisha.jp/seminar/20160305