酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

Lumia520とLumia720がグッドデザイン賞を受賞しました

グッドデザイン賞といえば日本で唯一の発売されている製品、アプリなどのデザインを評価・推奨する仕組みです。弊社は本業がデザイン事務所なので割りと関連があるらしく、2010年にiPhoneアプリでもグッドデザイン賞を頂いてたりします。

さて、今回Twitterで流れてきたのが「Lumia520とLumia720がグッドデザイン賞を受賞した!」というツイートでした。

調べてみると本当にLumiaが受賞していました。Lumiaのデザインは、Windows Phone独特のタイルスタイルにマッチするようなスタイリッシュな筐体ですからね*1

グッドデザイン賞には、以下の要領が存在します。

1-1.応募対象 応募対象は、2014年3月31日までに、ユーザーが購入または利用できるものごとで、2013年10月1日の受賞発表日に公表でき、かつ10月30日から開催される「グッドデザイン賞受賞展」において公開展示できるものとします。

このことからTwitter等の一部ユーザーが日本でも3月までに発売くるか!?と言われていたのですが、特に「日本のユーザーが利用可能である」との記載は見当たりませんでした。

グッドデザイン賞では、アジア各国のデザイン機関と制度連携などを進めているので、アジアでLumia520/720のデザインについての格付けのための応募だと思われます(出展者がNOKIA Chinaというところから推測)。

早く日本で欲しいですね。

だるさんにまとめてって言われたのでまとめてみました。

*1:でもWindows Phone 8が出て以降のLumiaは個人的に好きじゃない。やはりLumiaはLumia800は至高であってそれ以外は認めない

Windows PhoneでSliderコントロールの値の変化を取得する

Sliderコントロールは、値が変化するとValueChangedイベントを発行します。このイベントは、double型で変化後の新しい数値と変化前の古い数値が、引数として通知されます。

TextBlockを配置して、変化後の新しい数値を反映させてみましょう。プロジェクトを新規作成します。プロジェクト名は、SliderTestとします。ContentPanelにSliderとTextBlockを配置しました。

<phone:PhoneApplicationPage 
    x:Class="SliderTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">

    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="SOFTBUILD" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="Slider Test" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <StackPanel Margin="-12,0" Orientation="Vertical" VerticalAlignment="Top">
                <Slider Height="84" HorizontalAlignment="Center" 
                        Margin="0" x:Name="slider1" Width="480" 
                        ValueChanged="slider1_ValueChanged" />
                <TextBlock x:Name="textBlock1" TextWrapping="Wrap" Text="0.00" 
                           HorizontalAlignment="Right" Margin="0,0,12,0"/>
            </StackPanel>
        </Grid>
    </Grid>

</phone:PhoneApplicationPage>

SliderコントロールのValueChangedイベントハンドラ内で、e.NewValueをstring.Formatメソッドで小数点第2位まで四捨五入して、TextBlockのTextプロパティに代入しています。

using System.Windows;
using Microsoft.Phone.Controls;

namespace SliderTest {
    public partial class MainPage : PhoneApplicationPage {
        public MainPage() {
            InitializeComponent();
        }

        // 値が変化すると通知されるイベントハンドラ
        private void slider1_ValueChanged(object sender, 
            RoutedPropertyChangedEventArgs<double> e) {

            // 値を小数点第2位までの表示にする
            textBlock1.Text = string.Format("{0:0.00}", e.NewValue);
        }
    }
}

スライダーを動かすたびにValueChangedイベントが発生して数値を変化させることに成功しました。

f:id:ch3cooh393:20150518020357p:plain

関連記事

blog.ch3cooh.jp

Windows Phoneのアプリ開発の記事一覧

f:id:ch3cooh393:20111130232631j:plain

Microsoft社が提供するスマートフォンOS「Windows Phone」上で動くWindows Phoneアプリケーションの開発Tipsを紹介しています。

導入

アプリ開発に必要なWindows Phoneについての情報をご紹介します。

基本的なプログラミング

Windows Phone向けアプリを作る上で必要な基本的なプログラミングTipsです。

文字列操作

Page/Control

Launcher/Chooser

Windows Phoneにはアプリ間連携に「Launcher」と「Chooser(セレクター)」が使用できます。一覧にしてまとめてみました。

マルチメディア

カメラ

画像処理

ライブラリ

Hub Integrate

Windows Phone特有のハブ機能をアプリを統合します。ハブからアプリを起動することができるようになります。

ネットワーク

Background Agent

デバイス/センサー

システム

データ・ストレージ

アセンブリ

ストア関係/ライセンス関係

ローカライズ(多言語対応)

デバッグ

アプリをデバッグ実行する

パフォーマンス改善

その他

Windows Phone ガチコンテスト開催の可能性が

久しぶりにWindows Phoneの話題です。

日本のLumiaといえば@od_10zなのですが、今朝こんなことをツイートしていました。

アプリ数ではなくて、ストアの評価基準(コメントや☆の数)で順位が決まるとやる気出るよね、とTwitter上でワイワイ話していました。

お昼すぎに、高橋さんが乗ってきてくれました。

実現するとすれば、おそらく1カ月くらい準備期間が必要なはずなので、そこから募集と考えると、時期的にMashup Awards 9(リンクは去年のMA8のもの)と併願することができるかもしれません。

続報が楽しみです。

Windows PhoneでTransitionServiceを使って画面遷移時にアニメーションを行う

スマートフォンのアプリケーションと言えば、画面遷移時にページ間に繋がりを持たせる為にアニメーションを挿入するのが一般的です(iPhoneの場合ですとNavigationControllerによる横スライドなど)。画面遷移時のアニメーションのことは一般的に「トランジション」と呼ばれます。

Windows Phone SDKだけを使用した場合では、画面遷移時にトランジションアニメーションが行われません。……というよりは、OSとしてトランジション機能を提供していません。Windows Phone Toolkitを使用して、開発者が明示的にどのようなアニメーションをさせるのかを指定する必要があります。

前準備

Visual StudioのWizardでテンプレートプロジェクトを作成します。MainPage.xamlは既にあると思いますので、画面遷移先のページを追加してください。ここでは名前をSubPage.xamlをします。

MainPage.xaml、SubPage.xamlのそれぞれに下記の様なボタンを配置します。

MainPage.xamlに配置したボタンの名前はbtnMoveNextにしました。タップ時の動作としてSubPage.xamlへ遷移するように指定しています。

private void btnMoveNext_Click(object sender, RoutedEventArgs e)
{
    NavigationService.Navigate(new Uri("/SubPage.xaml", UriKind.Relative));
}

SubPage.xamlに配置したボタンの名前はbtnMovePrevにしました。タップ時の動作としてMainPage.xamlへ遷移するように指定しています。

private void btnMovePrev_Click(object sender, RoutedEventArgs e)
{
    NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
}

以上にて、本筋と関係ないお話は終わりです。

トランジションアニメーションを行う

ソリューションエクスプローラのReferencesを右クリックして、[Add References...]を選択します。Silverlight for Windows Phone ToolkitのアセンブリであるMicrosoft.Phone.Controls.Toolkitを追加します。

App.xaml.csのInitializePhoneApplicationメソッドを、PhoneApplicationFrameクラスからTransitionFrameクラスに変更します。この変更を忘れてしまうとアニメーションされませんので気をつけてください。

    //RootFrame = new PhoneApplicationFrame();
    RootFrame = new TransitionFrame();

トランジションアニメーションを行いたいページのxamlの名前空間にtoolkitを追加します。

    shell:SystemTray.IsVisible="True"
    xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit">

名前空間を追加したら次にトランジションの定義を行います。大きく分けて、画面へ入ってきた時と画面から出て行く時で定義を行います。更に詳細に「裏面に隠れてしまう画面のアニメーション」と「前面に出てくる画面のアニメーション」を定義します。

    shell:SystemTray.IsVisible="True"
    xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit">
    
    <!-- 画面に入ってきた時のアニメーション -->
    <toolkit:TransitionService.NavigationInTransition>
        <toolkit:NavigationInTransition>
            <toolkit:NavigationInTransition.Backward>
                <toolkit:TurnstileTransition Mode="BackwardIn"/>
            </toolkit:NavigationInTransition.Backward>
            <toolkit:NavigationInTransition.Forward>
                <toolkit:TurnstileTransition Mode="ForwardIn"/>
            </toolkit:NavigationInTransition.Forward>

        </toolkit:NavigationInTransition>
    </toolkit:TransitionService.NavigationInTransition>

    <!-- 画面から出ていく時のアニメーション -->
    <toolkit:TransitionService.NavigationOutTransition>
        <toolkit:NavigationOutTransition>
            <toolkit:NavigationOutTransition.Backward>
                <toolkit:TurnstileTransition Mode="BackwardOut"/>
            </toolkit:NavigationOutTransition.Backward>
            <toolkit:NavigationOutTransition.Forward>
                <toolkit:TurnstileTransition Mode="ForwardOut"/>
            </toolkit:NavigationOutTransition.Forward>
        </toolkit:NavigationOutTransition>
    </toolkit:TransitionService.NavigationOutTransition>

TransitionService.NavigationInTransitionにて画面が入ってきた時のトランジションを定義します。TransitionService.NavigationOutTransitionにて反対に画面から出て行く場合のトランジションを定義します。

若干判りにくいのですが、MainPageからSubPageへ遷移する場合には、MainPageのForwardOutとSubPageのForwardInのトランジションが行われ、SubPageからMainPageに戻る場合には、SubPageのBackwardInとMainPageのBackwardOutが行われます。

サンプルプロジェクトがToolkitに含まれていますので実際に動かして見た方が良いかもしれません。

その他に用意されているトランジションの種類

TurnstileTransition以外にもトランジションは用意されています。それぞれの説明と使いどころは下記の記事をご覧ください。

参考

Windows PhoneでWebClientを使ってWebページを取得する

ウェブコンテンツをダウンロードする場合、WebClientクラスを使用すると簡単です。

WebClientを使ってWebページを取得する

ダウンロード完了処理をイベントハンドラでおこなう

DownloadStringCompletedイベントハンドラを設定しておいて、DownloadStringAsyncメソッドで非同期ダウンロードを開始します。

// using System.Net;
// using Microsoft.Phone.Reactive;

// 一番シンプルなケース
private void button1_Click(object sender, RoutedEventArgs e) {
    var client = new WebClient();
    client.DownloadStringCompleted += client_DownloadStringCompleted;

    // ダウンロードを開始する
    client.DownloadStringAsync(new Uri("http://search.twitter.com/search.atom?q=ch3cooh"));
}

// ダウンロードが完了すると通知されるイベントハンドラ
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) {
    MessageBox.Show(e.Result);
}

Reactive Extensionsを使ってダウンロードしたデータを処理する

以下のソースコードの通り、Rxを使うとダウンロードした後の処理も含めてClickイベントハンドラ内で書いてしまうことができます。

Rxを使うには、あらかじめソリューションエクスプローラーにて[参照の追加]を選択し、参照の追加ダイアログを表示させ「System.Observable」と「Microsoft.Phone.Reactive」を選択しておきます。

// using System.Net;
// using Microsoft.Phone.Reactive;

// Rxを使ったケース
private void button2_Click(object sender, RoutedEventArgs e) {

    var client = new WebClient();
    Observable.FromEvent<DownloadStringCompletedEventArgs>(client, "DownloadStringCompleted")
        .Select(evt => evt.EventArgs.Result)
        .Subscribe((msg => MessageBox.Show(msg)));

    // ダウンロードを開始する
    client.DownloadStringAsync(new Uri("http://search.twitter.com/search.atom?q=ch3cooh"));
}

Windows PhoneでZXing Barcode Scanning Libraryを使ってバーコードを読み込む(Windows Phone OS 7.1 ~)

カメラプレビューから直接プレビューフレームを取り出せ無かったWindows Phone OS 7.0では、CameraCaptureTaskを利用してバーコードの読み込みを行いました。詳細については、ZXing Barcode Scanning Libraryを使ってバーコードを読み込む(Windows Phone OS 7.0)をご覧ください。

ここでは、PhotoCameraクラスを利用してカメラプレビューから映像を取り出しながら、解析を行いリアルタイム取り込みをしてみましょう。今回読み取るバーコードはこれです。

f:id:ch3cooh393:20140818122349p:plain

前述した通り、PhotoCameraから取り込んだ映像を矩形PreviewRectangleに表示して、取り込んだ映像をリアルタイムに解析し、バーコードの認識が出来ればリストボックスBarcodeListBoxへ解析結果を追加していきます。

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <!-- この矩形にカメラプレビューを表示する -->
    <Rectangle x:Name="PreviewRectangle" Margin="0">
        <Rectangle.Fill>
            <VideoBrush x:Name="PreviewBrush" />
        </Rectangle.Fill>
    </Rectangle>
    <ListBox Name="BarcodeListBox" />
</Grid>

MainPageクラスにPhotoCameraのインスタンス変数を追加しました。

    public partial class MainPage : PhoneApplicationPage {

        // コンストラクター
        public MainPage() {
            InitializeComponent();
        }

        PhotoCamera camera = null;

OnNavigatedToにてPhotoCameraクラスのインスタンスを生成します。同時に初期化処理完了のイベントハンドラの設定とPreviewBrushのデータソースとしてcameraを指定します。

        // ページがフレームでアクティブになったら呼び出される
        protected override void OnNavigatedTo(NavigationEventArgs e) {
            camera = new PhotoCamera();
            camera.Initialized += camera_Initialized;
            PreviewBrush.SetSource(camera);
        }

カメラの起動と初期化処理が完了すると、camera_Initializedメソッドが実行されます。カメラは大抵横向きに付いていますのでカメラの回転角度に合わせてプレビュー表示を回転させます。

        // カメラの初期化処理の完了
        void  camera_Initialized(object sender, CameraOperationCompletedEventArgs e) {
            // 初期化処理に失敗した場合は何もしない
            if (!e.Succeeded)
                return;

            // カメラの回転角度に合わせてプレビュー表示も回転させる
            Dispatcher.BeginInvoke(() => {
                PreviewBrush.RelativeTransform = new CompositeTransform() {
                    CenterX = 0.5, CenterY = 0.5,
                    Rotation = camera.Orientation
                };
            });
        }

カメラのプレビュー表示の仕組みはカメラデバイスのレンズから取り込んだ映像をパラパラ漫画のように表示させて、人間の目から見ると滞りなく動いているように見せているアレです。パラパラ映像を切り替える速度の単位をfps(frame per second)といいます。要は1秒間に何枚の画像を表示出来るの?という単位です。

リアルタイムといっても、Windows Phoneに搭載されているカメラの入力フレームレートは約30fps。1秒間に30枚の映像を処理しています。1枚辺り33ミリ秒です。この速度でバーコードの解析は難しいので、1秒間に2回解析を行うようにタイマーを定義します。

        // プレビューフレームの解析を行うタイマー
        DispatcherTimer readTimer = null;

        // カメラの初期化処理の完了
        void  camera_Initialized(object sender, CameraOperationCompletedEventArgs e) {
            // 初期化処理に失敗した場合は何もしない
            if (!e.Succeeded)
                return;

            // カメラの回転角度に合わせてプレビュー表示も回転させる
            Dispatcher.BeginInvoke(() => {
                PreviewBrush.RelativeTransform = new CompositeTransform() {
                    CenterX = 0.5, CenterY = 0.5,
                    Rotation = camera.Orientation
                };
            });
        }

これでカメラ起動は完了です。あとはリアルタイムでプレビューフレームの取り込みを行います。PhotoCamera.GetPreviewBufferArgb32メソッドで、ARGB32フォーマットでプレビュー中に表示されている画像(プレビューフレーム)を取得します。

読み取った結果は、こんな感じになります(画質が悪くて申し訳ない……)。

f:id:ch3cooh393:20140818122508j:plain

ライブラリから直接CameraCaptureTaskを起動する事も出来るらしいのですが、うちの環境では上手く動いてくれなかったのでこのような実装になりました。またライブラリ自体もBeta版ですのでそのうち動くようになると思います。

関連記事

参照