一番かんたんなJava入門

これからJavaを始めようという人の為の超入門サイトです。丁寧、簡単にこだわった解説なので初心者にぴったりです。

【Hello world!の仕組み3】 Fragmentについての説明

time 2014/11/12

 新規プロジェクトを作ってみようで、立ち上げると画面にHello world!と表示されるアプリを作りました。activity1

 画面にHello world!と表示されるその仕組みについてのお話の続きです。

 前回【Hello world!の仕組み2】 MainActivity.java と activity_main.xmlについては、setContentView(R.layout.activity_main)で、画面に、画面いっぱいサイズのFrameLayoutという枠を仕込むところまで説明しました。

sponsored link

onCreate()の続き

 Activityを立ち上げた時に最初に呼ばれるonCreate()メソッドの中身を引き続き見ていきます。

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);

	if (savedInstanceState == null) {
		getSupportFragmentManager().beginTransaction()
			.add(R.id.container, new PlaceholderFragment())
			.commit();
	}
}

 前回はsetContentView(R.layout.activity_main);まで説明したので、その次です。

savedInstanceState

 if (savedInstanceState == null)というif文で分岐しています。

 見たら分かると思いますが、savedInstanceStateっていうのは、onCreate()メソッドの引数に渡されているBundleインスタンスです。

 Bundleインスタンスっていうのは、画面遷移をする際、次の画面(Activity)に渡したいデータを詰め込んでおく箱みたいなものです。

 次のActivityに何かデータを渡したい時は、遷移元のActivityで渡したいデータの詰まったBundleインスタンスを作ってから、そのBundleインスタンスを遷移先のActivityに渡すという仕組みになっています。

 普通にアプリを立ち上げた時は何も渡されないので、
savedInstanceState == null
が成立しこのif文の中身が実行されることになります。

 何か渡された場合の処理は現状では書いていません。このHello world!と表示するだけのActivityに、何かを受け取ってどうこうするような処理は不要だからです。

Fragmentとは?

 では、そのif文の中身を見てみましょう。

getSupportFragmentManager()
     .beginTransaction()
     .add(R.id.container, new PlaceholderFragment())
     .commit();

※見やすいように改行をいれてます。

 一見ややこしいこの一文がしているのは、画面にFragmentを配置する為の処理です。

 Fragmentっていうのは、レイアウトのパーツ(断片)みたいなものです。複数のFragmentを組み合わせることで一つの画面レイアウトを構成させることが出来ます。

 例えばよくあるニュースアプリを想像してください。

fragment5 このように、ニュースの見出しを並べた部分を一つのFragmentとして、また、ニュースの本文を表示する部分を一つのFragmentとして設計することで、横向き画面ならの二つのFragmentを左右に並べて表示することもできるし、縦向きならトップ画面は見出しFragmentだけを表示して、その見出しをタップすれば、次のActivityで本文Fragmentを画面いっぱいに表示するなんていう作り方が出来ます。fragment7

 一つのActivityのレイアウトをベタッと一枚で設計するよりも、このように機能的にひとまとめに出来る部分をFragmentとして個別に作っておけば、それを複数のActivityから再利用したり、横からにゅるっとスライドインさせる機能なんかを実装しやすいので、非常に便利です。

 とは言え、Hello world!と表示するだけの本アプリにはそんな高度な機能は要りません。

Fragmentを追加する

 ここでしているのは、Fragmentを一枚貼り付けているだけです。
 注目するべきは以下の一行です(他の部分は決まった形なのでとりあえず形だけ覚えておいたらいいと思います)

     .add(R.id.container, new PlaceholderFragment())

 このadd()メソッドは、FragmentTransactionクラスのインスタンスメソッドです。第一引数に渡されたレイアウトに、第二引数に渡されたFragmentを配置するという機能を持っています。

 つまりR.id.containerというレイアウトに、new PlaceholderFragment()というFragmentを追加しています。

 R.id.containerというのは、言葉で説明すると「containerというIDが付けられたモノ」という意味です。containerというIDが付けられたモノって何か覚えてますでしょうか?activity_main.xmlで定義されているFrameLayoutですね。すなわち、この画面(MainActivity)の大枠であるFrameLayoutです。(参考:【Hello world!の仕組み2】 MainActivity.java と activity_main.xmlについて

 そして、new PlaceholderFragment()というのは見ての通りPlaceholderFragmentクラスをインスタンス化したものです。これがこの画面に貼り付けるFragmentです。つまりPlaceholderFragmentクラスというのはこのFragmentを定義したクラスなわけです。

 PlaceholderFragmentクラスはMainActivity.javaの下の方に定義されています。どんなFragmentなのか見てみましょう。

PlaceholderFragment

public static class PlaceholderFragment extends Fragment {

        public PlaceholderFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_main, container, false);
            return rootView;
        }
    }

 PlaceholderFragmentクラスは、Fragmentクラスを継承しています。

 Activityクラスを継承したMainActivityクラスがActivityとして扱われるように、Fragmentクラスを継承したPlaceholderFragmentクラスはFragmentとして扱えます。

 PlaceholderFragmentクラスで定義されているのはご覧のように、コンストラクタとonCreateView()メソッドの二つだけです。

 コンストラクタは見ての通り特に何もしていません(PlaceholderFragmentインスタンスを作るだけ)。

 onCreateView()メソッドはこのFragmentの見た目を作る非常に重要なメソッドです。

onCreateView()

 このonCreateView()は、ActivityクラスのonCreate()と同じく、システム側から然るべきタイミングで自動的に呼ばれるコールバックメソッドです。

 onCreateView()メソッドの戻り値と引数に注目して下さい。

public View onCreateView(
                  LayoutInflater inflater,
                  ViewGroup container,
                  Bundle savedInstanceState
)

※見やすいように改行を入れています。

 見ての通り、onCreateView()は引数を3つ受け取っています。そしてViewオブジェクトをリターンします。

 1つ目の引数、inflaterは、LayoutInflaterクラスのインスタンスです。これはレイアウトを描画するために必要なインスタンスで、わざわざ自分でインスタンスを作らなくていいようにシステム側から渡してくれているだけです。親切です。

 2つ目の引数には、このFragmentを配置する際の親となるViewGroupオブジェクトが渡されます。この場合、このFragmentの親に当たるのはMainActivityの大枠として配置してあるFrameLayoutを指しています。ちなみにFrameLayoutクラスはViewGroupクラスを継承しているので、ViewGroupオブジェクトとして扱えます。

 このFrameLayoutのIDはcontainerです。第二引数のViewGroupオブジェクトの仮引数名もcontainerです。この一致はたまたま偶然です。たまたま一致しているだけなのに、実際指しているものもたまたま一致しているのがややこしいところです。(笑)

 3つ目の引数、savedInstanceStateはMainActivityのonCreate()メソッドに渡されているのと同じBundleインスタンスです。

 戻り値としてViewオブジェクトを返すようになっていますが、何を返すのかと言うと、このFragmentの見た目(レイアウト)です。

 つまり、onCreateView()メソッドは、このFragmentを表示する際にシステム側から自動的に呼ばれて、そのFragmentの見た目(レイアウト)を戻り値としてシステム側に返すメソッドなわけです。

onCreateView()の中身

 では、一体どんなレイアウトを返しているのかメソッドの定義部分を見てみましょう。

View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;

 まずリターンするべきViewオブジェクト、rootViewを宣言して、そこに何かややこしいのを代入しています。

 このややこしいのは何をしているかと言うと、Fragmentとして表示するべきレイアウトを描画しています。そしてその出来上がったレイアウトを、宣言したrootViewに代入しています。

 このinflate()メソッドは、見ての通りのonCreateView()の引数として受け取ったinflater(LayoutInflaterクラスのインスタンス)のインスタンスメソッドです。第一引数はR.layout.fragment_main、第二引数はonCreateView()メソッドの引数として受け取ったcontainer、第三引数はfalseになっています。

 ここで重要なのは第一引数のR.layout.fragment_mainです。これはfragment_main.xmlというxmlファイルを指しているのですが、inflate()メソッドというのは第一引数に受け取ったxmlファイルを元にそのレイアウトを描画するメソッドなんです。

 第二引数(container)、第三引数(false)は決まった形として覚えていたらいいと思います(解説省略)。

 R.layout.○○○というのは、ファイルそのものではなく実はただのint型変数(数字)です。その数字がファイルの存在場所を示しています。

 R.layout.fragment_mainがどこを指しているかと言うと、プロジェクトフォルダ(FirstAppli)の中のresフォルダの中のlayoutフォルダの中にあるfragment_main.xmlのことを指しています。
r-layout-fragment-main

fragment_main.xml

 ではこのFragmentのレイアウトはどんな風に定義されているのかfragment_main.xmlを見てみましょう。

 fragment_main.xmlを開いて、グラフィカルレイアウトというタブをクリックします。fragment_main8
 直接ソースコードをいじるならfragment_main.xmlというタブでできますが、グラフィカルレイアウトというタブを開けば、ソースコードを触らずに直感的な操作と簡単なプロパティ値の入力だけでfragment_main.xmlを編集することが出来ます。

 初心者にはグラフィカルレイアウトの方が楽なので、まずはそっちでやりましょう。

 グラフィカルレイアウトを開いたら、右にアウトラインという枠が表示されていると思います。

outline ここには、このxmlファイルの内容のアウトラインが表示されます。見ての通り、fragment_main.xmlのアウトラインは、RelaiveLayoutというのがあって、その下層(内部)にTextViewというがあるのが分かると思います。折り畳んだり開いたり出来ますよね。

RelativeLayout

 RelativeLayoutというのは、FrameLayoutと同じくLayoutの一種です。

 Layoutというのは、その中にボタンや文字列や画像などのViewを配置するための枠です。ここではRelativeLayoutの中にTextViewという文字列を表示するViewを配置しています。

 RelativeLayoutやFrameLayoutなどLayoutには数種類あるのですが、Viewの配置のされ方にそれぞれルールがあります。

 配置のされ方のルールというのはどういうことなのか理解できるように、主な3つのレイアウトの特徴を説明します。

FrameLayout
FrameLayoutはViewを配置する位置を選ぶことができません。この枠の中にViewを追加すると左上に詰める形で配置されます。複数のViewを追加したら全部のViewが左上に詰める形で配置されるので結果的にViewが重なってしまいます。なのでこのレイアウトは複数のViewを配置するのには向いてません(というか正直、あまり使い道ありません)。
LinearLayout(Vertical)
このレイアウトにViewを追加すれば順番に縦に並んでいきます。横に並べることは出来ません。勝手にViewが並んでくれるので配置するのが非常に楽ちんです。
RelativeLayout
このレイアウトはViewを自由に配置することができます。しかしその分どこに配置するのかを細かく指示する必要があるのでちょっと大変です。

 

 ではこのRelativeLayoutについて、もう少し詳しく見てみましょう。
 アウトラインのRelativeLayoutを選択した状態で、下のプロパティというタブをダブルクリックしてください。propatey
 

 すると、RelativeLayoutのプロパティが画面いっぱいに開きます。propatey2

 このRelativelayoutのプロパティとして設定されているのは、
Padding Left
Padding Top
Padding Right
Pdding Bottom
の4つです。上の方にPadding Leftがなぜかもう一つありますが、同じものです。

padding paddingというのは余白のことです。このRelativeLayoutの左、上、右、下それぞれの余白を設定しています。
 

 @dimen/activity_horizontal_margin@dimen/activity_vertical_marginっていうのは、dimens.xmlというxmlファイルで定義されている値です。dimens.xmlがどこにあるかと言うと、プロジェクトフォルダ(FirstAppli) → resフォルダ → valuesフォルダ内にあるので確認してみて下さい。16pxになってるのが分かると思います。

TextView

 このRelativeLayoutの中にTextViewが配置されています。
 先ほど、RelativeLayoutは自由にViewを配置することができると言いましたが、デフォルト状態ではやはり左上に配置されます。ここでは親レイアウトに余白が設定されているのでその内側の左上いっぱいいっぱいに配置されています。

 では、このTextViewのプロパティを開いてみましょう。textview

 Textの欄の値を見て下さい。やっと辿り着きました。Hello world!です。
 この欄に直接、Hello world!と書いてもいいのですが、ここでは先ほどの@dimen/○○○と同じように、@string/○○○という形でxmlファイルにて文字列を定義しています。プロジェクトフォルダ → resフォルダ → valuesフォルダの中のString.xmlを見て下さい。

 hello_worldというのはname(変数名みたいなもの)、そのvalue(値)がHello world!です。string

 @string/[name]で、その[value]を呼べるんですね。

 つまり、このstring.xmlのhello_worldのvalueの欄に書いてある文字列が、このアプリの画面に表示されるようになっているわけです。

 ここを書き換えてからアプリを立ち上げると表示される文字が変わるのが確認できると思いますので、ぜひやってみて下さい。

Hello world!の仕組み

 いやぁしかし、Hello world!がこんなに遠いとは思ってませんでした。

 ここまで説明した内容をサクッとまとめましょう。

マニフェストファイルでしていること
・トップ画面についてはMainActivity.javaで定義している旨を書く。

MainActivityのonCreate()でしていること
・画面いっぱいの大きさのFrameLayoutをセットする。
・Hello world!という文字列(TextView)が乗ったFragmentを作成して、そのFragmentをFrameLayoutに貼り付ける。

 簡単に書けばこれだけのことです。

 余分な説明が多かったかも知れませんが、もしこの長ったらしい説明が役に立ったというAndroidアプリ初心者が一人でもいれば嬉しいです。

 ってなんか最期の挨拶みたいになってますが(笑)、まだHello world!です。やっとスタート地点です。

 これから、このアプリにいろんな機能を追加していこうと思ってます。少しずつ機能を追加しながら説明していけたらいいなと考えております。

 ではでは。

専門学校に通うより絶対お勧め!オンラインプログラミングスクールまとめ

sponsored link

Androidアプリを作ろう

コメント

  • とっても丁寧な説明で助かりました!ありがとうございます。

    by johnyDgoode €2015/01/13 18:58

  • 嬉しいコメントありがとうございます。励みになります。

    by Nobuo@管理人 €2015/01/14 22:18

  • 事細かく説明されていてとても勉強になりました。

    これからも勉強させていただいてきます。

    by jin €2015/04/22 10:29

  • 詳細はまだ公開できませんが、実はAndroidアプリ開発本をただいま執筆中なんです。
    続きはwebで!じゃなくて、続きは本で!と早く言えるように頑張って書きます。(^^;)

    by Nobuo@管理人 €2015/04/22 12:27

  • 初めてAndroid開発を行っています。エラーが出る理由が分からなかったのですが、以下の箇所を読んで、お陰様で理解できました。ありがとうございました!

    >containerというIDが付けられたモノって何か覚えてますでしょうか?activity_main.xmlで定義されているFrameLayoutですね。

    by THAK €2015/05/02 11:20

  • 良かったです!

    by Nobuo@管理人 €2015/05/02 15:01

  • Javaに慣れ始めてきて、でもAndroidアプリケーションは右も左もわからない状態でしたが、ソースコードの意味を丁寧に教えてくれたのでわかりやすかったです。
    今後も是非参考にさせていただきたいです(^-^)

    by Clementine €2015/05/23 21:27

  • すごく分かりやすかったです。

    by risa €2015/08/16 18:46

  • サイトの手順どおり進めたのですが、MainActivity.javaのonCreateメソッドにif文がありません。それに伴い、このページで書かれているすべてのメソッドが存在していないのですか、理由などわかれば教えていただきたいです。

    by 匿名 €2015/08/27 04:15

  • 開発環境によって、いろいろ変わってしまう部分があるようです。

    Android Studioでの開発なら、Androidアプリを作ろう [Android Studio対応版]がお勧めです。私が初心者向けに書いたkindle本です。

    本でもHello world!の仕組みを解説しているのですが、こちらはFragmentを使っていないのでかなり説明も簡略化されています。

    900円とかなりお安くなってますので、ご検討下さい。

    by Nobuo@管理人 €2015/08/27 19:25

down

コメントする



CAPTCHA


一番かんたんなJava入門

Androidアプリの作り方

忘備録

私の作ったAndroidアプリ

私の作ったWordPressテーマ

プロに教わるオンライン学習

管理人

Nobuo_CREATE

Nobuo_CREATE

WordPressテーマPrinciple、マテリアルを作ったり、Androidアプリを作ったり、Java入門サイトを作ったり、本を書いたりしています。どうぞよろしく。 [詳細]



sponsored link

オススメ書籍

[オススメpoint]

 この本は全く何も分からない初心者の方にお勧めです。プログラミングをするには覚えなければならない事が無茶苦茶いっぱいありますが、この本は教えてくれる順番、その構成が素晴らしいです。RPGのゲームを作るというストーリーにのっとってちょっとずつ難しいことを教えてもらえます。
 無機質で膨大なデータが載っているような本は読む気にならないという方は、こういうストーリー仕立ての本でチャレンジしてみてはいかがでしょうか?(注:RPGを作る為の本ではありません。)

[オススメpoint]

 ある程度、Javaを読み書きできるようになったら、オブジェクト指向について学ぶべきです。本書は、抽象的で分かったような分からんようなオブジェクト指向について、非常に分かりやすい例を出して説明してくれています。オブジェクト指向とは何なのか?という本質を掴むのにこれほど適した本はないと思います。オブジェクト志向の理念を理解できれば、より効率のいいコードをより楽に書けるようになるはずです。Java上級者を目指すなら必読の一冊!

只今、急拡大中

ゲームを作りたい人専門

JavaからのRuby on Rails入門

JavaからのRuby on Rails入門

COBOLからのJAVA習得