たぼさんの部屋

いちょぼとのんびり

T014) RelationLayout上で View#ViewGroupを動かす

目的

point

複数のTextView[]

TextView[] textviews = new TextView[index];
for(int i=0;i<textviews.length;i++){
   textviews[i] = new TextView(context);
   //処理
}

View#view#bringToFront()

重ね順を一番上に。

MarginLayoutParams param = (MarginLayoutParams) ViewGroup.getLayoutParams();

ViewGroupの配置プロパティ

MarginLayoutParams params = (MarginLayoutParams) ViewGroup.getLayoutParams();
params.setTopMargin = value;
params.setLeftMargin = value;
params.width = value;
params.height = value;
surface.setLayoutParams(params);

public final float getRawX ()

スクリーンからの絶対座標

public final float getX ()

Viewオブジェクトからの相対距離

f:id:donsuka_kk:20121116042004j:plain

動作

f:id:donsuka_kk:20121116052556p:plainf:id:donsuka_kk:20121116052600p:plain

Main.java

package com.example.t014_layoutparams;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class Main extends Activity {
	Context context;
	RelativeLayout base;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// TODO Auto-generated method stub
		context = getApplicationContext();
		base = new RelativeLayout(context);
		setContentView(base);

		// LinearLayout
		final LinearLayout linear = new LinearLayout(context);
		base.addView(linear);
		linear.setId(1);
		linear.setBackgroundColor(Color.GRAY);
		linear.setOrientation(LinearLayout.VERTICAL);

		MarginLayoutParams linearParams = (MarginLayoutParams) linear
				.getLayoutParams();
		linearParams.leftMargin = 100;
		linearParams.topMargin = 100;
		linearParams.width = 300;
		linearParams.height = 600;
		linear.setLayoutParams(linearParams);
		
		//リニアレイアウトにセットする子ビューの生成
		final TextView tv_0 = new TextView(context);
		//XXX OnClickListenerから参照するためfinal
		tv_0.setText("動かせるメニュー");
		linear.addView(tv_0);
		Button btn = new Button(context);
		btn.setText("座標表示");
		linear.addView(btn);
		//6個のtextViewを生成して追加
		final TextView[] textviews = new TextView[6];
		for(int i=0;i<textviews.length;i++){
			textviews[i] = new TextView(context);
			linear.addView(textviews[i]);
			textviews[i].setText("TextView"+i);
		}
		//btnにOnClickListenerをセット
		btn.setOnClickListener(new OnClickListener(){
			String[] str = {
					"getLeft",
					"getTop",
					"getWidth",
					"getHeight",
					"parent.getLeft",
					"parent.getTop"
			};
			@Override
			public void onClick(View v) {
				LinearLayout parent = (LinearLayout) v.getParent();
				//parent.getLeft();
				Log.v("parent",""+parent.getLeft());
				float[] values ={
						v.getLeft(),
						v.getTop(),
						v.getWidth(),
						v.getHeight(),
						parent.getLeft(),
						parent.getTop()
				};
				// TODO Auto-generated method stub
				for(int i=0;i<textviews.length;i++){
					textviews[i].setText(str[i]+"="+values[i]);
				}
			}
			
		});

		// TextView
		final TextView tv = new TextView(context);
		base.addView(tv);
		tv.setId(2);
		tv.setBackgroundColor(Color.RED);
		MarginLayoutParams tvParams = (MarginLayoutParams) tv.getLayoutParams();
		tvParams.leftMargin = 10;
		// tvParams.width = 100;
		tv.setLayoutParams(tvParams);
		tv.setText("hoge");
		
		// SurfaceView
		final SurfaceView surface = new SurfaceView(context);
		base.addView(surface);
		surface.setId(3);
		MarginLayoutParams surfaceParams = (MarginLayoutParams) surface
				.getLayoutParams();
		surfaceParams.topMargin = 150;
		surfaceParams.leftMargin = 50;
		surfaceParams.width = 100;
		surfaceParams.height = 100;
		surface.setLayoutParams(surfaceParams);

		OnTouchListener listener = new OnTouchListener() {

			private float downX;
			private float downY;

			private int downLeftMargin;
			private int downTopMargin;

			@Override
			public boolean onTouch(View v, MotionEvent event) {

				Log.v("OnTouch", "getId()=" + v.getId());
				Log.v("OnTouch", "getLeft()=" + v.getLeft());
				Log.v("OnTouch","getX()="+event.getX());
				Log.v("OnTouch","getRawX()="+event.getRawX());
				tv.setText("クリックされたIDは" + v.getId());
				//View.view.bringToFront() 重ね順を一番上に。
				v.bringToFront();
				final MarginLayoutParams params = (MarginLayoutParams) v
						.getLayoutParams();
				if (event.getAction() == MotionEvent.ACTION_DOWN) {
					downX = event.getRawX();
					downY = event.getRawY();

					downLeftMargin = params.leftMargin;
					downTopMargin = params.topMargin;

					return true;
				} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
					params.leftMargin = downLeftMargin
							+ (int) (event.getRawX() - downX);
					params.topMargin = downTopMargin
							+ (int) (event.getRawY() - downY);

					v.layout(params.leftMargin, params.topMargin,
							params.leftMargin + v.getWidth(), params.topMargin
									+ v.getHeight());

					return true;
				}

				return false;
			}
		};
		linear.setOnTouchListener(listener);
		tv.setOnTouchListener(listener);
		surface.setOnTouchListener(listener);
	}
}

*1: Viewをタッチすると移動させることができるUIを考えてみる。 ツールボタン的なUIに活用できるかもしれない。 これを実現するためには、サンプルプログラムのように実装したOnTouchListenerを移動させたいViewへセットしておけばよい。 移動対象のViewはRelativeLayoutの子Viewとなっており、タッチイベントでLayoutParamsのtopMarginとleftMarginを書き換えている。 複数のViewに同じリスナを登録すれば、それぞれのViewごとに移動させることができる。

*2: ViewGroupクラスのサブクラスはレイアウトと呼ばれ、以下のようなクラスが存在する。 LinearLayoutクラス FrameLayoutクラス RelativeLayoutクラス TableLayoutクラス それぞれのレイアウトクラスには、その内部にウィジェットを配置するためのクラスとして、 以下のようなViewGroup.LayoutParamsを継承した各レイアウト専用のLayoutParamsクラスが用意されていて、 基本的には、この専用のLayoutParamsクラスを使ってウィジェットを配置する。 LinearLayout.LayoutParamsクラス FrameLayout.LayoutParamsクラス RelativeLayout.LayoutParamsクラス TableLayout.LayoutParamsクラス