参考:Layouts | Android Developers
参考:Supporting Different Densities | Android Developers
参考:Supporting Multiple Screens | Android Developers
目次
画面を構成する要素
画面を構成する要素となる View には以下のようなものがあります。
TextView、EditText、ImageView、Button、CheckBox、RadioButton といったウィジェット(Widget)と、
LinearLayout、RelativeLayout、FrameLayout といったウィジェットを取りまとめるレイアウト(Layout)です。
これらウィジェットとレイアウトをまとめて、View と呼びます。
View を配置する
View を配置する際に使用する各種パラメータについて説明します。
サイズ
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="hello_world" />
</RelativeLayout>
要素 | 意味 |
---|---|
android:layout_height | Viewの高さ |
android:layout_width | Viewの横幅 |
android:layout_height
とandroid:layout_width
で指定できる値は、数値 dp
,sp
,px
などとmatch_parent
(fill_parent
)とwrap_content
となります。
match_parent
は、親のViewと同じサイズに調整されます。
wrap_content
は、コンテンツを表示するのに十分なサイズに調整されます。上記サンプルの場合、TextViewのサイズは”hello_world”を表示するのに必要なサイズへと調整されます。
fill_parent
はmatch_parent
と同じ機能ですが、API Level 8から非推奨となっています。
API Level 7以下をターゲットとしないのであればmatch_parent
を使用しましょう。
パディング、マージン
padding(パディング)、margin(マージン)を使用することでViewの余白を設定することができます。
パディングでViewの内側の余白をマージンで外側の余白を調整することができます。
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#f2f2f2"
android:padding="12dp"
android:text="Padding"
android:textSize="30sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="12dp"
android:background="#f2f2f2"
android:text="Margin"
android:textSize="30sp" />
要素 | 意味 |
---|---|
android:padding | 上下左右のパディング |
android:paddingTop | 上のパディング |
android:paddingBottom | 下のパディング |
android:paddingLeft | 左のパディング |
android:paddingRight | 右のパディング |
android:layout_margin | 上下左右のマージン |
android:layout_marginTop | 上のマージン |
android:layout_marginBottom | 上下のマージン |
android:layout_marginLeft | 左のマージン |
android:layout_marginRight | 右のマージン |
単位
Androidには様々な画面サイズ、画面密度(解像度)の端末が存在します。
そのためpx(pixel)でサイズ指定をすると端末によって画像が小さくなったり大きくなったりしてしまいます。
Androidではこのような複数解像度の端末に対応するため以下の単位が用意されています。
dp(dip)
dp(dip) は density-independent pixels (密度非依存のピクセル) の略です。
dipは160dpi(dots per inch) の画面を基準とされており、1dipは160dpiの画面では1ピクセルと同等と定義されています。
この関係を式にすると以下のようになり、解像度に対する1dipが何pxに相当するかがわかります。
px = dp * (dpi / 160)
320dpiの画面の場合だと1dipは2pxに自動的に換算され、画面上に反映されることになります。
よって、サイズにdpを使用することで特に意識することなく複数のが解像度端末に対応することができます。
dipとdpは両方使えますがdpの記述の方がspと統一感があるのでわかりやすいです。
sp
spはscale-independent pixels(スケール非依存のピクセル)の略です。
指定したサイズは、解像度とユーザーが設定したフォントサイズにあわせて自動的にスケールされます。
位置
Gravityを使用することでViewを指定した位置に配置することができます。
Gravityは重力という意味です。Viewに重力をかけることによって、かけた方向へViewが配置されます。
Gravityにはandroid:gravity
とandroid:layout_gravity
が存在し、用途によって使い分けます。
要素 | 意味 |
---|---|
android:gravity | 内部の要素の位置を決めます |
android:layout_gravity | 自分の位置を決めます |
android:gravity
内部にTextView
を持ったLinearLayout
にandroid:gravity="right"
を指定すると以下のようになります。
このことより、TextView
が右に整列されるのがわかります。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
android:gravity="right"
android:orientation="vertical" >
<TextView
android:layout_width="180dp"
android:layout_height="100dp"
android:background="@android:color/white"
android:text="Gravity Right1"
android:textSize="20sp" />
<TextView
android:layout_width="180dp"
android:layout_height="100dp"
android:background="@android:color/darker_gray"
android:text="Gravity Right2"
android:textSize="20sp" />
</LinearLayout>
次は、LinearLayout
内部のTextView
自体にandroid:gravity="right"
を指定すると以下のようになります。
このことより、TextView
内の文字が右に整列されます。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
android:orientation="vertical" >
<TextView
android:layout_width="180dp"
android:layout_height="100dp"
android:background="@android:color/white"
android:gravity="right"
android:text="Gravity Right1"
android:textSize="20sp" />
<TextView
android:layout_width="180dp"
android:layout_height="100dp"
android:background="@android:color/darker_gray"
android:gravity="right"
android:text="Gravity Right2"
android:textSize="20sp" />
</LinearLayout>
android:layout_gravity
内部にTextView
を持ったLinearLayout
にandroid:layout_gravity="right"
を指定すると以下のようになります。
LinearLayout
自体の位置が右に移動しTextView
のLinearLayout
内での位置は変わっていません。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
android:orientation="vertical" >
<LinearLayout
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:background="#d1992f"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:text="Gravity Right1"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/darker_gray"
android:text="Gravity Right2"
android:textSize="20sp" />
</LinearLayout>
</LinearLayout>
次に、LinearLayout
内部のTextView
自体にandroid:layout_gravity="right"
を指定すると以下のようになります。
このことより、TextView
が右に整列されます。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
android:orientation="vertical" >
<LinearLayout
android:layout_width="200dp"
android:layout_height="wrap_content"
android:background="#d1992f"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:background="@android:color/white"
android:text="Gravity Right1"
android:textSize="20sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:background="@android:color/darker_gray"
android:text="Gravity Right2"
android:textSize="20sp" />
</LinearLayout>
</LinearLayout>
RTL support
RTLとはright-to-left の略でアラビア語やヘブライ語などの右から左に記述する言語のことをRTL言語と呼ぶことがあります。
Androidでは古くからRTL言語の表示をすることは可能でしたが、4.2から機能が強化されました。ドキュメントではfull native support for RTLと記載されています。(実際には4.4で画像反転等の機能追加が行われるなどしています)
これにより、レイアウト上でもRTLを意識したデザインをすることが可能になりました。
レイアウトファイルをRTL対応した場合、どのように表示されるかは、下図のように左右が反転したデザインとなります。
日本国内だけをターゲットにする場合は、対応が必須とは言えませんができるだけ対応したほうがいいといえるでしょう。
対応方法
- AndroidManifest.xmlの
<application>
内にadd android:supportsRtl="true"
と記述する - targetSdkVersionに応じてレイアウトファイル内の記述を変更する
- minSdkVersion17未満
left,rightが含まれる値にstart,endの指定を追加し、両方の記述をする - minSdkVersion17以上
left,rightが含まれる値をstart,endの指定に変更する
- minSdkVersion17未満
で、対応が完了します。
レイアウトファイル内の記述の変更について具体的に記述すると
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:paddingLeft="2dp"
android:background="@android:color/darker_gray"
android:text="Gravity Right2"
android:textSize="20sp" />
と記述されていたものを、minSdkVersion17未満の場合は
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|start"
android:paddingLeft="2dp"
android:paddingStart="2dp"
android:background="@android:color/darker_gray"
android:text="Gravity Right2"
android:textSize="20sp" />
とします。この時にpaddingLeftに対してpaddingStartが追加されていることに気をつけてください。
minSdkVersion17以上の場合は、
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:paddingStart="2dp"
android:background="@android:color/darker_gray"
android:text="Gravity Right2"
android:textSize="20sp" />
とします。
レイアウトを作成する
レイアウトはUIの構造を定義します。
LinearLayout、RelativeLayout、FrameLayout、GridLayout、ListView、ScrollViewなどがあり、用途によって使い分けます。
LinearLayout
Viewを縦横に並べることができます。
android:orientation
で並べる方向を決めます。”horizontal” か “vertical”を指定します。
未設定の場合はhorizontalが適用されます。
横に並べる
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text2" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text3" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text4" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text5" />
</LinearLayout>
android:orientation="horizontal"
を指定することによりTextView
が横に並んでいます。
(android:orientation="horizontal"
を記述していなくても同様の画面レイアウトになります)
縦に並べる
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text2" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text3" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text4" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text5" />
</LinearLayout>
android:orientation="vertical"
を指定することによりTextView
が縦に並んでいます。
Layout Weight
LinearLayoutは個々の内部View(子View)に対してandroid:layout_weight
を割り当てることができます。
android:layout_weight
はViewを配置したときに残っているスペースを埋めることができるとても重要な機能です。
例えば、2つボタンが横並びに配置されているとします。片方のボタンにのみandroid:layout_weight="1"
を指定します。
指定していないボタンのandroid:layout_weight
は0
として扱われます。
android:layout_weight
は指定された値を元にスペースを割り当てます。この例では割り当てられる比率は1:0となります。
よって、指定されたボタンは残っているスペースを全て使うことになり目一杯横方向に伸びます。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Button1" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button2" />
</LinearLayout>
RelativeLayout
相対的にVeiwを配置することができます。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<Button
android:id="@+id/a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="A"
android:textSize="16sp" />
<Button
android:id="@+id/b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/a"
android:layout_toRightOf="@+id/a"
android:text="B" />
<Button
android:id="@+id/c"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/b"
android:layout_below="@+id/b"
android:text="C" />
<Button
android:id="@+id/d"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/c"
android:layout_alignTop="@+id/b"
android:layout_toRightOf="@+id/b"
android:text="D" />
</RelativeLayout>
- ボタンAを
android:layout_centerHorizontal="true"
で横方向の中心に、さらにandroid:layout_centerVertical="true"
で縦方向の中心に配置しています。またandroid:id="@+id/a"
と宣言することでボタンAの識別子を付与しています。 - ボタンBは
android:layout_toRightOf="@+id/a"
を指定することでボタンAの右に配置しており、android:layout_alignTop="@+id/a"
で上端をボタンAの上端に合わせています。 - ボタンCは
android:layout_below="@+id/b"
を指定することでボタンBの下に配置しており、android:layout_alignLeft="@+id/b"
で左端をボタンBの左端に合わせるようにしています。 - ボタンDは
android:layout_toRightOf="@+id/b"
を指定することでボタンBの右に配置しており、android:layout_alignTop="@+id/b"
で上端をボタンBの上端、android:layout_alignBottom="@+id/c"
で下端をボタンCの下端に配置するようにしています。
要素 | 意味 |
---|---|
android:layout_above | 指定したidのViewの上に配置します |
android:layout_alignBaseline | 指定したidのViewのベースラインにあわせて配置します |
android:layout_alignBottom | 指定したidのViewの下端にあわせて配置します |
android:layout_alignLeft | 指定したidのViewの左端にあわせて配置します |
android:layout_alignParentBottom | 親となるViewの下端にあわせて配置します |
android:layout_alignParentLeft | 親となるViewの左端にあわせて配置します |
android:layout_alignParentRight | 親となるViewの右端にあわせて配置します |
android:layout_alignParentTop | 親となるViewの上端にあわせて配置します |
android:layout_alignRight | 指定したidのViewの右端にあわせて配置します |
android:layout_alignTop | 指定したidのViewの上端にあわせて配置します |
android:layout_below | 指定したidのViewの下に配置します |
android:layout_centerHorizontal | 親となるViewの横方向の中央に配置します |
android:layout_centerInParent | 親となるViewの中央に配置します |
android:layout_centerVertical | 親となるViewの縦方向の中央に配置します |
android:layout_toLeftOf | 指定したidのViewの左に配置します |
android:layout_toRightOf | 指定したidのViewの右に配置します |
FrameLayout
FrameLayoutはViewを重ねて配置するのに使用します。
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/FrameLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<!-- 赤 -->
<ImageView
android:layout_width="200dp"
android:layout_height="200dp"
android:background="#FF0000" />
<!-- 緑 -->
<ImageView
android:layout_width="190dp"
android:layout_height="190dp"
android:background="#00FF00" />
<!-- 青 -->
<ImageView
android:layout_width="180dp"
android:layout_height="180dp"
android:background="#0000FF" />
</FrameLayout>
FrameLayout
内の上から順にViewが配置されます。
上記の場合は、赤のImageView
の上に緑のImageView
が配置され、その上に青のImageView
が配置されています。
ScrollView
ScrollViewは画面にレイアウトが収まらない場合、収まらない分をスクロールして表示するための使用します。
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ScrollView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hello_world"
android:textSize="30dp" />
・・・
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hello_world"
android:textSize="30dp" />
</LinearLayout>
</ScrollView>
ScrollView
が持つルートとなるViewは1つでなければなりません。
上記サンプルの場合、複数のTextView
をLinearLayout
でまとめ、LinearLayout
をルートとしています。
ScrollView
の直下にTextView
を複数配置するということはできません。
実習
実習プロジェクトを開き、以下の項目に取り組んでください。
レイアウトの参考として、スクリーンショットと同じようなレイアウトになるようにします。
詳細は、各レイアウトファイルの中に記述されています。
実習プロジェクトの開き方
- 実習プロジェクトを開くにはまず、Android Training資料を手元にダウンロードしてください。
- 次にAndroid Studioを起動し、”Quick Start”メニューの”Open an existing Android Studio project”を選択します。
- プロジェクト選択画面で、1の手順でダウンロードしたディレクトリ内の
AndroidStudio/build.gradle
を選択してください。 - “Import Project from Gradle”という確認ダイアログが出ますので、”Use default gradle wrapper(recommended)”を選択してください。
- 以上の手順でプロジェクトが開いたら、ウィンドウ左側のツリーから 1-1-LayoutPractice > res > layout 内にある各layoutファイルを選択し、実習に取り組んでください。
実習一覧
- LinearLayoutPractice
- activity_linear_layout1.xmlをこのようなレイアウトに変更してください
- activity_linear_layout2.xmlをこのようなレイアウトに変更してください
- RelativeLayoutPractice
- activity_relative_layout1.xmlをこのようなレイアウトに変更してください
- activity_relative_layout2.xmlをこのようなレイアウトに変更してください
- FrameLayoutPractice
- activity_frame_layout1.xmlをこのようなレイアウトに変更してください
- activity_frame_layout2.xmlをこのようなレイアウトに変更してください
- ScrollViewPractice
- activity_scroll_view.xmlをこのようなレイアウトに変更してください
課題
以下の項目に取り組んでください。
レイアウトの参考として、スクリーンショットと同じようなレイアウトになるようにします。
実習プロジェクトを開くには
詳細は、各レイアウトファイルの中に記述されています。
課題プロジェクトの開き方
- 実習プロジェクトの開き方4までは同じです
- 以上の手順でプロジェクトが開いたら、ウィンドウ左側のツリーから 1-1-LayoutAssignment > res > layout 以下の各layout.xml を選択し、課題に取り組んでください。
課題一覧
- activity_assignment1.xml は、下記の画像のようなレイアウトになっています。このレイアウトを元に、自由にレイアウトを編集してください。
- activity_assignment2.xml で、
layout_weight
がネストしているので、LinearLayout
をRelativeLayout
に置き換かえてネストを解消してください。layout_weight
のネストは、パフォーマンスに悪影響を及ぼします。- スクリーンショット
- activity_assignment3.xml で下記の画像のようなレイアウトを作成してください
- activity_assignment4.xml を変更して、下記の画像のようなレイアウトを作成してください。レイアウトファイル中に、指示と条件、ヒントがあります。
- スクリーンショット
- 3 つ並べるボタンの画像の指定は、それぞれ
android:src="@android:drawable/ic_menu_call"
,android:src="@android:drawable/ic_menu_send"
,android:src="@android:drawable/ic_menu_share"
とします