Skip to content

Androidカスタムコンポーネントのススメ

  • はじめに
    Androidアプリケーションの機能実装のアプローチとして、コンポーネント(Component / Control、Widgetと称すこともあります)を拡張していく方法があります。特にコンポーネントの振る舞いに紐づく機能は、それをActivityクラスに実装するよりコンポーネントに実装する方が、全体的にシンプルなコードになることがあります。
    例として、必須入力チェック機能付きEditTextコンポーネントを作成してみます。
    ※いつもの如くeclipseは英語版のままなので、適宜日本語に置き換えてください ;-)

  • 開発手順
    1. Androidプロジェクトを作成します。プロジェクト名は「CustomComponent」、パッケージ名は「jp.tworks.android.customcomponent」としました。パッケージ名は後に使いますので覚えておきましょう。
      プロジェクトの作成

    2. EditTextに必須入力チェック機能を付けるために、必要な属性を考えてみます。EditTextが必須チェックを行うか否かのフラグ(boolean)と必須チェックエラーを検出したときのエラーメッセージ(String)があれば良さそうですね。

    3. さっそく属性を定義します。/res/values/attrs.xml を追加します。
      /res/values からコンテキストメニューを開き、[New] –> [Other...] を選択します。
      attrs.xmlの追加

    4. Android XML Values Fileを選択します。
      attrs.xmlの追加

    5. ファイル名に「attrs.xml」を入力したらFinishをクリックします。
      attrs.xmlの追加

    6. attrs.xmlを以下のように編集します。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      
      <?xml version="1.0" encoding="utf-8"?>
      <resources>
       
          <declare-styleable name="ValidEditText">
              <attr name="required" format="boolean" />
              <attr name="required_message" format="string" />
          </declare-styleable>
       
      </resources>

      declare-styleable name=”xxxxxxxx” のxxxxxxxxは、これから作成するカスタムコンポーネントのクラス名を指定しておきましょう。

    7. 次にカスタムコンポーネントのクラスを作成します。プロジェクトにクラスを追加します。srcからコンテキストメニューを開き「New」–>「Class」をクリックします。
      クラスの追加

    8. Package名を「jp.tworks.android.customcomponent.widget」、クラス名を「ValidEditText」、継承元クラスをAndroid標準の「android.widget.EditText」としました。
      クラスの追加

    9. ValidEditTextクラスのコンストラクタを定義しましょう。widgetには3タイプのコンストラクタがありますが、ここではそのうちの1つ(引数が2つのバージョン)を定義します。

      1
      2
      3
      4
      5
      6
      7
      
      public class ValidEditText extends EditText {
       
      	public ValidEditText(Context context, AttributeSet attrset) {
      		super(context, attrset);
      	}
       
      }
    10. 必須チェックを行うか否かのフラグ(boolean)と必須チェックエラーを検出したときのエラーメッセージ(String)を管理するメンバ、およびそれへ値をセットするロジックを追記します。それぞれの値はlayout.xmlに「required=”true”」「required_message=”必須入力エラー”」のようにXMLの属性として記述されている前提とします。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      
      public class ValidEditText extends EditText {
       
      	// 必須チェック有無
      	private boolean required;
       
      	// 必須チェックエラー時のエラーメッセージ
      	private String required_message;
       
      	// コンストラクタ
      	public ValidEditText(Context context, AttributeSet attrset) {
      		super(context, attrset);
       
      		//----- layout.xmlに記述される属性を取得する -----
      		// /res/values/attrs が R.styleable として参照できる
      		// 先に定義した ValidEditText の属性名をすべて取得する
      		TypedArray attrsarray = context.obtainStyledAttributes(attrset, R.styleable.ValidEditText);
       
      		//----- ValidEditTextの属性値を個別に取得する -----
      		// 必須チェック有無
      		// 属性値がbooleanの場合は、第2引数で初期値を指定可能
      		required = attrsarray.getBoolean(R.styleable.ValidEditText_required, false);
       
      		// 必須チェックエラー時のエラーメッセージ
      		// 属性値がStringの場合、layout.xmlの属性値は @string/xxxxx 形式で記述可能
      		required_message = attrsarray.getString(R.styleable.ValidEditText_required_message);
      	}
       
      }

      AttributeSet#obtainStyledAttributes で、attrs.xmlで定義した属性を一挙に取得できます。またTypedArray#getBooleanやTypedArray#getStringで属性値を取得します。

    11. 入力チェックロジックを追記します。ValidEditTextクラスの外から呼べるように、メソッドのスコープをpublicにします。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      
      	// Validation
      	public boolean isValid(Context context) {
      		// 必須チェック
      		if (required == true) {
      			if (getText().length() == 0) {
      				// 何も入力されていないのでエラーを表示する
      				Toast.makeText(context, required_message, Toast.LENGTH_LONG).show();
      				return false;
      			}
      		}
       
      		return true;
      	}
    12. /res/values/string.xmlを編集して、必須入力エラーが検出されたときのエラーメッセージを定義します。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      
      <?xml version="1.0" encoding="utf-8"?>
      <resources>
       
          <string name="hello">Hello World, Main!</string>
          <string name="app_name">CustomComponent</string>
       
          <string name="required_message">何か入力してね!</string>
       
      </resources>
    13. /res/layout/main.xmlを編集し画面を定義します。上記で作成したValidEditTextとButtonを1つずつ追加します。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      
      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:orientation="vertical" >
       
          <jp.tworks.android.customcomponent.widget.ValidEditText
              android:id="@+id/validTextEdit1"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content">
       
              <requestFocus />
       
          </jp.tworks.android.customcomponent.widget.ValidEditText>
       
          <Button
              android:id="@+id/button1"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Button" />
       
      </LinearLayout>

      見た目はこのような感じです。
      main.xml

    14. 引き続き、ValidEditTextに属性と属性値を追記します。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      
      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tworks="http://schemas.android.com/apk/res/jp.tworks.android.customcomponent"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:orientation="vertical" >
       
          <jp.tworks.android.customcomponent.widget.ValidEditText
              android:id="@+id/validEditText1"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              tworks:required="true"
              tworks:required_message="@string/required_message" >
       
              <requestFocus />
       
          </jp.tworks.android.customcomponent.widget.ValidEditText>
       
          <Button
              android:id="@+id/button1"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Button" />
       
      </LinearLayout>

      XMLネームスペースの追加は、「xmlns:tworks=”http://schemas.android.com/apk/res/jp.tworks.android.customcomponent”」のように、http://schemas.android.com/apk/res/[アプリケーションのパッケージ名] という書き方になります。ValidEditTextの属性追加は「XMLネームスペース:属性=”属性値”」のような記述になります。ここでは「tworks:required=”true”」「tworks:required_message=”@string/required_message”」としました。

    15. 最後に/res/layout/main.xmlを読み込むActivityの実装を行います。Button(id:button1)をクリックしたときにValidEditText(id:validEditText1)のisValidメソッドを実行するようにします。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      
      public class Main extends Activity {
       
      	private ValidEditText validEditText;
       
          /** Called when the activity is first created. */
          @Override
          public void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.main);
       
              // ValidEditTextのインスタンスを取得
              validEditText = (ValidEditText)findViewById(R.id.validEditText1);
       
              // Buttonクリック時にValidEditTextのisValid()を実行する
              findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {
       
      			@Override
      			public void onClick(View v) {
      				validEditText.isValid(Main.this);				
      			}
      		});
       
          }
      }
    16. これで完成です。ValidTextEditに何も入力せずにボタンを押すと、Toastによってエラーメッセージが表示されますね!
      実行結果

  • 所感
    Activityは、チェックロジックの方法を知らなくてもよい=そこはブラックボックスでもよいケースが非常に多いです。そういった部分をカスタムコンポーネントで実装することで、Activityに記述する処理を減らすことができます。こうすることで、Activityはほぼドメインロジック(ビジネスロジック)を記述するだけでよくなりますし、コードの可読性や保守性を向上させることも出来ます。
    #あとはVとMが素結合にできれば…
  • Tagged

    双方向Bindingが可能なAndroid Binding v0.45を使ってみた

    • 前置き
      Android Bindingが0.45にバージョンアップしていたので試してみたところ、何と双方向Bindingに対応しているではないですか!…とTwitterにつぶやいたら@nakajiに「blogに書け!」と言われたので、纏めてみようと思います。
    • はじめに
      Android Bindingって何?ですが、一言で言うと「ViewとModel層を祖結合にしてくれるライブラリ」ってところです。これを使うとどう素敵になるの?という前置きは、@nakajiコチラに書かれていますのでご参照ください。@nakaji記事にもある通り、昔はView–>Modelへの片方向Bindingのみがサポートされていましたが、v0.45ではView<–>Modelの双方向Bindingが実現出来ていました。スバ、ラッシィ。
    • 事前準備
      • Androidの開発環境(eclipse+Android SDK)を整えておく
      • Android Bindingのサイトから android-binding-0.45-update.jar をダウンロードしておく
    • 開発手順
      1. Androidプロジェクトを作成します。AndroidBindingSampleと名付けました。
        プロジェクトの作成
      2. 事前にダウンロードしておいた android-binding-0.45-update.jar をプロジェクトの外部ライブラリとして参照追加します。プロジェクトの「Property」ダイアログを開き「Java Build Path」を選択し「Add External JARs…」ボタンを押下します。
        外部JARの追加
        android-binding-0.45-update.jar を選択します。
        外部JARの選択
        プロジェクトに参照が追加されました。
        外部JARの追加完了
      3. 次に画面を作り…たいのですが、その準備として、画面に表示する文字情報をリソース(string.xml)に定義します。
        <!--?xml version="1.0" encoding="utf-8"?-->
         
            Android Binding
            Enter your Height
            Enter your Weight
            Calc BMI
      4. 画面を作りましょう。…とその前に何のアプリケーションを作るかを決めていませんでした。@nakaji記事と比較しやすいように、入力された身長と体重からBMI値を計算し表示するアプリケーションにします。画面に身長(EditText)、体重(EditText)、計算ボタン(Button)、BMI計算結果(TextView)を貼り付けます。貼り付けついでに、EditText:hintプロパティとButton:textプロパティに、string.xmlで定義した文字列を設定しておきます。
        画面レイアウト
        layout.xmlの内容はこんな感じです。

        <?xml version="1.0" encoding="utf-8"?>
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:binding="http://www.gueei.com/android-binding/"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical" >
         
            <EditText
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:inputType="number"
                android:hint="@string/hint_height">
                <requestFocus />
            </EditText>
         
            <EditText
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:inputType="number"
                android:hint="@string/hint_weight"/>
         
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/caption_calcbmi"/>
         
            <TextView
                android:id="@+id/textView1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
         
        </LinearLayout>

        通常は各ウィジットにandroid:id=”@+id/hoge”という感じでIDを振りコードからfindViewById(”hoge”)という感じで参照します。Android BindingではBindingによる参照を行うため、潔く取っ払いました。

      5. 次に、画面の入力を受け取り結果を出力するModelクラスを追加します。(先ほどのlayout.xmlと関連のある)Activityと同じ階層にクラスを追加します。
        クラス名をBmiModelにしました。継承元クラスはデフォルトのjava.lang.Objectです。
        BmiModelクラスの追加
      6. Modelを実装します。
        package jp.tworks.android.bmi;
         
        import android.view.View;
        import gueei.binding.Command;
        import gueei.binding.observables.StringObservable;
         
        public class BmiModel {
         
        	// for EditText TextProperty
        	public StringObservable Height = new StringObservable();
        	public StringObservable Weight = new StringObservable();
        	public StringObservable Bmi = new StringObservable(); 
         
        	// for Button on Click
        	public Command calcBmi = new Command() {
         
        		public void Invoke(View view, Object... args) {
        			int height = Integer.valueOf(Height.get());
        			int weight = Integer.valueOf(Weight.get());
        			int bmi = (int)(weight / Math.pow(height / 100.0, 2));
        			Bmi.set(String.valueOf(bmi));
        		}
        	};
         
        }

        画面に配置した各ウィジットの属性(Property)と紐付け(Binding)するものはObservable(を継承したクラス)、onClickなどのイベントはCommandで実装します。EditTextに入力された情報はtextプロパティ(文字列型)で参照するため、StringObservableの変数としました。BMI計算結果を表示するTextViewについてもtextプロパティ(文字列型)ですのでStringObservable、Buttonのクリックイベントを処理するCommand名をcalcBmiとしました。
        続いてCommandのInvokeにBMI計算のロジックを記述します。StringObservableのHeight/Weightから値を取り出し、計算した結果をStringObservableのBmiに設定しました。

      7. 画面にModelとの紐付けを追記します。AndroidBindingライブラリが使用できるようにnamespaceを追加し、各ウィジットのプロパティにModelで実相したObservable/Commandを紐づけていきます。「binding:xxx=”yyy”」の箇所がそれです。
        <?xml version="1.0" encoding="utf-8"?>
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:binding="http://www.gueei.com/android-binding/"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical" >
         
            <EditText
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:inputType="number"
                android:hint="@string/hint_height"
                binding:text="Height">
         
                <requestFocus />
            </EditText>
         
            <EditText
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:inputType="number"
                android:hint="@string/hint_weight"
                binding:text="Weight"/>
         
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/caption_calcbmi"
                binding:onClick="calcBmi"/>
         
            <TextView
                android:id="@+id/textView1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                binding:text="Bmi" />
         
         
        </LinearLayout>
      8. 画面(View)とそれを扱うクラス(Model)を紐付ける処理を記述します。通常はActivityを継承したクラスで画面を生成しますが、Android BindingではActivityクラスの代わりにBindingActivityクラスを継承します。
        package jp.tworks.android.bmi;
         
        import gueei.binding.app.BindingActivity;
        import android.os.Bundle;
         
        public class BmiActivity extends BindingActivity {
            /** Called when the activity is first created. */
            @Override
            public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                // setContentView(R.layout.main);
         
                // モデルを生成
                BmiModel model = new BmiModel();
         
                // Layout.xmlの binding:xxx と modelを関連付ける
                setAndBindRootView(R.layout.main, model);
            }
        }

        setContentViewの代わりにsetAndBindRootViewというメソッドを使用します。このタイミングでViewとModelが実際に紐づきます。

      9. これで完成…と思いきや実はおまじないが足りておらず、これだけではウンともスンとも動きません(ここでハマること30分)。アプリケーションが起動するタイミングでAndroid Bindingライブラリの初期化を行う必要があります。android.app.Applicationクラスを継承したクラスを追加し、アプリケーション起動時にそれを呼ぶようにAndroid.Mainfestを変更します。
        プロジェクトの適当な場所に、android.app.Applicationを継承したクラスを追加します。
        クラス名をBmiApplicationにしました。継承元クラスはandroid.app.Applicationです。
        Applicationクラスの追加
        onCreateメソッドをオーバーライドし、Android Bindingの初期化処理を記述します。

        package jp.tworks.android.bmi;
         
        import gueei.binding.Binder;
        import android.app.Application;
         
        public class BmiApplication extends Application {
         
        	@Override
        	public void onCreate() {
        		super.onCreate();
        		Binder.init(this);
        	}
         
        }

        Android.Mainfestの「Application Attributes」–>「Name」に、追加したクラス名を設定します。
        Applicationクラスの置き換え設定

      10. これで完成です。身長と体重を入力してCalc BMIボタンを押すと、計算結果が表示されますね!
        実行結果1
      11. Android Bindingはこれ以外に入力チェック(Validation)の仕組みも持っています。今回は必須入力チェック(Required)をつけてみました。入力チェックはObservableな変数にアノテーションで指定します。更にModelValidator.ValidateModelメソッドで入力チェックを動かします。
        package jp.tworks.android.bmi;
         
        import android.view.View;
        import gueei.binding.Command;
        import gueei.binding.observables.StringObservable;
        import gueei.binding.validation.ModelValidator;
        import gueei.binding.validation.ValidationResult;
        import gueei.binding.validation.validators.Required;
         
        public class BmiModel {
         
        	// for EditText TextProperty
        	@Required(ErrorMessage = "Height is required.")
        	public StringObservable Height = new StringObservable();
         
        	@Required(ErrorMessage = "Weight is required.")
        	public StringObservable Weight = new StringObservable();
         
        	public StringObservable Bmi = new StringObservable(); 
         
        	// for Button on Click
        	public Command calcBmi = new Command() {
         
        		public void Invoke(View view, Object... args) {
        			// アノテーションで指定した入力チェックを実行する
        			ValidationResult result = ModelValidator.ValidateModel(BmiModel.this);
         
        			if (result.isValid()) {	// Validation OK
        				int height = Integer.valueOf(Height.get());
        				int weight = Integer.valueOf(Weight.get());
        				int bmi = (int)(weight / Math.pow(height / 100.0, 2));
        				Bmi.set(String.valueOf(bmi));
        			}
        			else {// Validation NG
        				// エラーを表示
        				String message = "";
        				for(String error : result.getValidationErrors()){
        					message += error + "\n";
        					Bmi.set(message);
        				}
        			}
        		}
        	};
         
        }

        実際に動かしてみるとこんな感じになります。手軽ですね。
        実行結果2

    • 所感
      AndroidプログラミングではView層とModel(ドメインロジック層)が強結合になりがちですが、Android Bindingを使うと少ない手間で祖結合にすることが出来ます。祖結合になることでUIから独立したドメインロジックを記述し易くなり、自動テストの範囲を広めるなどのメリットをもたらします。
    • 注意
      …とここまで書いて割と良いことだらけに見えますが、1つ大きな落とし穴がありました。Andorid Bindingライブラリのライセンスは本稿執筆時点でLGPLとなっています。AndroidにおけるLGPLというのは致命的で(理由はググってください)ソースを非公開にしたい商用アプリケーションなどでは使用できない状況です。ここだけ何とかならないかな…。
    • ライセンスは2012年6月にLGPLからMITに変更になりました。これで使用範囲を広げられそうですね!
    Tagged

    「はじめてのWindows Phoneプログラミング」執筆しました

    参考書「はじめてのWindows Phoneプログラミング」を執筆しました。蜜葉たんと共同執筆です。

    http://www.kohgakusha.co.jp/books/detail/978-4-7775-1661-2

    はじめてのWindowsPhoneプログラミング
    タイトルの通り、これから”はじめて”Windows Phoneプログラミングをする方向けの内容になっています。
    アプリを出している人が読む本じゃないんだからねっ!
    さておき、立ち読みして良かったら買ってくださいねー。

    Tagged

    アプリ内テーマのすすめ

    Windows Phone Advent Calendar 20日目の記事です。

    ■はじめに
     Windows Phoneのアプリケーションに、アプリ内テーマを適用する方法を紹介します。参考文献はコチラです。
     
     複数の画面を持つアプリケーションで、各画面に配置しているボタンやチェックボックスなどの配色をカスタマイズしつつ、全体で統一したいということがあります。画面毎/コントロール毎にプロパティを編集してもできますが、色味を変えたくなった時に、その都度すべてのコントロールのプロパティを編集しなければならないのは大変なことです。
      
     Androidは自身のアプリケーションの外観を統一させるために、Style Resourceという機能があります(Android UI前身のSWINGがその機能を持っており、それを継承していると思われます)。Style Resourceにデザイン要素を定義し、それを参照している画面はStyle Resourceのデザイン定義に従って描画を行います。
     
     Windows Phoneで同じことができないかと調べたところ、冒頭の文献を見つけました。

    ■開発手順

    1. アプリ内テーマを適用したいプロジェクトに「Theme」フォルダを追加します。
      screen1

    2. Themeフォルダに「System.Windows.xaml」と「ThemeResources.xaml」を追加します。
      screen2
      ファイルは以下からダウンロードしてください。
      System.Windows.xaml
      ThemeResources.xaml

    3. 「System.Windows.xaml」と「ThemeResources.xaml」のビルドアクションを「Resource」に設定します。
      screen3

    4. App.xamlを編集します。
      1
      2
      3
      4
      5
      6
      7
      8
      
      <!--アプリケーション リソース-->
      <Application.Resources>
        <ResourceDictionary>
          <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Theme/System.Windows.xaml"/>
          </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
      </Application.Resources>
    5. App.xaml.csを編集します。
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      
      using System.Collections;
       
      public App()
      {
        ...
        InitializeComponent();
       
        // 以下を追加する
        MergeCustomColors();
       
        InitializePhoneApplication();
        ...
      }
       
      // テーマをマージするロジック
      private void MergeCustomColors()
      {
        var dictionaries = new ResourceDictionary();
       
        // TODO:自身のアプリケーション名に合わせること
        string source = @"/InAppTheme;component/Theme/ThemeResources.xaml";
       
        var themeStyles = new ResourceDictionary { Source = new Uri(source, UriKind.Relative) };
        dictionaries.MergedDictionaries.Add(themeStyles);
       
        ResourceDictionary appResources = App.Current.Resources;
        foreach (DictionaryEntry entry in dictionaries.MergedDictionaries[0])
        {
          SolidColorBrush colorBrush = entry.Value as SolidColorBrush;
          SolidColorBrush existingBrush = appResources[entry.Key] as SolidColorBrush;
          if (existingBrush != null && colorBrush != null)
          {
            existingBrush.Color = colorBrush.Color;
          }
        }
      }
    6. ThemeResources.xaml を編集します。配色を変更したいものだけを残して残りはコメントアウトすると良いようです。今回は
      PhoneAccentBrush
      PhoneForegroundBrush
      PhoneRadioCheckBoxCheckBrush
      の3つをカスタマイズしてみました。

      1
      2
      3
      4
      5
      6
      7
      8
      
      <Color x:Key="PhoneAccentColor">#FFF5B80C</Color>
      <SolidColorBrush x:Key="PhoneAccentBrush" Color="{StaticResource PhoneAccentColor}"/>
       
      <Color x:Key="PhoneForegroundColor">#FF86FF02</Color>
      <SolidColorBrush x:Key="PhoneForegroundBrush" Color="{StaticResource PhoneForegroundColor}"/>
       
      <Color x:Key="PhoneRadioCheckBoxCheckColor">#FFF50CD8</Color>
      <SolidColorBrush x:Key="PhoneRadioCheckBoxCheckBrush" Color="{StaticResource PhoneRadioCheckBoxCheckColor}"/>
    7. ビルド、実行すると以下のようになりました。
      screen4

    ■所感
     簡単な手順でテーマが設定できました。テーマで配色が管理できるのはとても便利ですね!しかし配色をあまりに変更してしまうと、他のアプリケーションと見栄えがかけ離れてしまい、エンドユーザーにそぐわないアプリケーションになり兼ねません。コーポレートカラー/ブランドカラーなどワンポイントに留める方がよさそうな気がしました。

     ただし、アクセシビリティへの対応には結構使えるんじゃないでしょうか。このBlog執筆時点でWindows Phoneはアクセシビリティ対応に不十分で、色弱などの視覚障がい者に優しくないアプリケーションがあるかもしれません。そのような方向けの配色を考慮したアプリケーションを作成するときに、役立つと思います。

    ソースコードはこちら
    InAppTheme.zip

    Tagged

    今年最後の「たのアプ」やりますよー

    今年最後の「楽しいアプリ制作の会」を開催します!
    テーマ「楽しいLTの会 2011」。関西圏の勉強会主催者さんを中心に、楽しいLTセッションを行う催しです。

    詳細な告知はコチラでやってます。参加お待ちしてますー。

    GeForce 9600M GT / WDDM 1.1 on BootCamp Win7

    メインマシンのMacBook Pro 17′ (2009 Mid)のWindows 7 (BootCamp)で、ずっと困ってたことが解決したので備忘録を残します。

    ココからドライバをダウンロードしてインストールで解決しました。

    何が困っていたかというと、BootCamp(Mac OS X 10.6)が当ててくれるGPU(GeForce 9600M GT) のドライバがWDDM 1.0だったんですね。WDDM 1.0で何が困るかというと、Windows Phone 7開発で使うエミュレータがまともに動かないのですよ。エミュレータがまともに動く要件に、WDDM 1.1対応のGPUってのがありまして。

    まぁ普段の開発は実機があるので手詰まりになることはないのですが、勉強会などでプロジェクタ越しにUI/UXを見せたいときはエミュレータが要るのですよね。12/4に開催する「Windows Phone Hackathon in Osaka」に間に合ってホッとしています。

    次はコンソーシアムだ!

    次はコンソーシアムでしゃべります!

    先端IT活用推進コンソーシアムというのがありまして、それの分科会の「ユーザーエクスペリエンス技術部会」の「第1回「ユーザーエクスペリエンス技術部会」&
    「ネットデバイスアプリケーション部会」合同キックオフセミナー
    」(長っ!)でiOS/AndroidのUI/UXをしゃべります。

    セッションの講師陣が、僕以外はみなさん凄いですよ。っていうか僕だけ浮いてません?そしてセッションの順番が非常に良くない(汗)。UI/UXについて、いつも興味深く分かりやすいお話をしてくださるMicrosoft川西さんの後ってのがとってもプレッシャーです(汗)。でもいい機会を頂けたので、精一杯やってみようと思います。

    HTML5 プログラミング生放送勉強会 第11回@大阪 でしゃべってきた

    11/19に開催された「HTML5 プログラミング生放送勉強会 第11回@大阪」で、JavaScriptのスマートフォンWebアプリ開発フレームワーク「Sencha Touch」についてのセッションをやってきました。

    詳細なレポートはプロ生主催者の5jzさん(@jz5)のレポートを見て頂ければと思います。

    今回は資料作成に時間をかけることが出来ずSencha Touchの上辺しか語れなかったのですが、セッション後のアンケートを見るとさほど悪くないというか、厳し目に見ても普通くらいの評価でした。コーディングしつつデモを見せつつ〜という流れで進めたのが、分かりやすさに繋がったのかな。。。

    最後に、今回のお話を下さいました、プロ生主催者の5jzさん(@jz5)、なかじさん(@nakaji)本当にありがとうございました!またよろしくお願いします。

    資料は以下です。(slideshare)

    第2回 名古屋情報セキュリティー勉強会でしゃべってきた

    だいぶ遅くなりましたが、11/5(土)に開催された「第2回 名古屋情報セキュリティー勉強会」でiOS審査についてのセッションをやってきました。内容はこの1週間前に行われた「第23回まっちゃ139勉強会」と同じです。

    2週間続けてのセッションだったので、伝えるべきポイント(スパイラルのあたり)を伝えきれたかなと思います。それからセッションは伝えられてナンボっていうのが第一ですが、前後のセッションとうまく絡めつつ纏めつつという流れが組めると聞いてる人の興味を引けたりするので、竹森さん@KDDI Labsセッションとの関係性も意識してみました。

    今回は懇親会にも参加し、いろいろな方と談笑させていただきました。セッション内容について「面白かった」と言ってもらえましたが、具体的なツッコミが無かったのはそれ以上も以下も無かったということかな…次回はもっとストーリーを考えていかないといけませんね。

    最後に、登壇の機会をくださったまっちゃだいふく師匠、ありがとうございました!

    ということで発表資料は以下です。(slideshare)

    プロ生 第11回@大阪 でしゃべるよー

    ここのところ、他所の勉強会でしゃべりたくりの @tworks です。

    11/19 HTML5 プログラミング生放送勉強会 第11回@大阪でHTML5ネタをしゃべりますー。Twitterで @nakaji さんから突如話題を振られ、プロ生主催者の5zjさん(@jz5)とやりとりして、何故か喋ることになりましたw

    ネタなんですが「Sencha Touch」を喋ってみようと思ってます。理由は普段からスマホ系に携わっているので・・・です。さわってみて面白くなかったら、別のネタにするかもしれません(汗