Azure Mobile Service は Nuget版とXamarin Components版があるので注意

半日ほど嵌ったのでメモ書き。

Azure Mobile Services を扱うときにはライブラリを使うのが常なのですが、Microsoft.WindowsAzure.MobileServices は Nuget版と Xamarin Componets 版の2種類があります。

Azure ポータルの「Xamarin」でダウンロードするサンプルは Xamarin Componets 版

image

Windows ストアサンプルは Nuget版

image

Nugetでダウンロードできるのは当然 Nuget 版。

image

ソリューションエクスプローラーで「Componets」→「Edit Components」で拾えるのが Xamarin Components 版

image

image

こんな感じでその他のコンポーネントもダウンロードできる。

image

で、普段はどちらかしかダウンロードしないので、はまることはあまりないのですが、こんな風に Mobile Services を PCL 化して、iOS/Android/Windowsストアで共有しようとしたときに、PCL では Nuget版しかダウンロードできない。けれども、iOS/Android のほうで、Xamarin Componets 版をインストールすると、実行時にエラーがでます。変だなー、ってことに。

image

Xamarin Componets 版では、こんな感じに。

image

サンプルコードもどちらを使っているのか判別しづらいのですが、「CurrentPlatform.Init();」を使っている場合が Xamarin Componets版、使っていないのが Nuget版です。Nuget版には CurrentPlatform というクラスがありません。そのほか実装されているクラスは同じなのか?

追記 2014/04/17
いや、どちらも同じく CurrentPlatform.Init() はある。なので、区別がつかないかも。

Xamarin で Windows Azure モバイルサービスを使う(その1) – Qiita
http://qiita.com/amay077/items/40bd5918284fd40d0edc

MobileServiceClient がメインクラスですが、これを使う前に CurrentPlatform.Init() が必要です(DI だか IoC だかですかね)。

かも。

追記 2014/04/17 どちらもソースコードは https://github.com/Azure/azure-mobile-services になってる。

Nuget 版で作ったものは、こちら。

moonmile/XamarinAzureMobile · GitHub
https://github.com/moonmile/XamarinAzureMobile

ところで、アプリケーションキーって、サンプルをダウンロードしてみるしかないんですかね? Azure ポータルに見当たらない…と思ったけど、「モバイルサービス」→「キーの管理」で見れる。

カテゴリー: Xamarin | Azure Mobile Service は Nuget版とXamarin Components版があるので注意 はコメントを受け付けていません

Windows 8.1 Update でプルダウメニューが左開きになった時の対処

と、Windows 8.1 Update のせいか定かではないのですが、4/9 の Windows Update でなった現象として、こんな風にプルダウンメニューが左開きになることがあります。

20140410_03

メニューって、右へ右へと開いていたはずなのに、突如として左へ左へと開き始めます。突然、Microsoft 社が方針を変えたのか?と思って色々調べて、英語版Windows 8.1でもUpdateをかけて調べていたのですが、原因が分からず。バグかな?と思っていたのですが、

 

とのアドバイスがッ!!! コントロールパネルで「タブレットPC」で検索するとありました。どうしてなのか謎なのですが、デスクトップPCがタブレットPCに誤認識されて(タッチタイプじゃないディスプレイなんですけど)、利き手の設定が「右きき」になっています。このために、左側にメニューが表示されていたんですね。

image

そんな訳で、ここの設定を「左きき」に直すと、無事いつも通りにメニューが右開きに戻りました。どの Windows Update でこうなってしまったのか分からないのですが、誤認識されない場合はコントロールパネルで「タブレットPC」を検索しても出てきません。この場合は、いつも Windows Update をしても右開きのままです。

コントロールパネルでみつからないけど、メニューは左開きという変な状態になっている場合は、レジストリを直接書き換えます。「MenuDropAlignment」で検索して、「0」(左きき)にします。PC を再起動して反映すればOK。

image

調べてみると、結構よくある誤認識らしいですね。再起動したときに、↓のように「タッチキーボード」が出ていると誤認識しているようです。確か起動時にキーボードを認識でないときに出るので、日本語キーボード全般で出てるのかも。

image

ついに Microsoft は Windows 8.1 Update で普通の PC をタブレット PC にする技術を発明したッ!!! のかもしれませんね。あの Windows 8 の発売の感動をもう一度…なのか?

カテゴリー: 開発 | Windows 8.1 Update でプルダウメニューが左開きになった時の対処 はコメントを受け付けていません

Splashtopを使ってWindows PCからMacへリモート接続する

Visual Studio で Xamarin.iOS を使っていると、デザイナとiOSシミュレータは Mac 上で動くために Mac の操作が必須になってきます。2台並べて作業をすればよいのですが、マウスとキーボードを置くスペースは無駄だし、いちいちマウスを持ち替えるのも面倒です。他には、Xamarin Studio for Mac で完結させてしまう。Mac に Fusion などの仮想環境を入れて、Windows + Visual Studio を仮想環境で動かす。という方法もあるのですが、まあ、高機能な Windows デスクトップを使いたいわけで(慣れとか、PC のほうが安いってのもあるけど)、普段使いは Windows なので、Mac へリモートデスクトップで操作をしたい訳です。

で、いままでは VNC を使って Mac の画面を操作していたのですが、VNC の描画が遅くて結構もたついてしまうのと、mac mini の場合は PC 側の jis 109 キーボードの認識が変で「@」マーク等のキーコードが Mac に伝えられないという不都合があります(Mac book Air などでは、そういうことはありません)。そんな訳で、最近 splashstop を使い始めました。

トップリモートデスクトップアプリ | iPad からコンピューターにアクセス | Splashtop Personal | Splashtop って、以前 iPad から PC へリモート接続ができる、ってんで話題になってたもので、Apple Store では「splashtop 2」が 500円になってます。iTunes の App Store で配信中の iPhone、iPod touch、iPad 用 Splashtop 2 – Remote Desktop 以前のバージョンは 85円だった気もするのですが、それはさておき。ちなみに、iPad から艦これができるっていう話題もありますね。SplashtopのIP直打ち設定で艦これリモートプレイが簡単にできてしまった | はげあたま.org どうせならば、PC 側に WPF で iPad のサイズで艦これビューアを作って接続するといいかも、とか。まあ、WiFi が必須なんですが。

で、私の場合は、Mac をホスト/サーバー(Splashtopでは「Streamer」)にして、Windows PC をクライアントにします。この環境は無料で構築できます。ただし、条件があって「インターネットに接続していて、splashtop へログインできる環境が必要」です。接続するときにログインIDを求められるので、外部接続が必須ですね。なので、ローカルに閉鎖された状態のプライベートネットワークではダメかも。まあ、そういう場合は VNC とか他のリモート接続の環境を用意するとして。

■インストール方法

http://www2.splashtop.com/ja/personal からパーソナル版をダウンロードします。

image

クライアント(リモート接続するPC)のアプリをダウンロードしてインストール

image

Streamer(リモート接続されるほうのPC/Mac)のアプリをダウンロードしてインストール

image

■Streamer(サーバー)側の設定

単純に起動しておけばOKです。接続されるとこんな感じになります。

image

Mac Book Air の場合、カバーを閉じて作業をすることが多いので(画面を見る必要がないので立てかけてしまってもいいし)カバーを閉じてもスリープしないようにしておきます。たぶん、Splashtopを入れたときに初期化されているのかもしれません。以下で「スリープ設定の変更」をクリックして、

image

環境設定で省エネルギーを設定しなおします。省電力を考えて「3時間」にしていますが、使っている限りは動くのでこれでよいかと。

image

■クライアントの設定

Windows PC のほうでは、最初にログイン画面が出た後に、こんな風に接続先が出てきます。ポートを探って、なんでも出てしまうので社内ネットワークとかで PC が多い場合は混乱するかも。そのあたりは、Business 版を買うんでしょうか?いや、アカウントでわかれるから大丈夫かな。

image

接続するときの解像度を選択できます。相手の解像度を判別しているのかは分かりません。ちなみに「ローカルコンピューターのネイティブ解像度」を選択しても、画面一杯に広がる訳ではありませんでした。Mac Book Air だからなのかな。

image

うまく接続ができると、こんな風に表示されます。ウィンドウを小さくすると、そのまま画面が小さくなるので、隅において監視したいときは便利です。タイトルの↓に「v」がにはメニューがあります。「100%」表示に戻すときに便利ですね。「切り替え画面」というのがあるので、マルチディスプレイに対応しているのかもしれません。

image

Windows 8.1 から Mac に接続していると、途中でクライアントのウィンドウが固まります。何故かよくわからないのですが、設定で「ネットワークに最適化」を OFF にすると直りました。通常は有線LANを使うからこれでいいと思います。クライアントには「Windows ストアアプリ版」があるのですが、どうなんだろう…デスクトップ版で十分な気がするんですが。

image

iPad から Mac/Windows への [D] 爆速リモートデスクトップSplashtop 2でMacとの付き合い方が変った! あたりが詳しいです。

そうそう、splashtop と Windows 標準のリモートデスクトップの違いは、リモートデスクトップが PC を占有してしまうけど、splashtop の場合は占有しないことです。VNC接続でもそうなのですが、どちらの PC/Mac でもマウスとキーボードの操作が可能なので、隣においてちょっとだけ Mac のキーボードで操作するってのも可能です。

カテゴリー: 開発 | 2件のコメント

C#とVBでXAMLを共有プロジェクトで使える…かと思ったけどできなかったの巻

C#とVBで共有プロジェクトを使おうと思ったけど、コードのプラグマは #if と #if … Then の違いがあって微妙に違って共有できないので、XAMLファイルを共有しようかと思ってやってみました。そう、*.xaml ファイルだけ共有します。コードビハイドは、それぞれの *.cs, *.vb を参照させます。

image

以下、作成手順

  1. ユニバーサルアプリから、shared プロジェクトを引っこ抜く。
  2. *.shproj に、MainPage.xaml だけ追加する。
  3. MainPage.xaml のクラス名を「XamlShare.MainPage」のように共通で使えるように変更
  4. *.csproj をエディタで開いて、MainPage.xaml.cs から MainPage.xaml を連結させている箇所を消す。
  5. *.csproj をエディタで開いて、XamlShare.Shared.projitems への Import を追加する。
  6. 同様に *.vbproj から MainPage.xaml.cs から MainPage.xaml を連結させている箇所を消す
  7. *.vbproj をエディタで開いて、XamlShare.Shared.projitems への Import を追加する。
  8. C# と VB の namespace を揃える。

とやると、上記の形になります。これで C# のプロジェクトは無事コンパイルができるのですが、VB の場合は、

エラー    1    ファイル “obj\Debug\D:\work\blog\src\XamlShare\XamlShare.Shared\MainPage.xbf” を “bin\Debug\D:\work\blog\src\XamlShare\XamlShare.Shared\MainPage.xbf” にコピーできません。指定されたパスのフォーマットはサポートされていません。    XamlShare.VB

のような謎なエラーを残してビルドができません。obj\Debug\D:\work\… のように変な形でドライブがついてしまっているのでビルド型式がおかしくなっているんでしょうね。共有プロジェクトのために、Update 2 で C# のビルド型式に修正を入れたのだと思います。残念。

よく見ると、VB のほうにはユニバーサルアプリがないという結果に。

image

で、ユニバーサルアプリのある C++ ならば、と思ってやってみるとビルドが通りました。うまくいかなかったと思ったけど、どこか手順をミスしたみたい。

サンプルは XamlShare-v0.2-src.zip から。

これは「空のアプリ」になっているので、後で中身を追加してみましょう。

カテゴリー: 開発 | C#とVBでXAMLを共有プロジェクトで使える…かと思ったけどできなかったの巻 はコメントを受け付けていません

共有プロジェクトをコンソールアプリでも使ってみる

ユニバーサルアプリで使っているSharedプロジェクトをXamarin.iOSで使う | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/5696

の続きです。

コード共有できることが分かったのだから、本当に「ユニバーサルにしてしまおう」という訳で、

  • コンソールアプリ
  • Windows フォームアプリ
  • WPFアプリ
  • Silverlight

も追加してみました。サンプルソースは、こちらから。

image

当たり前ですが、すべて動きます。

コンソールで

image

Windows フォームで

image

WPF で

image

Silverlight で

image

ネタ的に

カテゴリー: 開発 | 共有プロジェクトをコンソールアプリでも使ってみる はコメントを受け付けていません

ユニバーサルアプリで使っているSharedプロジェクトをXamarin.iOSで使う

Visual Studio 2013 Update で追加された「ユニバーサルアプリ」で、

Universal Windows appを見てみた – かずきのBlog@hatena
http://okazuki.hatenablog.com/entry/2014/04/03/220347

この中に「*.Shared」というプロジェクトがあります。このプロジェクトは何をやっているかというと、手っ取り早く言えばファイルをリンクで共有しているだけかなと。であれば、ユニバーサルアプリだけでなくて、Xamarin.iOSやXamarin.Androidとか、他のプロジェクトでも使えるはずで、ちょっと試してみます。

コード共有のプロジェクトは通常のプロジェクトの追加では出てきません。ならば、「ファイル」→「テンプレートのエクスポート」で自作してみれば?と思ったのですが、これを作ってもプロジェクトの追加では出てきません。これが、RC2 だからなのか、先行き追加されるのか解りませんが…仕方がないので *.csporj ファイルを編集します。

  • ユニバーサルアプリのプロジェクトを作成する。
  • *.Shared.csproj をコピーして、自作のプロジェクトファイルを作る。

ここではプロジェクトの名前を「AppShare.Shared」にしておきます。

  • AppShare.Shared.projitmes にリネームする。
  • SharedGUID をユニークになるように変更する。

  • AppShare.Shared.csproj に以下の行を追加する。
  <Import Project="AppShare.Shared.projitems" Label="Shared" />
  • ソリューションエクスプローラーで、AppShare.Shared.csproj を追加する。
  • 参照するプロジェクト(AppShare.ioS.csproj など)に以下の行を追加する。
  • 「参照設定」から追加できないので、これも直接書き換えます。

  <Import Project="..\AppShare.Shared\AppShare.Shared.projitems" Label="Shared" />

うまく追加できると、次の図のように共有コードのプロジェクトが参照できる状態になります。

このプロジェクトはファイル共有しているだけなので、コードだけじゃなくてコントロールなども置けますね。書き方によれば、partial class も置けるし、インターフェースなしで本体を参照する dack コードも書けます。いわゆる、プロジェクトにファイルを追加するときに「リンクとして追加」と同じ機能になると思います。なので、各プロジェクトのシンボル(プラグマ)が使えるということで、切り替えは #if を使えば OK。

チープですが、共有コードに、ShareClass を作っておいて、

using System;
using System.Collections.Generic;
using System.Text;

namespace AppShare.Shared
{
    class ShareClass
    {
        public int Add( int x, int y )
        {
            return x + y;
        }
    }
}

AppShare.Androidプロジェクトのほうでコードを書きます。

void button_Click(object sender, EventArgs e)
{
    var edit1 = FindViewById<EditText>(Resource.Id.editText1);
    var edit2 = FindViewById<EditText>(Resource.Id.editText2);
    var text1 = FindViewById<TextView>(Resource.Id.textView1);

    int x = int.Parse(edit1.Text);
    int y = int.Parse(edit2.Text);
    var obj = new Shared.ShareClass();
    int ans = obj.Add(x, y);
    text1.Text = ans.ToString();
}

AppShare.iOSでも同じ感じで。

partial void clickCalc(MonoTouch.Foundation.NSObject sender)
{
    int x = int.Parse(text1.Text);
    int y = int.Parse(text2.Text);
    var obj = new Shared.ShareClass();
    int ans = obj.Add(x, y);
    lable1.Text = ans.ToString();
}


サンプルコードはこちらから http://1drv.ms/1jbhVNq

ちなみに、Xamarin StudioでAndroidのほうはビルドできるのですが、Xamarin Studio for Mac で iOSのほうはビルドができませんでした。Visual Studio限定の技かも。

カテゴリー: 開発, Android, WinRT, Xamarin, iOS | ユニバーサルアプリで使っているSharedプロジェクトをXamarin.iOSで使う はコメントを受け付けていません

Windows 8.1 Update の内容をざっと

Microsoft Build Developer Conference | April 2 – 4, 2014
http://www.buildwindows.com/ 
Channel 9: Videos about the people building Microsoft Products & Services
http://channel9.msdn.com/#videoHolder

のネタ的に記念に。Windows 8.1 Update は 4/8 にダウンロードできるそうなので、特別な理由がない限りわざわざ MSDN からダウンロードする必要はないのですが。一応、VMWare の Windows 8.1 に入れて試してみました。MSDN からスタンドアローンのアップデートをするときは、解凍した後で ReadMe.txt にインストールの順番が書いてあるのでそれで。私の環境では、 KB2919442 が適用済みだったので大丈夫ですが、エクスプローラーで一番上から(KB番号が若い順)インストールすると嵌るかもしれません。先頭の2つのKBだけが順序が逆なので。

以下は、デスクトップPC に Windows 8.1 Update を入れたときの話。

ちなみに目玉(?)の機能っぽい、スタートメニューのタイル化と、ストアアプリのウィンドウ化は、今回の Windows 8.1 Update には入っていません。ストアアプリのウィンドウ化は、サードパティが商品化していたのでそれの寿命が尽きるのか…とも思われますが、どうなんでしょう?

http://buchizo.files.wordpress.com/2014/04/image28.png

普通に Windows 8.1 を使っている限りはあまり、いらんかなーという感じなのですが、マウスを上に持ってくると Windows デスクトップアプリのようにタイトルと、閉じるボタンが出ます。「_」が最小化ボタンで、「×」が閉じるボタンですね。ツールチップはでませんが。

image

左上のコントロールボックス(という名前だったはず)をクリックするとおなじみのメニューが出ます。ここで「最小化」と「閉じる」が選べますね。実は、「最小化」がアプリを閉じる(中断)で、「閉じる」がアプリが終了なんですが…まあ、英語版の場合は「Minimize」「Close」だから、こっちのほうがいいかも。「最大化」は、画面分割をしている状態だと、全画面に最大化されます。意味合いはあってますね。コントロールボックスをダブルクリックすると、ストアプリが終了できるのは、デスクトップアプリと同じです。分割した状態では「最大化」と「最小化」、「閉じる」しかないので、右に動かしたり左に動かしたりするのはマウスでやることになります。残念…と思ったけど、以下の Alt+Space で動かせます。

image

image

ちなみに、このコントロールボックスは、Alt+Space で出せます。デスクトップからの継承なので統一感はばっちりですね(誉めてます)。あと、Alt+F4 でストアアプリを終了できます。これは、Windows 8.1 でもある機能です(というのをさっき初めて確認しました)

さて、ヘルプを見ると Windows 8.1 の操作があるのですが、残念、アプリの終了方法はドラッグする方法しか書いてありません。これはヘルプのアップデート待ちかと…って、これをアップデートしてたらすごいぞッ!!! 品質的に。4/8 以降のストアアプリのアップデートで、更新されるのかな?

image

おなじみのデスクトップに戻ると、おなじみのスタートボタンの横に「ストア」ボタンが表示されます。ええ、ストアアプリもタスクバーに置かれるようになったので、ここからもストアを起動できます。そういえば、Microsoft の記事に「Window 8 では、ほとんどのユーザーが24時間以内にストアを見つけることができましたッ!!!」とあったので、結構気にしていたんですね。24時間じゃ遅いよッ!!! チャームとかだと全然見つかりません。なわけで、iPad みたく、AppleStore のアイコンを置くわけですよ。いや、正直言って邪魔なので「タスクバーからピン留めを外す」で消え去ってもらう訳ですが、ユーザー的にはデスクトップにアイコンを置く「ゴミ箱の横あたりに置く」ぐらいのずうずうしさは必要かも。慎ましやかですね。

image

さて、ストアアプリがタスクバーに置かれると何が便利かというと、こんな感じでプレビューが出ます。Update 前は、ストアアプリの場合は左のタスクバー(だっけ?)で確認、デスクトップアプリの場合はタスクバーで確認と分かれていたのですが、Update 以後はタスクバーで一括してプレビューが確認できます。便利ですね。

image

でもって、このタスクバー。不便なところもあって、いままでゲームのストアアプリを立ち上げて、おいてボスが来たら Win+D キー一発でデスクトップに戻れたのですが(昔懐かしのボス機能です)、Update 以後はタスクバーにゲームのアイコンが残ってしまうのでばれてしまいますね。注意したいところです。今後はどうするのがいいでしょうか?これはサポートセンターに問い合わせ…ても答えてくれないと思いまふ。

と思ったら、「Windows ストアアプリをタスクバーに表示する」のチェックを外せばよいとのこと。なるほど。Surface RT のようなタブレットの場合は、逆にこのチェックが OFF になっているので、ON にすれば表示されるようになります。

image

ちなみに、今気づいたのですが、Win+T でタスクのタスクの切り替えもストアアプリ込みになります。いままで、Alt+Tab を使うか、Win+Tab でストアアプリだけ、という感じだったので意外と便利かもしれません。いや、マウスでぽちぽちやるために機能追加なのでしょうが、副産物として。

正直、トリプルディスプレイで使っている身としては、ストアアプリのウィンドウ化はあまり必要ないのですが、シングルのノートブックでやっているときは便利なのかなぁ。Alt+Tab で全画面切り替えを普通にやるので、いまひとつ私にはメリットがありません。Windows 8 のデザイン的に、ストアアプリは全画面(あるいは縦長のスナップ)が標準になっているので、デスクトップにウィンドウが出るとしても補助的なものかと。本格的に画面にマッチさせるには、WPFで作るかWindowsフォームになりますよね。そのあたり手軽なウィジットが無くなったので、この穴を埋めるのは誰/何だろう、って気もしてます。まだ、Adobe Air なのかなとか。ああ、Silverlight on Desktop があったはずですがアレは何処行ったんでしょう。ちなみ、Silverlight 自体は、Silverlight 8.1 となって戻ってくるそうなので 藍澤光 http://www.microsoft.com/taiwan/silverlight/ が戻ってくるかも?というか、8人姉妹?それとも8.1人姉妹?

カテゴリー: windows 8.1 | Windows 8.1 Update の内容をざっと はコメントを受け付けていません

Xamarinでコントロールのドラッグに対応する

いわゆる画像をドラッグします。本来はこれがやりたかったのですが、プラットフォームごとに微妙に違うので断念。どうせ C# で言語をそろえるので拡張メソッドが適当なヘルパークラスを作れば統一できそうです。

■Windows ストアアプリの場合

ManipulationDelta を使う。

<Canvas 
    x:Name="canvas"
    ManipulationDelta="canvas_ManipulationDelta"
    HorizontalAlignment="Left" Height="564" Margin="80,10,0,0" Grid.Row="1" VerticalAlignment="Top" Width="1200">
    <Ellipse 
        x:Name="circle"
        ManipulationMode="All"
        Fill="#FF4CE035" Height="100" Canvas.Left="133" Stroke="Black" Canvas.Top="63" Width="100" 
        />
</Canvas>

Canvas で ManipulationDeltaイベントを設定してして、ドラッグ対象のコントロールに ManipulationMode=”All” を指定します。

private void canvas_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
    var el = e.OriginalSource as UIElement;
    var cir = el as Ellipse;
    double x = Canvas.GetLeft(el) + e.Delta.Translation.X;
    double y = Canvas.GetTop(el) + e.Delta.Translation.Y;
    // 画面からはみ出ないようにする
    if (-cir.ActualWidth / 2 <= x &&
        x <= canvas.ActualWidth - cir.ActualWidth / 2 &&
        -cir.ActualHeight / 2 <= y &&
        y <= canvas.ActualHeight - cir.ActualHeight / 2)
    {
        Canvas.SetLeft(el, x);
        Canvas.SetTop(el, y);
    }
}

ManipulationDelta イベントでは、対象のオブジェクトと移動距離が取れるのでこれを使って位置を移動します。Canvas上に乗せているので、位置指定は Canvas.SetLeft と Canvas.SetTop を使います。

■Androidの場合

Touch イベントを使います。Touch イベントで、DOWN/MOVE/UP が取れるので、これで対象のコントロール(ウィジット)を移動させます。

protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);

    // Set our view from the "main" layout resource
    SetContentView(Resource.Layout.Main);

    // Get our button from the layout resource,
    // and attach an event to it
    this.iv1 = FindViewById(Resource.Id.imageView1);
    this.iv2 = FindViewById(Resource.Id.imageView2);
    this.iv1.SetImageResource(Resource.Drawable.MarkBlue);
    this.iv2.SetImageResource(Resource.Drawable.MarkBlue);
    this.text1 = FindViewById(Resource.Id.textView1);
    iv1.Touch += iv1_Touch;
    iv2.Touch += iv1_Touch;
}

bool moveFlag = false;
float _sx, _sy;
void iv1_Touch(object sender, View.TouchEventArgs e)
{
    var el = sender as ImageView;
    if (el == null) return;

    float x = e.Event.RawX;
    float y = e.Event.RawY;

    switch (e.Event.Action)
    {
    case MotionEventActions.Down:
        _sx = x - el.Left;
        _sy = y - el.Top;
        moveFlag = true;
        break;
    case MotionEventActions.Move:
        if (moveFlag)
        {
            int left = (int)(x - _sx);
            int top = (int)(y - _sy);
            el.Layout(left, top,
                left + el.Width,
                top + el.Height);
        }
        break;  
    case MotionEventActions.Up:
        moveFlag = false;
        break;
    }
}

framelayout にコントロールを乗せておけば、Layout メソッドで位置指定ができます。

■iOSの場合

ドラッグするコントロールを継承する方法もあるのですが、ViewControllerでまとめて操作してみます。TouchesBegan、TouchesMoved、TouchesEnded をオーバーライドします。

    
UIImageView dragItem = null;
/// タッチ開始
public override void TouchesBegan(NSSet touches, UIEvent evt)
{
    base.TouchesBegan(touches, evt);
     UITouch touch = touches.AnyObject as UITouch;
     foreach (var el in this.drags) {
        if (el.Frame.Contains (touch.LocationInView (View))) {
            this.dragItem = el;
            break;
        }
    }
}
/// タッチ移動
public override void TouchesMoved(NSSet touches, UIEvent evt)
{
    base.TouchesMoved(touches, evt);
    UITouch touch = touches.AnyObject as UITouch;
    PointF newPoint = touch.LocationInView(View);
    PointF previousPoint = touch.PreviousLocationInView(View);
    if (dragItem != null ) {
        float offsetX = previousPoint.X - newPoint.X;
        float offsetY = previousPoint.Y - newPoint.Y;
        dragItem.Frame = new RectangleF (
            new PointF (dragItem.Frame.X - offsetX, dragItem.Frame.Y - offsetY),
            dragItem.Frame.Size);
    }
}
/// タッチ終了
public override void TouchesEnded (NSSet touches, UIEvent evt)
{
    base.TouchesEnded (touches, evt);
    dragItem = null;
}

TouchesMoved メソッドで、コントロールの移動前と移動後が取れるので、これを使ってコントロールを移動させます。移動したコントロールの判別を Frame.Contains で使っているのがいいまいちなのですが。

それぞれドラッグイベントの取得の仕方が微妙に違うので、ややこしいです。

  • Windows ストアアプリの場合は、ドラッグ対象にフラグを設定して、コンテナでイベント取得
  • Androidの場合は、ドラッグ対象にイベントを設定して、コンテナに委譲
  • iOSの場合は、コンテナでイベントを取得して、ドラッグ対象を計算で特定

このあたりは、どうせ C# で作るのだから統一しておきたいところです。個人的には Android 方式のほうがわかりやすいのですが(Java ではリスナークラスが必要になるので逆にわかりにくい)、差分を取れるほうが楽なので、ManipulationDelta のようにできると良いかなと。

サンプルは こちら https://github.com/moonmile/SampleTouch

カテゴリー: Android, WinRT, Xamarin, iOS | Xamarinでコントロールのドラッグに対応する はコメントを受け付けていません

XamarinでAndroid/iOS/Windowsストアの回転に対応する

実機を回転したときに縦置きと横置きの対応する方法は、基本はフローレイアウトを使うほうがいいのですが、コントロールがたくさん並んでいる場合にはなかなか大変ですね。…という理由を付けて、まとまったものが見つからなかったので、3つのプラットフォームでXamarinでどう対応するのかを残しておきます。

それぞれ方法があると思いますが、Potable Class Library で DataModel を共有化することと、3つのプラットフォームで似た方法で作れる、ことを目的とします。

■Windowsストアプリ の場合

  1. 横置き(Landscape)と縦置き(Portrait)の2つのViewStateを作る。
  2. PageクラスのLayoutUpdatedイベントで DisplayInformation.GetForCurrentView() でデバイスの向きを判断して、VisualStateManager.GoToState メソッドを呼び出す。

Blend を使って、VisualStateGroup を作って、その中に2つの ViewState を作る。”Landscape” と “Portrait” を作っておく。

image


 
  
   
   
    

コントロールを Portrait を設定してデザインを作る。

画面自体は1画面なので、XAMLに対して、this.DataContext = _model; のようにバインドができる。

回転時はイベントを取得して、ViewState を切り替える。

private void pageRoot_LayoutUpdated(object sender, object e)
{
    DisplayInformation displayInfo = DisplayInformation.GetForCurrentView();
    switch (displayInfo.CurrentOrientation)
    {
        // 横置き
        case DisplayOrientations.Landscape:
        case DisplayOrientations.LandscapeFlipped:
            VisualStateManager.GoToState(this, "Landscape", true);
            break;
        // 縦置き
        case DisplayOrientations.Portrait:
        case DisplayOrientations.PortraitFlipped:
            VisualStateManager.GoToState(this, "Portrait", true);
            break;
    }
}

横置きと縦置きで、コントロールの位置はこんな風に自由に配置できる。方法としてはスナップも同じ。というかスナップと同じ方法。

image

image

■Android の場合

  1. Alternative Layouts で、landscape 用のレイアウトを作る。
  2. layout-land/Main.axml を横置き用に編集する。
  3. ウィジット(コントロール)の ID は元の Portrait と同じにしておく。

image

image

回転したときには内部で自動的に判断して、layout-land/Main.axml が呼び出される。*.axml ファイルが2つになるので、IDをそろえておく。揃えておくと、FindViewById メソッドで統一して扱える。

private void UpdateData()
{
    FindViewById(Resource.Id.textViewID).Text = _model.ID;
    FindViewById(Resource.Id.textViewUserName).Text = _model.UserName;
    FindViewById(Resource.Id.textViewScore).Text = _model.Score.ToString();
    FindViewById(Resource.Id.textViewRank).Text = _model.Rank.ToString();
}

 

Android エミュレータは Ctrl+F11 で回転できる。

image

image

■iOS の場合

  1. Storyboard で、横置き用の ViewController を作成する。
  2. Storyboard Segue に名前を付けおく。
  3. 元の ViewController の View のタグを付けておく(初期化判断用)
  4. 同じ ViewController クラスに設定しておく。
  5. UIDeviceOrientationDidChangeNotification イベントで、PerformSegue メソッドを使って View を切り替える。

最初の画面が縦置き(Portrait)で、横置き(Landscape)に画面遷移する、という想定で作る。

image

切り替えを「Model」にしておく。

image

最初の View に Tag を付けておく。これは最初の画面のみ UIDeviceOrientationDidChangeNotification を設定するため。

image

AwakeFromNib をオーバーライドして UIDeviceOrientationDidChangeNotification イベントを登録。回転イベントが発生したら、UIDevice.CurrentDevice.Orientation で View を切り替える。

bool isShowingLandscaeView ;
public override void AwakeFromNib ()
{
    base.AwakeFromNib ();
    // main view only 
    if (this.View.Tag == 100) {
        // main view only,
        // set to main view's tag 100.
        this.isShowingLandscaeView = false;
        UIDevice.CurrentDevice.BeginGeneratingDeviceOrientationNotifications ();
        NSNotificationCenter.DefaultCenter.AddObserver (
            "UIDeviceOrientationDidChangeNotification",
            orientationChanged);
    }
}
void orientationChanged( NSNotification obj ) 
{
    var deviceOrientation = UIDevice.CurrentDevice.Orientation;
    if (deviceOrientation == UIDeviceOrientation.LandscapeLeft ||
        deviceOrientation == UIDeviceOrientation.LandscapeRight) {
        if (isShowingLandscaeView == false) {
            this.PerformSegue ("LandView", this);
            isShowingLandscaeView = true;
        }
    } else if (deviceOrientation == UIDeviceOrientation.Portrait ||
        deviceOrientation == UIDeviceOrientation.PortraitUpsideDown) {
        if (isShowingLandscaeView == true) {
            this.DismissViewController (false, null);
            isShowingLandscaeView = false;
        }
    }
}

 

元画面(portrait)から lanscape に遷移するときは、this.PerformSegue (“LandView”, this); を使い、landscape から元画面(portrait)に戻るときは this.DismissViewController (false, null); を使う。これは、storybord の画面遷移と同じ。遷移のアニメーションと回転時のアニメーションが競合するよな気もするんだが…このほうは Apple のマニュアルにもあるので、大丈夫だと思う。

image

image

2つの画面に分かれるが、同じ ViewController を示すようにして、IBOutlet させたプロパティにDataModel から設定する。

■ DataModel を PCL で作る

データ自体は、DataModel 内にひとつにしたいので、複数の View に対応する必要がある。基本は画面遷移をしたときと同じなのだが、画面のコントロール/ウィジットが多い場合には意外と大変かも。ただし、縦横で別々に作ったほうが使いやすいデザインにはなる。

  Winストア Android iOS
デザイン 1つのXAML 2つの
AXMLファイル
2つのViewController
回転
切り替え
コード 自動 コード
データ
設定
データバインド FindViewById で取得。IDを揃える。 IBOutletで取得

上記のサンプルは git で公開しています。https://github.com/moonmile/SampleRotate

機会を作って MvvmCross でも。

カテゴリー: Android, C#, WinRT, Xamarin, iOS | XamarinでAndroid/iOS/Windowsストアの回転に対応する はコメントを受け付けていません

HAXM で Android 仮想デバイスを高速化

ほとんど、Android仮想デバイス(AVD)の高速化 – Yahoo!知恵袋 に書いてある通りなので、自分用にメモとして残しておきます。

私の環境が、

  • Windows 8.1 Pro
  • VMWare Worksitation 10

なので、Hyper-V の機能が使えません。VMWare の仮想の仕組みが Hyper-V と競合するので、あれこれで HAXM Android* – Intel® Hardware Accelerated Execution Manager | Intel® Developer Zone と競合するのかと思っていたのですが、勘違いしていました。Intel CPU の場合は利用できる。AMD CPU の場合は利用できない。という違いですね。Intel VT という仮想化技術で実現しているので、さっくりと VirtualChecker 3.0.1 でチェックしておきます。

image

左上の「Intel VT-X」が Enabled になっていれば OK です…と思ったけど、AMD-V 対応でも Enabled になる?まあ、自分のPCが IntelかAMDぐらいかぐらいは分かるか。

Android エミュレータの「Intel Atom x86」を動かすために、Android* – Intel® Hardware Accelerated Execution Manager | Intel® Developer Zone から、Hotfix for Windows 8.1 only (1.0.7) のほうをダウンロード(Windows 8.1なので)。Android SDK Manager の HAXM は、Windows 8.1 だとクラッシュするそうです(試してません)。

image

「Intel Atom x86」のイメージは、各API に入っています。4.0.3 以降(API 15)以降ですね。

image

Android Virtual Device Manager で、CPU/ABI を ARM から Intel Atom (x86) に変更します。

image

Android Virtual Device Manager で起動する Android を選択して「Start」ボタンを押してエミュレーターを起動。

image

エミュレータ自体は結構なスピードで立ち上がります。

image

で、実際のところ Xamarin.Android からデプロイをしてみると、最初のデプロイに結構な時間がかかるのは同じ模様で。

image

…と、ここまで書いてやっぱりデプロイできず。変だな。で、試しに 4.0.3 (API 15)で Intel Atom で動かすと正常に動きます。私の 4.4.2 のエミュレータの作り方がおかしいのか、後で調べなおそう。

image

API 19 だと ARM でも動かないので、エミュレータの設定がおかしいのかも。試しに 4.3 (API 18)を入れると動くので、現状では API 19 は対応していないのかも。

カテゴリー: Android, Xamarin | HAXM で Android 仮想デバイスを高速化 はコメントを受け付けていません