2011年10月7日金曜日

Chapter14: スタイル適用の答え合わせ

Chapter13はできたでしょうか?
スタイルをまとめるというのは、CSSを書く感覚と同じなので、理解しやすかったのではないでしょうか?
では、コードを見てみましょう。Sample03プロジェクトの/res/values/sample_styles.xmlを開いてください。
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="SampleTopBtnPort">
        <item name="android:layout_width">90dip</item>
        <item name="android:layout_height">90dip</item>
        <item name="android:adjustViewBounds">true</item>
    </style>
</resources>
スタイルは、styleタグで定義します。
name属性がCSSのクラス名と同じと思ってください。
各スタイルの定義自身は、itemタグで設定します。
itemタグのname属性に、Viewの属性名を記述し、値を定義します。
敢えてCSSっぽく書くと、
.SampleTopBtnPort {
    android:layout_width: 90dip;
    android:layout_height: 90dip;
    android:adjustViewBounds: true;
}
という感じでしょうか。

これをViewに適用すると、以下のようになります。
/res/layout/chapter14.xmlの一部を抜粋
<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:gravity="top|center_horizontal"
    android:layout_marginBottom="10dp">
    <ImageView
        android:src="@drawable/regist"
        android:layout_marginRight="10dp"
        style="@style/SampleTopBtnPort" />
    <ImageView
        android:src="@drawable/manage"
        android:layout_marginRight="10dp"
        style="@style/SampleTopBtnPort" />
    <ImageView
        android:src="@drawable/photo_book"
        style="@style/SampleTopBtnPort" />
</LinearLayout>
ImageViewのstyle属性に@style/SampleTopBtnPortを指定したことで、だいぶすっきりした見た目になったかと思います。

Chapter13: スタイルにまとめてみる

さて、Chapter12はクリアできたでしょうか?
以下のような画面になっていればOKです。
次は、見た目は変わらないまま、スタイルを作ってみましょう。
スタイルとは、CSSみたいなもので、レイアウトXML内で使うViewの属性をまとめたものです。スタイルを使うことで、レイアウトの修正を簡単にすることができますし、ソースの可読性が上がります。


コードレビュー

では、コードを見てみましょう。Sample03プロジェクトの/res/layout/chapter13.xmlを開いてください。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/back_img_repeat">
    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:paddingTop="20dp"
        android:paddingBottom="20dp">
        <ImageView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:src="@drawable/logo"
            android:adjustViewBounds="true"
            android:layout_centerInParent="true" />
    </RelativeLayout>
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="vertical"
        android:gravity="bottom"
        android:layout_marginBottom="10dp">
        <!-- 
            ImageViewで定義している属性をstyleに書き換えてください。
            ファイル名はstyles.xml
            style名はTopBtnPortで作成してください。
         -->
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="top|center_horizontal"
            android:layout_marginBottom="10dp">
            <ImageView
                android:src="@drawable/regist"
                android:layout_marginRight="10dp"
                android:layout_width="90dp"
                android:layout_height="90dp"
                android:adjustViewBounds="true" />
            <ImageView
                android:src="@drawable/manage"
                android:layout_marginRight="10dp"
                android:layout_width="90dp"
                android:layout_height="90dp"
                android:adjustViewBounds="true" />
            <ImageView
                android:src="@drawable/photo_book"
                android:layout_width="90dp"
                android:layout_height="90dp"
                android:adjustViewBounds="true" />
        </LinearLayout>
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="top|center_horizontal">
            <ImageView
                android:src="@drawable/ranking"
                android:layout_marginRight="10dp"
                android:layout_width="90dp"
                android:layout_height="90dp"
                android:adjustViewBounds="true" />
            <ImageView
                android:src="@drawable/about"
                android:layout_marginRight="10dp"
                android:layout_width="90dp"
                android:layout_height="90dp"
                android:adjustViewBounds="true" />
            <View
                android:layout_width="90dp"
                android:layout_height="90dp"
                android:adjustViewBounds="true" />
        </LinearLayout>
    </LinearLayout>
    <RelativeLayout
        android:id="@+id/adArea"
        android:layout_width="fill_parent"
        android:layout_height="50dp">
        <ImageView
            android:src="@drawable/nail_banner"
            android:layout_width="fill_parent"
            android:layout_height="50dp"
            android:layout_centerInParent="true" />
    </RelativeLayout>
</LinearLayout>
Chapter12の答え合わせですが、ここではボタンでなくImageViewを使っています。ImageButtonというViewもあるのですが、ボタン用の縁などがつくので、そういうものがいらない場合は、ImageViewで作ってしまったほうが手っ取り早いと思っています。

75行目のViewですが、ここでは表示する画像がないので、敢えて何も表示しないViewを配置しています。何も表示しないViewを配置するというのも、テクニックになってきます(最初思いつきませんでしたが、他の方のソースを見たりして、こういう方法もあるのかと気づきました)。

Chapter13の課題の「スタイルにまとめてみる」ですが、参考になるソースは、/res/layout/chapter14.xmlと、/res/values/sample_styles.xmlになります。参考にして挑戦してみてください。

Chapter12: ボタンを表示させる

さて、Chapter11はクリアできたでしょうか?
以下のような画面になっていればOKです。
次はこの画面にボタンを表示させます。
ボタンといっても、コスメマネージャーの場合はImageViewを使って画像を表示させています。
以下のような画面になります。
課題については、Chapter12のレイアウトファイル内に書かれています。


コードレビュー

では、コードを見てみましょう。Sample03プロジェクトの/res/layout/chapter12.xmlを開いてください。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/back_img_repeat">
    <!-- ロゴを入れるRelativeLayout -->
    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:paddingTop="20dp"
        android:paddingBottom="20dp">
        <ImageView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:src="@drawable/logo"
            android:adjustViewBounds="true"
            android:layout_centerInParent="true" />
    </RelativeLayout>
    <!-- メニューを入れるLinearLayout -->
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="vertical">
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="top|center_horizontal"
            android:layout_marginBottom="10dp">
            <!-- 
                ImageViewを3つ使ってボタンを作成してください
                srcは
                @drawable/regist
                @drawable/manage
                @drawable/photo_book
                を使ってください。
                layout_widthは90
                layout_heightは90
                adjustViewBoundsはtrue
                を指定すること。
                他に使う属性もあります。
             -->
        </LinearLayout>
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="top|center_horizontal">
            <!-- 
                ImageViewを2つ使ってボタンを作成してください
                srcは
                @drawable/ranking
                @drawable/about
                を使ってください。
                layout_widthは90
                layout_heightは90
                adjustViewBoundsはtrue
                を指定すること。
                他に使う属性もあります。
                また、もう1つViewを追加して見た目を整えてください。
             -->
        </LinearLayout>
    </LinearLayout>
    <!-- フッター(広告エリア)など -->
    <RelativeLayout
        android:id="@+id/adArea"
        android:layout_width="fill_parent"
        android:layout_height="50dp">
        <ImageView
            android:src="@drawable/nail_banner"
            android:layout_width="fill_parent"
            android:layout_height="50dp"
            android:layout_centerInParent="true" />
    </RelativeLayout>
</LinearLayout>
Chapter11の答え合わせですが、ハイライトしている部分がそうです。
ImageViewで画像を指定する場合、@drawable/[ファイル名]を使います。

余談ですが、このファイルは、/res/drawable-hdpiに置いています。
いろんな解像度に対応しようと思ったら、drawable-****のすべてに画像を置くべきですが、hdpiの画像のみを置いています。 優先順位的に画像が使われるので、mdpiの端末でも、drawable-mdpiに同名のファイルがない場合はdrawable-hdpiにある画像が使われます。 全ての解像度の画像を準備しようと思うと、大変ですし、アプリ自体のファイルサイズも大きくなるので、表示が合わない素材だけを、 特定のフォルダに置くようにしましょう。

 また、デフォルトだとdrawableのフォルダのみ-hdpiや-mdpiという指定がありますが、実はlayoutファイルでもこのような指定をすることができます。詳細は今回は書きませんが、Android Developersの開発ガイドのマルチスクリーンのページを見れば参考になるかと思います。

Chapter12の解答はChapter13に書いてあるので、わからない場合はそちらを見ながら書いてみましょう。

2011年10月6日木曜日

Chapter11: ロゴとフッターを表示させる

さて、Sample03のインポートは終わっているでしょうか?
「タイトルバーを消す」をしている人はもうしているかもしれません。まだの人は、「Sample03プロジェクトを公開しました」より、インポートしてください。

今回の課題からは、実践方式になっています。
今までは基本的にソースコードを読んでもらう方式でしたが、手を動かさないとなかなか覚えられないと思いますので、そうしてみました。
Chapter11の完成コードがChapter12に、Chapter12の完成コードがChapter13に、Chapter13の完成コードがChapter14になっています。

では、Chapter11の最初の画面を見てみましょう。
Sample03アプリを起動しましょう。最初の画面は、完成予定画面です。メニューボタンを押して、chapter11をタップしてみましょう。以下の画面が表示されます。

背景だけ適用されているプレーンな画面です。
Chapter11では、ロゴとフッターをつけてもらいます。
完成イメージは以下になります。
課題はコード内に書かれていますが、コードのみ置いておきます。
Chapter11自体の答え合わせはChapter12で行います。


コードレビュー

では、コードを見てみましょう。Sample03プロジェクトの/res/layout/chapter11.xmlを開いてください。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/back_img_repeat">
    <!-- ロゴを入れるRelativeLayout -->
    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:paddingTop="20dp"
        android:paddingBottom="20dp">
        <!-- ImageViewを使って@drawable/logoを入れてください -->
    </RelativeLayout>
    <!-- メニューを入れるLinearLayout -->
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="vertical">
    </LinearLayout>
    <!-- フッター(広告エリア)など -->
    <RelativeLayout
        android:id="@+id/adArea"
        android:layout_width="fill_parent"
        android:layout_height="50dp">
        <!-- ImageViewを使って@drawable/nail_bannerを入れてください -->
    </RelativeLayout>
</LinearLayout>
課題の行をハイライトしています。 回答はChapter12になるので、chapter12.xmlを開いて参考にしてもらっても構いませんが、できればコピペしないでください。

タイトルバーを消す方法

Chapter11にしようかと思いましたが、あまりにも簡単だし、汎用的な内容でもあるので、ChapterではなくTips扱いにします。

Sample03プロジェクトで、コスメマネージャーのトップページを作るというのを題材に扱おうとしていますが、トップページは、アプリによりますが、タイトルバーを消したりする場合があります。コスメマネージャーはトップにロゴがあるので、タイトルバーを消しています。

そこで、タイトルバーを消す方法です。
サンプル画面を見てみましょう。

タイトルバーを消すのは、レイアウトのXMLファイルからではできません。できるのはAndroidManifest.xmlファイルで、です。
AndroidManifest.xmlファイルは、Androidで使うAPIについて定義したり、使う画面用Javaファイルの定義をしたり、アプリのバージョン情報を書いたりする設定ファイルです。

アプリで統一したいテーマを定義する場合はapplicationタグでテーマ属性を定義しますが、
画面(Activity)毎にテーマを設定することも可能です。
画面Aではタイトルバーを表示したいが、画面Bでは消したいということもありますから、今回の例ではActivity単位で消してみます。


コードレビュー

ではレイアウトのコードを見てみましょう。 Sample03プロジェクトの/AndroidManifest.xmlを開いてください。
<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.okolabo.android.sample03"
    android:versionCode="1"
    android:versionName="1.0">
    <uses-sdk android:minSdkVersion="7" />
    <application
        android:icon="@drawable/icon"
        android:label="@string/app_name">
        <activity
            android:name=".SampleActivity"
            android:label="@string/app_name"
            android:theme="@android:style/Theme.NoTitleBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".Chapter11Activity"
            android:theme="@android:style/Theme.NoTitleBar" />
        <activity
            android:name=".Chapter12Activity"
            android:theme="@android:style/Theme.NoTitleBar" />
        <activity
            android:name=".Chapter13Activity"
            android:theme="@android:style/Theme.NoTitleBar" />
        <activity
            android:name=".Chapter14Activity"
            android:theme="@android:style/Theme.NoTitleBar" />
    </application>
</manifest>
最初のactivityタグのandroid:theme属性で、androidがデフォルトで持っているテーマを呼び出しています。android:themeを何も指定しない場合、

@android:style/Theme

が適用されます。今回はタイトルバーを消したかったので、

@android:style/Theme.NoTitleBar

を指定しています。また、タイトルバーだけでなく、ステータスバーも消してフルスクリーンにしたい場合は、

@android:style/Theme.NoTitleBar.FullScreen

を指定します。黒めのテーマを使う場合は@android:style/Theme.Black系を、白めのテーマを使う場合は、@android:style/Theme.Light系を使います。基本の背景色や、メニューボタンを押して出てくるメニューの色などが変わるので、プレーンな感じでいい場合は好きなほうをテーマとして選びましょう(デフォルトは黒系)

なお、ここでは詳しくは解説しませんが、テーマは継承できます。わかりやすくいうと、デフォルトのCSSを使って、気に入らないところだけ自分で上書きして新しいテーマを作ることができるということです。1から全部書かなくてもよいですし、全部自分で書くとAndroidアプリケーションとして他アプリとしての統一性がなくなるので、基本的にはテーマを継承して新しいテーマを定義したほうがよいでしょう。

Sample03プロジェクトを公開しました

前回までで、Sample02のプロジェクトの内容が終わりました。
 次のプロジェクトを準備してあるので、Sample03プロジェクトをダウンロードしてインポートしてください。やり方は、Eclipseでプロジェクトをインポートする(zipのまま)です。ダウンロードするURLの部分だけ、読み替えてください。よろしくお願いします。

Sample03プロジェクトへのリンク(github)

Sample03で扱う内容は、以下の通りです。
今回は著者が公開しているAndroidアプリの「コスメマネージャー」のトップ画面を作ります。

  • タイトルバーを消す
  • (Chapter11)ロゴとフッターを表示させる
  • (Chapter12)ボタンを表示させる
  • (Chapter13)スタイルを作成する
  • (Chapter14)スタイル適用の答え合わせ
  • (Chapter15)画面用javaファイルの簡単な説明

2011年10月4日火曜日

Eclipseのショートカット集

※これは私がよく使うショートカットというだけです。

動作が重たいEclipseが使われる理由として、開発者に便利な機能がたくさんあるからというのがあります。それを使いこなさないと、単に重たい動作のエディタということになってしまいます。

ここでは私が開発のときによく使うショートカットを紹介します。


●Ctrl + Space: アシスト
AdobeのDWでもある機能ですから、アシストの意味はわかるかと思いますが一応。
入力の候補を表示してくれます。この機能のおかげで、タグをあんまり覚えたりしなくてもだいたいわかります。便利です。これがないと開発できない気持ちになってしまうくらいです。
Javaに限らず、xmlファイルでも使うことができます。
<Lを入力した時点で候補が出てきますが、カーソル移動させて表示が消えてしまったときなど、もう一度表示させようと思ったら、Ctrl + Spaceを入力します(Win, Mac共通)。 Macの場合は、Ctrl + SpaceがSpotlightのショートカットに割り当てられているので、それを無効化しておく必要があります。
タグが追加されました。続けて、android:layout_widthを入力したいと思います。
laと入力して、Ctrl + Spaceで、ずらーっと候補が出てきます。
layout_widthを選択後、再びCtrl + Spaceを""の間で押すと候補が表示されます。こんな感じでポンポン選択していくだけでよいことが多いので、コーディング量は相当減ります。

●Ctrl(Command) + Shift + F: ソースコードの整形
ぐちゃぐちゃになったソースコードを見やすい形に整形してくれます。
ただし、機械的に行われるので、コメントを見やすく書いていたつもりでも、それも機械的に整理されてしまうので、気を付けて使う必要がある場合があります。

こんな汚いソースでも・・・
 一発で綺麗に整形してくれます!


●Ctrl(Command) + Shift + O: 必要なパッケージの自動インポート(Java)
プログラムも多少いじらないといけなくなると思いますので、それのサポートとして。プログラマの人は知っておいたほうが超便利です。
Javaのパッケージは膨大にあって、もちろん全部覚えられるわけもなく、長いソースコードになれば、どのパッケージを使っていて、どのパッケージを使わなくなったかなど、知る由もありません。
そこで、Ctrl + Shift + O(オー)を押すと、必要なパッケージの自動インポートを行ってくれます。

下のソースのように、Intentクラスをインポートしていなくてエラーになったり、使わなくなったProgressBarクラスがあったとします。ここで、Ctrl + Shift + Oを押します。
すると、なんということでしょう。
import文が綺麗に整形され、エラーが消え去ったではありませんか。
これも、匠(Eclipse)のなせる業です。

●Ctrl(Command) + 1: クイックフィックス
クイックフィックスは、汎用的に使える機能で、なんか不具合があったら押したら解決する方法を提示してくれたりします。自分が使う場合は、変数の定義の場合によく使います。

まず右辺だけ書きます。今回はnew Intent();です。
その後、行にカーソルを合わせた状態でCtrl + 1を押します。
すると、クイックフィックスの候補が出てきます。新規ローカル変数を定義したいので、1つめを選択します。
 すると、左辺が保管されました。これを知ってから効率がだいぶあがりました。

動作が重い分、使いこなせばかなり効率的にプログラミングや、レイアウトの記述ができるようになります。Eclipseを完全に使いこなす必要はないと思いますが、よく使う機能や便利な機能は知っておいたほうがいいと思ったので、紹介しました!