Android: ギャラリーのような画像ドラッグ(仮)

コメントにて、Androidに元々入っているギャラリーのような動きをさせるその後はどうなったんだ!?という質問を受けましたので、公開してしまおうと思います。ただ、当然ながらこれは私の独自のやり方なので、はっきりいって正しいかどうかはわかりません。

あと、画像の拡大・縮小にはAnimationを使っております。ドラッグ移動はできますが、ビヨーンといった跳ね返りとかは実装していません(そこまで精神がもたなかった)。やろうと思えばできるんでしょうけどねぇ〜。
イベントはダブルタップとかドラッグとか使うので、OnGestureListenerとかOnDoubleTapListenerは必須。implementsしておいてください。

で、画像の拡大・縮小はそんなに難しくないので、省略するとして(オィ)、問題はドラッグ移動なわけです。
画像のドラッグについては、下のメソッドで動くはず。なんで動くのか?を説明するのは結構難儀ですが。
ちなみに、拡大率は2倍固定です(面積は4倍)。

// private Rect mRect
// private Matrix mMatrix = new Matrix();
// private float[] mValues = new float[9];
private void imageMove(ImageView iv, MotionEvent e) {
	if (e.getHistorySize() > 0) {
		int x = (int) e.getHistoricalX(0) - (int) e.getX();
		int y = (int) e.getHistoricalY(0) - (int) e.getY();
		iv.scrollBy(x, y); // ①

		int new_x = iv.getScrollX();
		int new_y = iv.getScrollY();

		mRect = iv.getDrawable().getBounds();
		mMatrix = iv.getImageMatrix();
		mMatrix.getValues(mValues);

		// ②
		// 画面上の画像の横サイズ
		int iw = (int) ((int) mRect.width() * mValues[Matrix.MSCALE_X]);
		// 画面上の画像の縦サイズ
		int ih = (int) ((int) mRect.height() * mValues[Matrix.MSCALE_Y]);
		// 画像の横サイズの半分
		int iw_harf = iw / 2;
		// 画像の縦サイズの半分
		int ih_harf = ih / 2;
		// 縦方向の黒くなっているところの高さ
		int black_out_w = (iv.getWidth() / 4) - iw_harf;
		// 縦方向の黒くなっているところの高さ
		int black_out_h = (iv.getHeight() / 4) - ih_harf;

		Log.d("imageMove", "new_x=" + Integer.toString(new_x) + ", new_y="
				+ Integer.toString(new_y));
		Log.d("imageMove", "_x=" + Integer.toString(iw) + ", _y="
				+ Integer.toString(ih));
		Log.d("imageMove", "black_out_w=" + Integer.toString(black_out_w)
				+ ", black_out_h=" + Integer.toString(black_out_h));

		// 拡大画像がはみ出ないようにする処理
		if (Math.abs(new_x) > black_out_w || Math.abs(new_y) > black_out_h) {
			// new_x, new_yが0の場合を考慮する必要あり
			if (new_x == 0 && new_y == 0) {
				// 何もしない ③
			} else if (new_x == 0) {
				iv.scrollTo(0, new_y
						/ Math.abs(new_y)
						* (int) Math.min(Math.abs(new_y), Math
								.abs(black_out_h))); // ④
			} else if (new_y == 0) {
				iv.scrollTo(new_x
						/ Math.abs(new_x)
						* (int) Math.min(Math.abs(new_x), Math
								.abs(black_out_w)), 0); // ⑤
			} else {
				iv.scrollTo(new_x
						/ Math.abs(new_x)
						* (int) Math.min(Math.abs(new_x), Math
								.abs(black_out_w)), new_y
						/ Math.abs(new_y)
						* (int) Math.min(Math.abs(new_y), Math
								.abs(black_out_h))); // ⑥
			}
		}
	}
}

では説明しまーす。

まず、①で、普通のドラッグ移動を行います。
ヒストリーが取れるので、前の場所から移動した分だけスクロールするよって処理です。

②で、画像の大きさや画面からはみ出る範囲や背景が黒くなっている部分の大きさを計算・取得します。正直ここが一番面倒というか、わかると簡単なんですが、辿り着くのに数日かかりました。アホです。図にして考えるとやりやすい(手書きでガシガシ書いたので、残ってない…)。

Matrixから画像の拡大率を取ります。これは何故かというと、画面よりもでかい画像を読んだら縮小して表示されるんですが、Rect.width()に本来の画像の横サイズが入っているので、それに拡大率をかけることによって画面内における画像の横幅を取得します。縦幅も同様に。

で、画像が画面とまったく同じ大きさでもない限り、黒抜きにされるから、その黒抜きの幅を取得します。これは表現として合ってないかもしれませんが。

③です。これ以降が、画像どこかしらが画面の端っこにきている場合の処理です。普通の場合はscrollByをしていましたが、それ以外の場合はscrollToで上書きする感じになります。

iv.getScrollX()は、親要素に対してスクロールした量だったかな…。割り算をやるので、0の場合は処理しないように制御しないと、例外が発生してアプリが落ちますので、ご注意を。それらが、③、④、⑤。基本は⑥の処理。

という感じです。すみません、眠い頭で書いてるので、説明がグダグダかもしれませんが、メソッド自体は合ってると思います。(但しアニメーションで画像を2倍にしたときに限る)

以上です。


Android: 組み計算をリリースしました。

Androidアプリの第二弾として、組み計算というアプリをリリースしました。
色々な組み合わせで計算をしたい場合などに使えるようなアプリです。まだちょっと完成度は低いかもしれませんが…(だからバージョン0.1.0です)。

早速、紹介ページを作りました。
サイドバーのアプリのところか、以下のリンクからどうぞ!!

紹介ページはこちらです。


Android: GridView対策!ソフトウェアキーボードを消す

@yanzmさんのブログで紹介されているまんまなんですが、備忘録に書かせてもらいます。

まずは何故、俺がこれを実装する必要があったかの経緯を書きます。
いろいろあって、GridViewで画像の一覧を表示する必要があるのですが、その前のアクティビティでは検索フォームがあり、その検索用アクティビティでソフトウェアキーボードを開いた状態で検索ボタンを押して画像一覧アクティビティに来たら、Out of Memoryでアプリが落ちました。ええ、HT-03Aでです。Desireだと落ちなかったのでわからなかった…。

HT-03Aでもずっとテストしていたのですが、画像一覧アクティビティで画像がたくさん出ても落ちないかどうかのテストはやっていたのですが、面倒だったので検索条件なしでずっと実験していたため、ソフトウェアキーボードを開いた状態で画像GridViewにきたら落ちるなんて夢にも思ってませんでした。

なので、検索ボタンを押したらソフトウェアキーボードを消すようにして実験してみたところ、HT-03Aでもアプリが落ちなくなりました。恐るべし、ソフトウェアキーボード!!

参考にしたyanzmさんのブログ記事は以下のURL。
http://y-anz-m.blogspot.com/2009/12/android.html

// 検索ボタンを押したときのイベント
this.btnSearch.setOnClickListener(new OnClickListener() {
	public void onClick(View v) {
		// キーボードを消す
		InputMethodManager inputMethodManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
		inputMethodManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
		// 次のアクティビティに渡すIntentの呼び出しなど
	}
}

Android: ListView内でEditTextが書けない場合の対処

ListView内にEditTextを入れて、追加ボタンが押される度にEditTextが追加されていくようなものを作っているのですが、いざ文字を書こうとしたところ、入力されない。いや、文字は入力されるんだけど、一文字入ったところでクリアされてしまう…。なんぞ、これ!?というわけでほとほと困り果てていたわけですが、ListView, EditTextでググってみたところ、以下のサイトが見つかりました。

http://stackoverflow.com/questions/2825571/android-edittext-in-listview

これを見る限りでは、AndroidManifest.xmlで、Activityタグ内でandroid:windowSoftInputMode=”adjustPan”を指定しろとあります。これが何を表しているのかがまだイマイチよく分かってないです。

ソフトウェア技術ドキュメントを勝手に翻訳を後で読んでおこうと思いますが、ひとまず上記の指定で、EditTextに入力することができるようになりました!!


新聞: 住宅ローン

土曜日の朝日新聞の一面に住宅ローンについての記事が出ていた。読んでいると、なんだか悲しくなってくるなぁ。それなりの幸せを手に入れるために住宅ローンを組んで家を購入したわけだけれど、会社が倒産して再就職ところ給料が減ってローンが払えなくなり、担保にしていた家が競売にかけられて売られてしまう。また、当然ながら安く売られてしまうので、ローンを完済できるわけもなく、家を失い、ただただローンが数百万円残ったという…。働いてもローンに搾取される人生だけが残るという感じ。

以前は、こういう記事を見ていたら、「本人の勉強不足でこういう事態に陥ったわけだから、自己責任だろ。相手も商売でやってるんだから、ちゃんと計画立てろよ」とか思っていたわけだが、今はちょっと違う。違うといっても、半分はそう思ってるけど。そもそもローンを組んで家を買うことに対しては俺は否定的だし。家は財産だなんて思ってないし。まぁこの辺りの話は「金持ち父さん貧乏父さん」とか読んだらわかる。

つーか、サブプライムローンみたいだよなぁ〜。低所得者に高利で融資して家を買わせる。で、家の価格が上昇している間はそれでいいけれど、バブルが弾けたら利子さえ払うのが苦しくなって家を売りに出されて本人は段ボールハウスに住むみたいな…。全然幸せじゃない。売る側も、買う側も。資本主義の悪い面だけが顔を出しているように思える。

幸せのモノサシが、他人との比較しかできない物ならば、そんなモノサシはへし折ってしまえ!!

いい加減、世間が作り出した理想なんかには影響を受けない生き方を模索するべきですな。人様にすごく迷惑にならない限りは世間体なんてどうでもよく、ほどほどに暮らせていられれば幸せなんじゃないでしょうかね〜。今日食べられるご飯と飲める水があるだけで、相当幸せなこと。相対的貧困を意識し過ぎて、心まで貧困になってはならないと思います。

※相対的貧困・・・世間が作り出した、中流の基準以下の生活による劣等感。

と、ここまで書いて、投稿を終わろうとしたのだけど、よく見たら、なぜ「自己責任」でカタを付けないか?を書くのを忘れそうになっていた。反貧困ネットワークの湯浅 誠さんが出ている番組とかを見ている間に、これは「自己責任」という一言で片付けられる問題ではないなぁと思ったからです。個々が知識武装をしていないと安心して暮らせない世の中ってのも、相当歪んでると思うし…。そもそもそれだと生きるのがしんどいんじゃないかなって…。

何事も自己責任だから、絶対的貧困に陥るのも自己責任っていうのは暴論だなと。

※絶対的貧困・・・今日食べるご飯、水にも困るほどの状態。