2012年11月6日火曜日

FrameLayout ウィジェットを重ね合わせて配置する。

FrameLayoutは、後に配置したウィジェットが先に配置したウィジェットの上に重ね合わせて表示される。

透過色を使って背景画像に上書きする形で、 下のレイヤーから上のレイヤーまで何階層かに渡って画像を合成して表示させるのに便利かな。

次の例は、FrameLayoutを使って大きさの異なるボタンを重ね合わせて表示する、xmlレイアウトファイルの例である。

リスト1(main.xml)

01 <?xml version="1.0" encoding="utf-8"?>
02 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
03 android:layout_width="fill_parent"
04 android:layout_height="fill_parent"
05 >
06 <Button
07 android:id="@+id/button1"
08 android:layout_width="400px"
09 android:layout_height="400px"
10 android:text="1"
11 />
12 <Button
13 android:id="@+id/button2"
14 android:layout_width="200px"
15 android:layout_height="200px"
16 android:text="2"
17 />
18 <Button
19 android:id="@+id/button3"
20 android:layout_width="100px"
21 android:layout_height="100px"
22 android:text="3"
23 />
24 </FrameLayout>


FrameLayoutの内部に最初に配置したbutton1ボタンが最背面に、 2つ目に配置したbutton2ボタンがbutton1ボタンの前面に、 最後に配置したbutton3ボタンが更にbutton2ボタンの前面にと、 後に配置したウィジェットほど前面に表示されているのがわかる。


動的にウィジェットの重ね合わせの順番を変更する。


FrameLayoutの表示順は、先に追加されたウィジェットほど下層のレイヤーに表示されるので、 この追加順を変更してやる事で動的にウィジェットの重ね合わせの順番を変更する事ができる。

これには、ViewGroupクラスのremoveViewメソッドとaddViewメソッドを使う。

addViewメソッドは、レイアウトにウィジェットを追加する時におなじみのメソッドであるが、 追加位置を指定するオーバロードされたメソッドも存在する、このメソッドを使う。

表示順(位置)を変更したいウィジェットを、一旦、removeViewメソッドを使ってFrameLayoutから削除した後、 addViewメソッドを使って挿入位置を指定して、再度、削除したウィジェットを追加してやる。


以下は、リスト1のレイアウトファイルの3つのButtonに対して、 Buttonが押下された時に押下されたButtonを最背面に移動させるプログラムの例である。

リスト2(FreamLayut1Activity.java)

01 package gudon.sample.fream_layut1;
02
03 import android.app.Activity;
04 import android.os.Bundle;
05 import android.view.View;
06 import android.view.View.OnClickListener;
07 import android.view.ViewGroup;
08
09 public class FreamLayut1Activity extends Activity implements OnClickListener {
10 @Override
11 public void onCreate(Bundle savedInstanceState) {
12 super.onCreate(savedInstanceState);
13 setContentView(R.layout.main);
14
15 findViewById(R.id.button1).setOnClickListener(this);
16 findViewById(R.id.button2).setOnClickListener(this);
17 findViewById(R.id.button3).setOnClickListener(this);
18 }
19
20 @Override
21 public void onClick(View v) {
22 ViewGroup p=(ViewGroup)v.getParent();
23 p.removeView(v);
24 p.addView(v,0);
25 }
26 }

このプログラムを実行して、Buttonを押下すると、押下されたButtonが最下層(最背面)に移動する。


FrameLayoutとGravity

例えば、以下のようにリスト1を修正して、6行目にGravityの指定行を追加してもbuttonは下方に移動しない。

リスト3(main.xml)

2 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="fill_parent"
4 android:layout_height="fill_parent"
5 android:gravity="bottom"
6 >

しかし、Gravityがまったく使えないのかというと、そうでもない。

FrameLayout内部に配置したウィジェットに対して、個々にlayout_gravity属性を指定すればよい。

例えばリスト1を以下のように修正して、 button2を下方向に,button3を右方向にlayout_gravity属性を指定する。

リスト4(main.xml)

01 <?xml version="1.0" encoding="utf-8"?>
02 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
03 android:layout_width="fill_parent"
04 android:layout_height="fill_parent"
05 >
06 <Button
07 android:id="@+id/button1"
08 android:layout_width="400px"
09 android:layout_height="400px"
10 android:text="1"
11 />
12 <Button
13 android:id="@+id/button2"
14 android:layout_width="200px"
15 android:layout_height="200px"
16 android:text="2"
17 android:layout_gravity="bottom"
18 />
19 <Button
20 android:id="@+id/button3"
21 android:layout_width="100px"
22 android:layout_height="100px"
23 android:text="3"
24 android:layout_gravity="right"
25 />
26 </FrameLayout>

このプログラムを実行すると、意図した方向にbuttonが移動しているのがわかる。

FrameLayoutとマージン
FrameLayoutの内部に配置するウィジェットにマージンを設定する事で、 表示位置が重ならないように位置をずらすことができる。

リスト4のレイアウトファイルを以下のように修正する。

リスト5(main.xml)

01 <?xml version="1.0" encoding="utf-8"?>
02 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
03 android:layout_width="fill_parent"
04 android:layout_height="fill_parent"
05 >
06 <Button
07 android:id="@+id/button1"
08 android:layout_width="400px"
09 android:layout_height="400px"
10 android:text="1"
11 android:layout_gravity="left|top"
12 android:layout_marginLeft="50px"
13 android:layout_marginTop="50px"
14 />
15 <Button
16 android:id="@+id/button2"
17 android:layout_width="200px"
18 android:layout_height="200px"
19 android:text="2"
20 android:layout_gravity="bottom"
21 android:layout_marginLeft="50px"
22 android:layout_marginBottom="50px"
23 />
24 <Button
25 android:id="@+id/button3"
26 android:layout_width="100px"
27 android:layout_height="100px"
28 android:text="3"
29 android:layout_gravity="right"
30 android:layout_marginRight="50px"
31 android:layout_marginTop="50px"
32 />
33 </FrameLayout>

指定したマージンの値が、Buttonの位置に反映されているのがわかる。

ただし、注意すべき点として、FrameLayoutのマージンはlayout_gravityの指定が無いと有効にならないようだ。

layout_gravityがデフォルトではtop|leftで指定されているはずだからと思って、リスト5の11行目のlayout_gravityの指定を削除してしまうと、 button1はマージンで指定された位置に移動しなくなる。


foreground属性とforegroundGravity属性 - 最前面に更に画像を表示


foreground属性を指定して、子ウィジェットの更に前面(最前面)に画像を表示させる事ができる。

また、foregroundGravity属性を指定して、foreground属性に指定した画像のGravityを指定する事ができる。

勘違いしやすい点であるが、foregroundGravity属性は、foregroundに指定した画像に対するGravityの指定であって、 子ウィジェットに対するGravityの指定ではないようなので注意。

リスト5のレイアウトファイルのFrameLayoutの部分を、 以下のように修正して foreground属性とforegroundGravity属性を確認してみる。

リスト6(main.xml)

2 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="fill_parent"
4 android:layout_height="fill_parent"
5 android:foreground="@drawable/icon"
6 android:foregroundGravity="right|center_vertical"
7 >

foreground属性とforegroundGravity属性の指定により、アイコン画像が右側中央に表示されるのがわかる。

ちなみに、foregroundGravity属性はデフォルトでfillとなっており、指定しない場合、アイコン画像は画面一杯に拡大されて表示される。


FrameLayoutをコードで記述


リスト5,6のレイアウトを、レイアウトファイルを使わずにコードを使って記述すると、以下のようになる。

リスト7(FreamLayut2Activity.java)

01 package gudon.sample.fream_layut2;
02
03 import android.app.Activity;
04 import android.os.Bundle;
05 import android.view.Gravity;
06 import android.view.View;
07 import android.view.View.OnClickListener;
08 import android.view.ViewGroup;
09 import android.widget.Button;
10 import android.widget.FrameLayout;
11 import android.widget.FrameLayout.LayoutParams;
12
13 public class FreamLayut2Activity extends Activity implements OnClickListener {
14
15 @Override
16 public void onCreate(Bundle savedInstanceState) {
17 super.onCreate(savedInstanceState);
18
19 FrameLayout layout = new FrameLayout(this);
20 layout.setForeground(getResources().getDrawable(R.drawable.icon));
21 layout.setForegroundGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);
22 setContentView(layout);
23
24 Button button1 = new Button(this);
25 button1.setText("1");
26 LayoutParams layoutParams1 = new LayoutParams(400, 400);
27 layoutParams1.gravity = Gravity.LEFT | Gravity.TOP;
28 layoutParams1.leftMargin = 50;
29 layoutParams1.topMargin = 50;
30 layout.addView(button1, layoutParams1);
31 button1.setOnClickListener(this);
32
33 Button button2 = new Button(this);
34 button2.setText("1");
35 LayoutParams layoutParams2 = new LayoutParams(200, 200);
36 layoutParams2.gravity = Gravity.BOTTOM;
37 layoutParams2.leftMargin = 50;
38 layoutParams2.bottomMargin = 50;
39 layout.addView(button2, layoutParams2);
40 button2.setOnClickListener(this);
41
42 Button button3 = new Button(this);
43 button3.setText("1");
44 LayoutParams layoutParams3 = new LayoutParams(100, 100);
45 layoutParams3.gravity = Gravity.RIGHT;
46 layoutParams3.rightMargin = 50;
47 layoutParams3.topMargin = 50;
48 layout.addView(button3, layoutParams3);
49 button2.setOnClickListener(this);
50 }
51
52 @Override
53 public void onClick(View v) {
54 ViewGroup p = (ViewGroup) v.getParent();
55 p.removeView(v);
56 p.addView(v, 0);
57 }
58 }

FrameLayoutのxml属性については、以下のページが参考になるかも。

* faviconUIコンポーネント/FrameLayout - Android Wiki* <http://wikiwiki.jp/android/?UI%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8%2FFrameLayout>
FrameLayoutのxml属性についてまとめられている。
* faviconUIコンポーネント/FrameLayout.LayoutParams - Android Wiki* <http://wikiwiki.jp/android/?UI%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8%2FFrameLayout.LayoutParams>
FrameLayoutクラスのxml属性についてまとめられている。

0 件のコメント:

コメントを投稿