スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

更新・・・

だいぶ時間があいてしまいました・・・。

転職やら引っ越しやら何やらでゴタゴタしていて、落ち着いて記事を書けませんでした。

ようやく落ち着いたので、これからまた記事を再開したいと思います。

テーマ : プログラミング
ジャンル : コンピュータ

レイアウトxmlでSurfaceViewを使用する

はじめに


久々の投稿です。以前、SurfaceViewについての記事を投稿しましたが、その際はSurfaceViewを画面全体に使用しており、レイアウトにxmlファイルを使用していませんでした。しかし、androidを開発する場合は、レイアウトはxmlファイルにまとめた方が何かと便利ですので、今回はxmlファイルを使用してSurfaceViewを画面上にレイアウトしてみたいと思います。


ポイント


今回のポイントは、SurfaceViewのためのコールバックをどうやって登録するか、です。そこさえ理解できれば、後は以前の記事と同じです。


プロジェクトの新規作成


いつものようにEclipseを起動して、新規プロジェクトを作成します。「ファイル」→「新規」→「Androidプロジェクト」を選択して、「新規Androidプロジェクト」ウィンドウを表示させます。そして以下を設定します。


プロジェクト名:SampleSurView


ビルド・ターゲット:Android 1.6


アプリケーション名:Sample Sur View


パッケージ名:jp.sample.SampleSurView


Create Activity:SampleSurView


リソースレイアウトの修正


以前、SurfaceViewを使用したサンプルでは、リソースレイアウトを使用していませんでした。しかし、今回はxmlファイルを使用してSurfaceViewをレイアウトします。


<?xml version="1.0" encoding="utf-8"?>

<TableLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/TableLayoutMain">


<!-- メイン領域:SurfaceViewを使用する -->
<SurfaceView
android:id="@+id/SurfaceViewMain"
android:layout_width="fill_parent"
android:layout_height="100px">

</SurfaceView>

<!-- ボタン領域 -->
<TableRow
android:id="@+id/TableRowMenu"
android:layout_width="fill_parent"
android:layout_height="wrap_content">

<Button
android:id="@+id/ButtonA"
android:text="A">

</Button>
<Button
android:id="@+id/ButtonB"
android:text="B">

</Button>
<Button
android:id="@+id/ButtonC"
android:text="C">

</Button>
<Button
android:id="@+id/ButtonD"
android:text="D">

</Button>
</TableRow>
</TableLayout>

今回はシンプルなレイアウトです。画面上部にSurfaceViewを配置し、その下にボタンを4つ配置しています。これらのビューをうまく配置するために、TableLayoutも使用しています。実際にこれを実行すると、以下のような画面になります。


20100103_article1

レイアウトは以上になります。後はSurfaceViewに対してコールバックを登録すればOKです。


ソースコードの修正


今回はソースコードを2つに分けます。1つは普段生成するメインのアクティビティのソースコード、もう1つはSurfaceView用のソースコードです。まずは、SurfaceView用のソースコードから掲載します。


「MainSurfaceView.java」


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MainSurfaceView implements SurfaceHolder.Callback, Runnable {
private SurfaceHolder holder;
private static final String LOG = "MainSurfaceView";

// コンストラクタ
public MainSurfaceView(Context context, SurfaceView sv) {
holder = sv.getHolder();
holder.addCallback(this);
}

@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
Log.d(LOG, "surfaceChanged");
}

@Override
public void surfaceCreated(SurfaceHolder arg0) {
Log.d(LOG, "surfaceCreated");

Canvas canvas = arg0.lockCanvas();
canvas.drawColor(Color.BLACK);

// canvasを使用してSurfaceViewに描画する
arg0.unlockCanvasAndPost(canvas);
}

@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
Log.d(LOG, "surfaceDestroyed");
}

@Override
public void run() {
Log.d(LOG, "run");
}
}

上記コードの一番のポイントは、コンストラクタの部分です。引数でSurfaceViewクラスのインスタンスをもらい、そこからgetHolderメソッドでSurfaceHolderを取得し、addCallbackメソッドで自クラスをコールバックとして登録します。これでOK。後は、上記MainSurfaceViewクラスをインスタンス化する時に、引数でSurfaceViewクラスのインスタンスを渡せば、SurfaceViewを使用することができます。


なお、MainSurfaceViewクラスの各メソッド(surfaceChanged, surfaceCreated, surfaceDestoryed, run)に、それぞれSurfaceViewを使用する際に実行したいコードを記述すれば、所望の動作をSurfaceViewに行わせることができます。今回はログを表示するのみ。




残りはメインのアクティビティのソースコードです。こちらのアクティビティから上記MainSurfaceViewクラスをインスタンス化します。


「SampleSurView.java」


import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;

public class SampleSurView extends Activity {
private SurfaceView mSvMain;
private MainSurfaceView mMainDrawArea;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

// SurfaceViewを参照
mSvMain = (SurfaceView)findViewById(R.id.SurfaceViewMain);

// 作成したMainSurfaceViewクラスをインスタンス化
mMainDrawArea = new MainSurfaceView(this, mSvMain);
}
}

ポイントはonCreateメソッドの中の最後の二行です。まずはリソースレイアウトにて定義したSurfaceViewをfindViewByIdメソッドによって参照します。これはmSvMainというメンバに保持しておきます。次に、mSvMainをMainSurfaceViewクラスをインスタンス化する際の第二引数に渡します。すると、MainSurfaceViewクラスのコンストラクタ内で、第二引数で渡されたインスタンスを使用して、MainSurfaceViewクラスをSurfaceViewを使用するためのコールバックとして登録します(MainSurfaceView.javaファイル参照)。これだけです。


実行結果


今回は目に見える動作は何も実行していませんので、実行結果は特にありません。


おわりに


今回はSurfaceViewをリソースレイアウトxmlファイルで使用してみました。Androidアプリを開発する場合はxmlファイルでレイアウトをいじる場合が多いと思いますので、今回の例のようにSurfaceViewを使用する場合もリソースレイアウトでレイアウトする場合が多いと思います。



テーマ : プログラミング
ジャンル : コンピュータ

App Inventor for Androidを始めよう!使い方その2

はじめに


前回の記事では、App Inventorを使用するための準備を行いました。今回は、実際にプロジェクトを作成してエミュレータ上でアプリを実行してみます。




App Inventor プロジェクトの新規作成


App Inventorのトップページにはいろいろな情報が掲載されています。チュートリアルやFAQもありますので、かなり参考になります。まずは簡単なサンプルを作成します。最初に画面右上にある「My Projects」をクリックします。


new project

すると以下のような画面が開きますので、「New」ボタンをクリックします。


AppInventor_07.png

以下のようなウィンドウが表示されますので、プロジェクト名を入力します。


AppInventor_08.png

すると以下のようなページに遷移します。これが開発用のページのようです。結構洗練されてますね。この画面はアプリの「GUI」部分を作成するためのもので、画面左側にボタンやテキストボックス等いろいろなパーツが用意されています。基本的には配置したいパーツをマウスでドラッグ&ドロップして、画面中央のアプリ画面に貼付けるだけです。


AppInventor_09.png

今回はシンプルに「ボタンを押したらテキストボックスに文字列を表示する」アプリを作りたいと思います。




GUIの作成


まず、ボタンをアプリ画面に配置します。左上にある「Button」をドラッグ&ドロップしてアプリ画面に持ってきます。すると、アプリ画面にボタンが配置されます。ボタンのプロパティは画面右側に表示されますので、例えばボタンに表示させる文字列を変更させたりできます。ここでは「クリックしよう!」という文字列を表示させます。これらを実行した後の結果は下図のようになります。


AppInventor_20.png

同様の手順でTextBoxも配置していきます。以下のようになります。


AppInventor_21.png

これで今回のGUI作成は終わりです。簡単ですね。




ロジックの作成


次にロジックの作成を行います。ここがApp Inventorのキモですね。まずはApp Inventorのページにある「Open the Blocks Editor」ボタンをクリックします(下図)。


AppInventor_22.png

すると以下のような画面が表示されますので、「開く」をクリックします。なお、これはFirefox 3.6での場合で、Safariなど他のブラウザで行う場合はこの限りではないかもしれません。


AppInventor_23.png

ファイルがダウンロードされ、実行されますが、そのとき以下のような警告が表示されると思いますので、「許可」ボタンをクリックします(私の環境では、許可ボタンのクリックが遅くなるとうまくBlocks Editorが開けないことがありましたので、早めにクリックするのが吉かも)。


AppInventor_24.png

うまくいくと、これでBlocks Editorが開きます。以下のような画面です。App Inventorのページに比べるとちゃちい気がしませんか?


AppInventor_25.png

画面の簡単な説明としては、左上の「Built-in」は動作を規定するブロック(if文などの制御ロジックや、テキスト設定など)、「My Blocks」はGUIとして自分が配置したパーツのブロックを切り替えるためのボタンです。Blocks Editorを開いた段階では「Built-in」のほうが選択されているようで、DefinitionやTextなどのボタンが画面左に並んでいます。


まずはGUI生成のときに作った「ここをクリック!」ボタンが押されたときの挙動を拾うための設定します。Blocks Editorの「My Blocks」ボタンをクリックします。すると以下のようなボタンが画面左に表示されます。


AppInventor_26.png

ここで「Button1」ボタンをクリックします。すると、以下のようにButton1に関連するブロックが表示されます。


AppInventor_27.png

今回はボタンクリックなので、一番上のブロック「Button1.Click」をドラッグ&ドロップして画面上に配置します(下図)。


AppInventor_28.png

次に、ボタンがクリックされたときの挙動を設定してきます。今回はボタンが押されたらテキストボックスにテキストを表示するので、まずはTextBox1のボタンをクリックします(下図)。先ほどと同じようにTextBox1に関連するブロックが表示されます。


AppInventor_29.png

TextBox1にテキストを設定するためのブロックは「set TextBox1.Text to」です。これを先ほどと同じ要領でドラッグ&ドロップしていきます。ここで注意する点は、先ほどは位置した「Button1.Click」ブロックのに配置するということです(下図のような感じ)。


AppInventor_30.png

これで「Button1がClickされたら、TextBox1.Textをsetする」という動作が設定できました。後は設定するテキストですが、これは「My Blocks」のほうではなく「Built-in」のほうにブロックがありますので、「Built-in」ボタンをクリックします(下図)。


AppInventor_31.png

ここで「Text」をクリックして、「text text」というブロックをドラッグ&ドロップします。接続先は「set TextBox1.Text to」です(下図)。


AppInventor_32.png
AppInventor_33.png

後は、少し大きめのテキストで「Text」と書いてある部分をクリックして、任意の文字列を入力して終わりです。今回は「Clicked!」と入力します(下図)。


AppInventor_34.png

これで終わりです。少し手順がなくなりましたが、慣れると簡単かと思います。




エミュレータで実行


まずはエミュレータプログラムを起動します。Macの場合は「アプリケーション→AppInventor→commands for AppInventor」フォルダにある「run-emulator」を実行します。ターミナルが起動して、その後しばらくしてからエミュレータが起動します。結構時間がかかります。


注意:私が試した所によると、どうやらエミュレータを起動してからBlocks Editorを起動しないとうまくエミュレータと連携できないみたいです。エミュレータを起動する際はいったんBlocks Editorを閉じてからエミュレータ起動→Blocks Editor再び起動、すると良さそうです。


AppInventor_35.png

起動してくると途中で以下のようなエラー画面が表示されることがありますが、とりあえず「Force Close」押しておけばオッケーそうです。


AppInventor_36.png

エミュレータが起動したら、Blocks EditorのConnect to phoneボタンをクリックしてエミュレータと接続します(下図)。


AppInventor_37.png

しばらく待っていると、エミュレータ上でアプリが実行されます。今回作ったアプリの実行結果は以下。


AppInventor_39.png

日本語は文字化けしてしまっていますね。App Inventorでは日本語は使用しない方が良さそうです。アプリ上でボタンをクリックすると、テキストボックスに「Clicked!」というテキストが表示されます。


AppInventor_40.png

これで今回のアプリの開発は完了です。





おわりに


今回はとても簡単なアプリを開発してみました。App Inventorはまだベータ版なので、いろいろ不具合などあるかもしれませんが、アプローチとしては面白いのではないでしょうか。また、今回の記事はいろいろ私が試行錯誤した結果のものですので、正規の手順と違う部分もあるかもしれませんので、ご了承ください。個人的にはブロックを配置するだけでコーディングの代わりになる部分は興味深い体験でした!





テーマ : プログラミング
ジャンル : コンピュータ

App Inventor for Androidを始めよう!使い方その1

はじめに


Android開発に詳しい方は既にご存知かもしれませんが、Googleが「誰でもAndroidアプリを開発できるツール App Inventor」を発表しました(ニュースサイト記事:ITmedia News)。


どういうことかと言うと、今までAndroidアプリの開発と言えば、Eclipseをインストールして、Javaでプログラミングしていました。しかしそれではプログラミングを勉強しないとアプリが作れないということにもなります。ま、プログラミングできない人がAndroidアプリ作りたいかどうかはともかくとして、少なくともAndroidアプリのアイディアは持っているけれど、それを実現するためのスキル(Javaを勉強したり、Eclipseみたいな開発環境を用意したり)を身につけるためのハードルがあることは事実だと思います。


そんなジレンマを解消するツールが「App Inventor」だそうです。今までプログラミングしていた部分を、動作を規定したブロックをポンポン配置していく感じで実現するようです。


ということで、実際に試してみます。ちょっと記事が長くなってしまったので、今回はApp Inventorの準備だけに注力します。




App Inventor 申請手順


App Inventorを使用するためには、まず申請が必要らしいです。App Inventorのページに行き、ページ右上にある「Request Access」欄の「this from」というリンクをクリックします。すると申請用のページが開きますので、所定の欄にメールアドレスなどの情報を記載した後、ページ下部の「Submit」ボタンをクリックします。これで完了。


うまく申請されたら申請許可されましたメールが来るそうですが、私の場合はそのようなメールは来ていませんが、App Inventorが使えるようになってました。日本Androidの会のメーリングリストに流れていた情報を見ても、メールが来てないけれど使えたよ、って人がいましたので、そんなものかもしれません。自分でちょくちょく使えるようになったかチェックしにいくのが良いかもしれません。





App Inventor 使用準備


App Inventorが使えるようになったら、実際に使ってみます。まずはGoogleのトップページに行き、自分のアカウントでログイン。そしてページ上部の「その他」をクリックして「サービス一覧」を選択します。


AppInventor_01.png

するとサービス一覧が現れますので、「Labs(英語)」を選択します。


AppInventor_02.png

試験運用機能というリストが出てきますので、「App Inventor for Android」を選択します。


AppInventor_03.png

Terms of Service画面が現れますので、「I accept the terms of service」ボタンを選択します。


AppInventor_04.png

これでApp Inventorの入り口に入る事ができました。


AppInventorトップ画面

次に、App Inventorを使用するための準備。トップページに「Get Started」欄があるので「Set up your computer and phone」リンクをクリックします(以下)。


AppInventor_10.png

開いたページで「Set Up Your Phone and Computer」リンクをクリック(下図)。


AppInventor_11.png

インストールするOSの種類を選択します。私はMac OS環境なので「Instractions for Mac OS X」を選択(下図)。


AppInventor_12.png

「Installer software」リンクをクリックします(下図)。


AppInventor_13.png

すると「AppInventorExtras.pkg」というファイルがダウンロードされますので、開きます。


AppInventor_14.png

後はインストーラの説明に従ってインストールします。設定はこれで終わり。




おわりに


今回はApp Inventorを使用するための準備だけを説明しました。ちょっと記事が長くなってしまったので、実際にプロジェクトを作成してみるのは、次の記事にしたいと思います。実際にプロジェクトを作成してみましたが、慣れると結構簡単にアプリを作れるかも!という手応えでした。

テーマ : プログラミング
ジャンル : コンピュータ

SurfaceViewの使い方4:ユーザがタッチできるようにする

はじめに


前回の記事では、ボールをSurfaceViewに描画して、画面内を跳ね返りながら動かすプログラムを作成しました。ただ、これでは勝手にボールが動くだけのプログラムなので、ユーザがいろいろ操作できるようにしたいと思います。


基本的に、Androidでユーザがタッチパネルにタッチしたことを受け取るためには、onTouchEventメソッドをOverrideしてやることで実現できます。また、キー入力を受け取るためには、onKeyDownやonKeyUpメソッドをOverrideしてやることで実現できます。


そして、いろいろ調べてみると、SurfaceViewクラスでも、onTouchEventなどのメソッドを用いてタッチイベントなどを拾えるそうです。SurfaceViewクラスを継承したクラスで、onTouchEventメソッドをOverrideすることで、タッチイベントを受け取る事ができます。今回は、このonTouchEventをOverrideして、ユーザが画面をタッチしたら、ボールの移動する方向を変えるようなプログラムを作成したいと思います。


プロジェクトの新規作成


いつものようにEclipseを起動して、新規プロジェクトを作成します。「ファイル」→「新規」→「Androidプロジェクト」を選択して、「新規Androidプロジェクト」ウィンドウを表示させます。そして以下を設定します(前回までと同じですね)。


  • プロジェクト名:SampleSurViewCycle

  • ビルド・ターゲット:Android 1.6

  • アプリケーション名:Sample Surface View Cycle

  • パッケージ名:jp.sample.SampleSurViewCycle

  • Create Activity:SampleSurViewCycle

  • リソースレイアウトの修正


    今回もリソースレイアウトは使用しません。SurfaceViewクラスを継承したクラスを用いますので。


    ソースコードの修正


    今回修正するコードは、前回の記事のSampleSurfaceViewCycle.javaをベースにして、onTouchEventメソッドのみをOverrideして追加します。コードの全体は以下です。


    package jp.sample.SampleSurViewCycle;

    import android.app.Activity;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.os.Bundle;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    import android.view.MotionEvent;;

    public class SampleSurViewCycle extends Activity {
    // スレッドクラス
    Thread mainLoop = null;
    // 描画用
    Paint paint = null;

    // SurfaceViewを描画するクラス
    class DrawSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable{
    // 円のX,Y座標
    private int circleX = 0;
    private int circleY = 0;
    // 円の移動量
    private int circleVx = 5;
    private int circleVy = 5;

    public DrawSurfaceView(Context context) {
    super(context);
    // SurfaceView描画に用いるコールバックを登録する。
    getHolder().addCallback(this);
    // 描画用の準備
    paint = new Paint();
    paint.setColor(Color.WHITE);
    // スレッド開始
    mainLoop = new Thread(this);
    mainLoop.start();
    }

    // タッチイベントを処理するためOverrideする
    @Override
    public boolean onTouchEvent(MotionEvent event) {
    // 移動する方向を反転させる
    // onTouchEventでは、以下の動きをとらえる事ができる
    // [ACTION_DOWN] [ACTION_UP] [ACTION_MOVE] [ACTION_CANCEL]
    // 今回はACTION_DOWN(タッチパネルが押されたとき)に、ボールの動きを反転させます
    switch (event.getAction())
    {
    case MotionEvent.ACTION_DOWN:
    circleVx *= -1;
    circleVy *= -1;
    break;
    default:
    break;
    }
    return true;
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
    int height) {
    // TODO 今回は何もしない。
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    // SurfaceView生成時に呼び出されるメソッド。
    // 今はとりあえず背景を白にするだけ。
    Canvas canvas = holder.lockCanvas();
    canvas.drawColor(Color.BLACK);
    holder.unlockCanvasAndPost(canvas);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    // TODO 今回は何もしない。
    }

    @Override
    public void run() {
    // Runnableインターフェースをimplementsしているので、runメソッドを実装する
    // これは、Threadクラスのコンストラクタに渡すために用いる。
    while (true) {
    Canvas canvas = getHolder().lockCanvas();
    if (canvas != null)
    {
    canvas.drawColor(Color.BLACK);
    // 円を描画する
    canvas.drawCircle(circleX, circleY, 10, paint);
    getHolder().unlockCanvasAndPost(canvas);
    // 円の座標を移動させる
    circleX += circleVx;
    circleY += circleVy;
    // 画面の領域を超えた?
    if (circleX < 0 || getWidth() < circleX) circleVx *= -1;
    if (circleY < 0 || getHeight() < circleY) circleVy *= -1;
    }
    }
    }

    }

    // アクティビティが生成されたときに呼び出されるメソッド
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new DrawSurfaceView(this));
    }

    @Override
    public void onDestroy() {
    super.onDestroy();
    Thread.interrupted();
    }
    }

    コードが長くなってしまいましたが、前回の記事と異なるのはonTouchEventメソッドの部分だけです。onTouchEventメソッドを、SurfaceViewクラスを継承したDrawSurfaceViewクラス内でOverrideします。すると、SurfaceView上でタッチした場合に、そのイベントを拾えるようになります。


    onTouchEventメソッドでは、ユーザがどのようなアクションをしたかを判別する事ができます。MotionEvent.ACTION_DOWN・・・タッチしたとき、MotionEvent.ACTION_UP・・・タッチを離したとき、MotionEvent.ACTION_MOVE・・・タッチしながら移動させているとき、等。他にもいろいろイベントを拾えるようです。詳しくは、MotionEvent | Androidを参照すると良いと思います。


    実行結果


    SurfaceView_06_onTouchEvent_01.png

    まずは起動直後。白いボールが画面左上から右下へ移動していきます。前回はこのまま動き続けるだけですが、今回はタッチすると動きが反転するので、エミュレータ上でタッチ(正確にはマウスでクリック)してみます。


    SurfaceView_07_onTouchEvent_02.png

    静止画なので、ボールの動きが反転しているかどうか分かりませんが、上記コードを実行するとうまく動いているようです。もう一度タッチすると、またボールの動きが反転します。これで今回の目的は達成しました。


    おわりに


    今回はSurfaceViewでユーザのタッチイベントを受け付けるようにしました。少しだけ、前回よりゲームチックになったように思います(まだまだしょぼいですが)。ただし、これだけでは、まだまだ使えるレベルではないので、次回はよりゲームチックな要素を取り入れたサンプルを作りたいと思います。





    テーマ : プログラミング
    ジャンル : コンピュータ

    プロフィール

    sepiablue

    Author:sepiablue
    組込みソフトウェアエンジニアやってます。普段はC言語使い。
    趣味はプログラミング、京都旅行で神社巡り。
    AndroidアプリをMacで開発中。

    最新記事
    スポンサードリンク
    スポンサードリンク
    月別アーカイブ
    カテゴリ
    検索フォーム
    RSSリンクの表示
    リンク
    QRコード
    QRコード
    上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。